casdoor-ruby-sdk 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +134 -55
- data/lib/casdoor/adapter.rb +48 -0
- data/lib/casdoor/application.rb +48 -0
- data/lib/casdoor/auth.rb +143 -0
- data/lib/casdoor/cert.rb +47 -0
- data/lib/casdoor/email.rb +33 -0
- data/lib/casdoor/enforce.rb +47 -0
- data/lib/casdoor/enforcer.rb +48 -0
- data/lib/casdoor/entity.rb +17 -44
- data/lib/casdoor/global.rb +34 -0
- data/lib/casdoor/group.rb +48 -0
- data/lib/casdoor/invitation.rb +57 -0
- data/lib/casdoor/jwt.rb +75 -0
- data/lib/casdoor/ldap.rb +67 -0
- data/lib/casdoor/logout.rb +41 -0
- data/lib/casdoor/mfa.rb +53 -0
- data/lib/casdoor/model.rb +48 -0
- data/lib/casdoor/notification.rb +29 -0
- data/lib/casdoor/order.rb +59 -0
- data/lib/casdoor/order_pay.rb +40 -0
- data/lib/casdoor/organization.rb +47 -0
- data/lib/casdoor/payment.rb +61 -0
- data/lib/casdoor/permission.rb +57 -0
- data/lib/casdoor/plan.rb +48 -0
- data/lib/casdoor/policy.rb +67 -0
- data/lib/casdoor/pricing.rb +48 -0
- data/lib/casdoor/product.rb +48 -0
- data/lib/casdoor/provider.rb +48 -0
- data/lib/casdoor/record.rb +43 -0
- data/lib/casdoor/resource.rb +75 -0
- data/lib/casdoor/role.rb +52 -0
- data/lib/casdoor/session.rb +53 -0
- data/lib/casdoor/sms.rb +31 -0
- data/lib/casdoor/subscription.rb +48 -0
- data/lib/casdoor/syncer.rb +48 -0
- data/lib/casdoor/token.rb +60 -0
- data/lib/casdoor/transaction.rb +62 -0
- data/lib/casdoor/url.rb +47 -0
- data/lib/casdoor/user.rb +124 -0
- data/lib/casdoor/util.rb +147 -0
- data/lib/casdoor/util_modify.rb +65 -0
- data/lib/casdoor/version.rb +1 -1
- data/lib/casdoor/webhook.rb +48 -0
- data/lib/casdoor.rb +13 -5
- metadata +41 -6
- data/lib/casdoor/api/auth.rb +0 -153
- data/lib/casdoor/api/crud.rb +0 -122
- data/lib/casdoor/api/enforce.rb +0 -44
- data/lib/casdoor/api/users.rb +0 -83
- data/lib/casdoor/client.rb +0 -143
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
# The permission checks, the counterpart of enforce.go of the Go SDK. One of permission_id, model_id, resource_id,
|
|
19
|
+
# enforcer_id ("owner/name") or owner chooses the policies to check, the others are empty strings.
|
|
20
|
+
class Client
|
|
21
|
+
# casbin_request is a Casbin request like ["alice", "data1", "read"]. Returns true if any of the checked
|
|
22
|
+
# permissions allows it.
|
|
23
|
+
def enforce(permission_id, model_id, resource_id, enforcer_id, owner, casbin_request)
|
|
24
|
+
data = do_enforce('enforce', permission_id, model_id, resource_id, enforcer_id, owner, casbin_request)
|
|
25
|
+
raise ApiError, 'invalid data' unless data.is_a?(Array)
|
|
26
|
+
|
|
27
|
+
data.any?(true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# casbin_requests is a list of Casbin requests. Returns the results of each checked permission, like
|
|
31
|
+
# [[true, false]] for two requests checked against one permission.
|
|
32
|
+
def batch_enforce(permission_id, model_id, resource_id, enforcer_id, owner, casbin_requests)
|
|
33
|
+
data = do_enforce('batch-enforce', permission_id, model_id, resource_id, enforcer_id, owner, casbin_requests)
|
|
34
|
+
raise ApiError, 'invalid data' unless data.is_a?(Array) && data.all?(Array)
|
|
35
|
+
|
|
36
|
+
data
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def do_enforce(action, permission_id, model_id, resource_id, enforcer_id, owner, body)
|
|
42
|
+
query = { 'permissionId' => permission_id, 'modelId' => model_id, 'resourceId' => resource_id,
|
|
43
|
+
'enforcerId' => enforcer_id, 'owner' => owner }
|
|
44
|
+
do_post(action, query, body)['data']
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
class Enforcer < Entity; end
|
|
19
|
+
|
|
20
|
+
# The enforcer APIs, the counterpart of enforcer.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_enforcers
|
|
23
|
+
get_objects('get-enforcers', Enforcer, 'owner' => organization_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the objects of the page and the total count. query_map can filter and sort them, e.g.
|
|
27
|
+
# { field: "name", value: "alice", sort_field: "created_time", sort_order: "descend" }
|
|
28
|
+
def get_pagination_enforcers(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-enforcers', Enforcer, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_enforcer(name)
|
|
33
|
+
get_object('get-enforcer', Enforcer, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_enforcer(enforcer)
|
|
37
|
+
modify_object('update-enforcer', Enforcer, enforcer, organization_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_enforcer(enforcer)
|
|
41
|
+
modify_object('add-enforcer', Enforcer, enforcer, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def delete_enforcer(enforcer)
|
|
45
|
+
modify_object('delete-enforcer', Enforcer, enforcer, organization_name)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/casdoor/entity.rb
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
require 'json'
|
|
18
18
|
|
|
19
19
|
module Casdoor
|
|
20
|
-
# An object of Casdoor, like a user or an application
|
|
21
|
-
# updating an object never clears the fields that the SDK doesn't know
|
|
22
|
-
# Casdoor versions work without updating the SDK.
|
|
20
|
+
# An object of Casdoor, like a user or an application, the counterpart of the structs of the Go SDK. It keeps all
|
|
21
|
+
# the JSON fields returned by Casdoor, so that updating an object never clears the fields that the SDK doesn't know
|
|
22
|
+
# about, and the fields added by newer Casdoor versions work without updating the SDK.
|
|
23
23
|
#
|
|
24
24
|
# The fields can be read and written in snake_case, which is converted to the camelCase name used by Casdoor:
|
|
25
25
|
#
|
|
@@ -38,6 +38,11 @@ module Casdoor
|
|
|
38
38
|
key.to_s.gsub(/_([a-z\d])/) { Regexp.last_match(1).upcase }
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# The JSON name of a snake_case field name
|
|
42
|
+
def self.field_key(name)
|
|
43
|
+
camelize(name)
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
def initialize(attributes = {})
|
|
42
47
|
@attributes = {}
|
|
43
48
|
(attributes || {}).each { |key, value| self[key] = value }
|
|
@@ -55,6 +60,11 @@ module Casdoor
|
|
|
55
60
|
@attributes.key?(field_name(key))
|
|
56
61
|
end
|
|
57
62
|
|
|
63
|
+
# "owner/name", the ID of the object in the Casdoor API
|
|
64
|
+
def get_id
|
|
65
|
+
"#{self[:owner]}/#{self[:name]}"
|
|
66
|
+
end
|
|
67
|
+
|
|
58
68
|
def to_h
|
|
59
69
|
@attributes.dup
|
|
60
70
|
end
|
|
@@ -74,11 +84,11 @@ module Casdoor
|
|
|
74
84
|
def method_missing(method_name, *args)
|
|
75
85
|
field = method_name.to_s
|
|
76
86
|
if field.end_with?('=') && args.length == 1
|
|
77
|
-
self[
|
|
87
|
+
self[field.chomp('=').to_sym] = args.first
|
|
78
88
|
elsif field.end_with?('?') && args.empty?
|
|
79
|
-
self[
|
|
89
|
+
self[field.chomp('?').to_sym] ? true : false
|
|
80
90
|
elsif args.empty? && field.match?(/\A[a-z][a-z\d_]*\z/)
|
|
81
|
-
self[
|
|
91
|
+
self[method_name]
|
|
82
92
|
else
|
|
83
93
|
super
|
|
84
94
|
end
|
|
@@ -92,44 +102,7 @@ module Casdoor
|
|
|
92
102
|
|
|
93
103
|
# String keys are the exact names of Casdoor, while Symbol keys are snake_case
|
|
94
104
|
def field_name(key)
|
|
95
|
-
key.is_a?(Symbol) ?
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
class Adapter < Entity; end
|
|
100
|
-
class Application < Entity; end
|
|
101
|
-
class Cert < Entity; end
|
|
102
|
-
class Enforcer < Entity; end
|
|
103
|
-
class Group < Entity; end
|
|
104
|
-
class Invitation < Entity; end
|
|
105
|
-
class Model < Entity; end
|
|
106
|
-
class Order < Entity; end
|
|
107
|
-
class Organization < Entity; end
|
|
108
|
-
class Payment < Entity; end
|
|
109
|
-
class Permission < Entity; end
|
|
110
|
-
class Plan < Entity; end
|
|
111
|
-
class Pricing < Entity; end
|
|
112
|
-
class Product < Entity; end
|
|
113
|
-
class Provider < Entity; end
|
|
114
|
-
class Resource < Entity; end
|
|
115
|
-
class Role < Entity; end
|
|
116
|
-
class Session < Entity; end
|
|
117
|
-
class Subscription < Entity; end
|
|
118
|
-
class Syncer < Entity; end
|
|
119
|
-
class Token < Entity; end
|
|
120
|
-
class Transaction < Entity; end
|
|
121
|
-
class User < Entity; end
|
|
122
|
-
class Webhook < Entity; end
|
|
123
|
-
|
|
124
|
-
# The claims of a JWT token issued by Casdoor: the fields of the user, plus the standard claims like "exp" and "aud"
|
|
125
|
-
class Claims < Entity
|
|
126
|
-
def user
|
|
127
|
-
User.new(to_h)
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
# Casdoor names the claim "tokenType", or "TokenType" for the "JWT-Custom" token format
|
|
131
|
-
def refresh_token?
|
|
132
|
-
(self['tokenType'] || self['TokenType']) == 'refresh-token'
|
|
105
|
+
key.is_a?(Symbol) ? self.class.field_key(key) : key.to_s
|
|
133
106
|
end
|
|
134
107
|
end
|
|
135
108
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
# The counterpart of the *_global.go files of the Go SDK: every public method of Client can also be called on the
|
|
19
|
+
# module, with the global client initialized by Casdoor.init_config:
|
|
20
|
+
#
|
|
21
|
+
# Casdoor.init_config(endpoint, client_id, client_secret, certificate, organization_name, application_name)
|
|
22
|
+
# users = Casdoor.get_users
|
|
23
|
+
def self.global_client
|
|
24
|
+
@global_client or raise Error, 'The global client is not initialized, call Casdoor.init_config first'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
(Client.public_instance_methods(false) - %i[endpoint client_id client_secret certificate organization_name
|
|
28
|
+
application_name access_token custom_headers custom_headers=
|
|
29
|
+
open_timeout open_timeout= read_timeout read_timeout=]).each do |method|
|
|
30
|
+
define_singleton_method(method) do |*args, **kwargs, &block|
|
|
31
|
+
global_client.public_send(method, *args, **kwargs, &block)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
class Group < Entity; end
|
|
19
|
+
|
|
20
|
+
# The group APIs, the counterpart of group.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_groups
|
|
23
|
+
get_objects('get-groups', Group, 'owner' => organization_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the objects of the page and the total count. query_map can filter and sort them, e.g.
|
|
27
|
+
# { field: "name", value: "alice", sort_field: "created_time", sort_order: "descend" }
|
|
28
|
+
def get_pagination_groups(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-groups', Group, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_group(name)
|
|
33
|
+
get_object('get-group', Group, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_group(group)
|
|
37
|
+
modify_object('update-group', Group, group, organization_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_group(group)
|
|
41
|
+
modify_object('add-group', Group, group, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def delete_group(group)
|
|
45
|
+
modify_object('delete-group', Group, group, organization_name)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
class Invitation < Entity; end
|
|
19
|
+
|
|
20
|
+
# The invitation APIs, the counterpart of invitation.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_invitations
|
|
23
|
+
get_objects('get-invitations', Invitation, 'owner' => organization_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the objects of the page and the total count. query_map can filter and sort them, e.g.
|
|
27
|
+
# { field: "name", value: "alice", sort_field: "created_time", sort_order: "descend" }
|
|
28
|
+
def get_pagination_invitations(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-invitations', Invitation, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_invitation(name)
|
|
33
|
+
get_object('get-invitation', Invitation, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The invitation of the code, for the application (in "admin") that the user signs up with
|
|
37
|
+
def get_invitation_info(code, application_name)
|
|
38
|
+
get_object('get-invitation-info', Invitation, 'applicationId' => "admin/#{application_name}", 'code' => code)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def update_invitation(invitation)
|
|
42
|
+
modify_object('update-invitation', Invitation, invitation, organization_name)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def update_invitation_for_columns(invitation, columns)
|
|
46
|
+
modify_object('update-invitation', Invitation, invitation, organization_name, columns)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def add_invitation(invitation)
|
|
50
|
+
modify_object('add-invitation', Invitation, invitation, organization_name)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def delete_invitation(invitation)
|
|
54
|
+
modify_object('delete-invitation', Invitation, invitation, organization_name)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/casdoor/jwt.rb
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require 'jwt'
|
|
18
|
+
require 'openssl'
|
|
19
|
+
|
|
20
|
+
module Casdoor
|
|
21
|
+
# The claims of a JWT token issued by Casdoor: the fields of the user, plus the standard claims like "exp" and "aud"
|
|
22
|
+
class Claims < Entity
|
|
23
|
+
def user
|
|
24
|
+
User.new(to_h)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Casdoor names the claim "tokenType" for the JWT, JWT-Empty and JWT-Standard formats, and "TokenType" for
|
|
28
|
+
# JWT-Custom
|
|
29
|
+
def refresh_token?
|
|
30
|
+
(self['tokenType'] || self['TokenType']) == 'refresh-token'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Verifying the JWT tokens, the counterpart of jwt.go of the Go SDK
|
|
35
|
+
class Client
|
|
36
|
+
JWT_ALGORITHMS = %w[RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512].freeze
|
|
37
|
+
|
|
38
|
+
# Verifies a JWT token (the access token or the ID token) with the certificate of the client, and returns its
|
|
39
|
+
# claims. The token must not be expired, and must be issued to this application: pass audience: to check a
|
|
40
|
+
# different audience (e.g. the resource of RFC 8707), or audience: false to skip the check.
|
|
41
|
+
#
|
|
42
|
+
# claims = client.parse_jwt_token(token["access_token"])
|
|
43
|
+
# claims.name # => "alice"
|
|
44
|
+
# claims.owner # => "casbin"
|
|
45
|
+
# claims.user # => Casdoor::User
|
|
46
|
+
def parse_jwt_token(token, audience: nil)
|
|
47
|
+
# The expiration and the "not before" time are verified by default
|
|
48
|
+
payload, = JWT.decode(token, jwt_public_key, true, algorithms: JWT_ALGORITHMS)
|
|
49
|
+
check_audience(payload['aud'], audience) unless audience == false
|
|
50
|
+
Claims.new(payload)
|
|
51
|
+
rescue JWT::DecodeError => e
|
|
52
|
+
raise InvalidTokenError, e.message
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def jwt_public_key
|
|
58
|
+
pem = certificate.to_s
|
|
59
|
+
raise Error, 'The certificate of the client is required to parse JWT tokens' if pem.strip.empty?
|
|
60
|
+
|
|
61
|
+
pem.include?('CERTIFICATE') ? OpenSSL::X509::Certificate.new(pem).public_key : OpenSSL::PKey.read(pem)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Casdoor issues the tokens to the client ID, or to "<client ID>-org-<organization>" for shared applications
|
|
65
|
+
def check_audience(aud, audience)
|
|
66
|
+
auds = Array(aud)
|
|
67
|
+
valid = if audience
|
|
68
|
+
auds.include?(audience)
|
|
69
|
+
else
|
|
70
|
+
auds.any? { |item| item == client_id || item.to_s.start_with?("#{client_id}-org-") }
|
|
71
|
+
end
|
|
72
|
+
raise InvalidTokenError, "The token is issued to #{auds.inspect}, not this application" unless valid
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/casdoor/ldap.rb
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
# An LDAP server of an organization. Unlike the other objects, it's identified by "owner/id" instead of
|
|
19
|
+
# "owner/name".
|
|
20
|
+
class Ldap < Entity
|
|
21
|
+
def get_id
|
|
22
|
+
"#{self[:owner]}/#{self[:id]}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class LdapUser < Entity; end
|
|
27
|
+
|
|
28
|
+
# The LDAP APIs, the counterpart of ldap.go of the Go SDK
|
|
29
|
+
class Client
|
|
30
|
+
def get_ldaps
|
|
31
|
+
get_objects('get-ldaps', Ldap, 'owner' => organization_name)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get_ldap(id)
|
|
35
|
+
get_object('get-ldap', Ldap, 'id' => get_id(id))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def add_ldap(ldap)
|
|
39
|
+
modify_object('add-ldap', Ldap, ldap, organization_name)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def delete_ldap(ldap)
|
|
43
|
+
modify_object('delete-ldap', Ldap, ldap, organization_name)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update_ldap(ldap)
|
|
47
|
+
modify_object('update-ldap', Ldap, ldap, organization_name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The users in the LDAP server. Returns a hash like {"users" => [LdapUser], "existUuids" => [...]}.
|
|
51
|
+
def get_ldap_users(id)
|
|
52
|
+
data = do_get_bytes(get_url('get-ldap-users', 'id' => get_id(id))) || {}
|
|
53
|
+
data.merge('users' => (data['users'] || []).map { |user| LdapUser.new(user) })
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Imports the LDAP users into Casdoor. Returns a hash like {"exist" => [LdapUser], "failed" => [LdapUser]}.
|
|
57
|
+
def sync_ldap_users(id, users)
|
|
58
|
+
data = do_post('sync-ldap-users', { 'id' => get_id(id) }, users.map { |user| to_entity(LdapUser, user) })['data']
|
|
59
|
+
(data || {}).to_h { |key, value| [key, (value || []).map { |user| LdapUser.new(user) }] }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Imports all the users of the LDAP server into Casdoor
|
|
63
|
+
def sync_ldap_users_from_server(id)
|
|
64
|
+
sync_ldap_users(id, get_ldap_users(id)['users'])
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
# Signing users out, the counterpart of logout.go of the Go SDK
|
|
19
|
+
class Client
|
|
20
|
+
# Signs the user out of all their sessions, and expires their tokens
|
|
21
|
+
def logout(access_token)
|
|
22
|
+
sso_logout(access_token, true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Signs the user out of only the session of the access token
|
|
26
|
+
def logout_current_session(access_token)
|
|
27
|
+
sso_logout(access_token, false)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# The "/api/sso-logout" API identifies the user by their own access token, so the Bearer token is used instead of
|
|
33
|
+
# the application's Basic Auth
|
|
34
|
+
def sso_logout(access_token, logout_all)
|
|
35
|
+
raise ArgumentError, 'logout() error: the access_token should not be empty' if access_token.to_s.empty?
|
|
36
|
+
|
|
37
|
+
with_access_token(access_token).do_post('sso-logout', { 'logoutAll' => logout_all.to_s }, nil, true)
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/casdoor/mfa.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
# Setting up the multi-factor authentication of a user, the counterpart of mfa.go of the Go SDK. mfa_type is
|
|
19
|
+
# "app" (TOTP), "sms" or "email". The responses are the hashes of Casdoor, like
|
|
20
|
+
# {"status" => "ok", "msg" => "", "data" => ...}.
|
|
21
|
+
class Client
|
|
22
|
+
# Starts setting up the MFA. For "app", the "data" has the "secret", the "url" of the QR code and the
|
|
23
|
+
# "recoveryCodes".
|
|
24
|
+
def initiate(owner, mfa_type, name)
|
|
25
|
+
do_post('mfa/setup/initiate', nil, { 'owner' => owner, 'mfaType' => mfa_type, 'name' => name }, true)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Verifies the passcode of the MFA being set up
|
|
29
|
+
def verify(owner, mfa_type, name, secret, passcode)
|
|
30
|
+
form = { 'owner' => owner, 'mfaType' => mfa_type, 'name' => name, 'secret' => secret, 'passcode' => passcode }
|
|
31
|
+
do_post('mfa/setup/verify', nil, form, true)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Enables the MFA after it's verified
|
|
35
|
+
def enable(owner, mfa_type, name, secret, recovery_code)
|
|
36
|
+
form = { 'owner' => owner, 'mfaType' => mfa_type, 'name' => name, 'secret' => secret,
|
|
37
|
+
'recoveryCodes' => recovery_code }
|
|
38
|
+
do_post('mfa/setup/enable', nil, form.reject { |_, value| value.to_s.empty? }, true)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def set_preferred(owner, mfa_type, name, secret)
|
|
42
|
+
form = { 'owner' => owner, 'mfaType' => mfa_type, 'name' => name, 'secret' => secret }
|
|
43
|
+
do_post('set-preferred-mfa', nil, form.reject { |_, value| value.to_s.empty? }, true)
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Disables all the MFA of the user
|
|
48
|
+
def delete(owner, name)
|
|
49
|
+
do_post('delete-mfa', { 'owner' => owner, 'name' => name }, nil)
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
class Model < Entity; end
|
|
19
|
+
|
|
20
|
+
# The model APIs, the counterpart of model.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_models
|
|
23
|
+
get_objects('get-models', Model, 'owner' => organization_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the objects of the page and the total count. query_map can filter and sort them, e.g.
|
|
27
|
+
# { field: "name", value: "alice", sort_field: "created_time", sort_order: "descend" }
|
|
28
|
+
def get_pagination_models(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-models', Model, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_model(name)
|
|
33
|
+
get_object('get-model', Model, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_model(model)
|
|
37
|
+
modify_object('update-model', Model, model, organization_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_model(model)
|
|
41
|
+
modify_object('add-model', Model, model, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def delete_model(model)
|
|
45
|
+
modify_object('delete-model', Model, model, organization_name)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module Casdoor
|
|
18
|
+
# Sending notifications with the notification provider of the application, the counterpart of notification.go of
|
|
19
|
+
# the Go SDK
|
|
20
|
+
class Client
|
|
21
|
+
# recipient can be empty for the providers that send to a fixed channel
|
|
22
|
+
def send_notification(content, recipient = '')
|
|
23
|
+
form = { 'content' => content }
|
|
24
|
+
form['recipient'] = recipient unless recipient.to_s.empty?
|
|
25
|
+
do_post('send-notification', nil, form)
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|