casdoor-ruby-sdk 1.0.0 → 1.1.0

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +134 -55
  3. data/lib/casdoor/adapter.rb +48 -0
  4. data/lib/casdoor/application.rb +48 -0
  5. data/lib/casdoor/auth.rb +143 -0
  6. data/lib/casdoor/cert.rb +47 -0
  7. data/lib/casdoor/email.rb +33 -0
  8. data/lib/casdoor/enforce.rb +47 -0
  9. data/lib/casdoor/enforcer.rb +48 -0
  10. data/lib/casdoor/entity.rb +17 -44
  11. data/lib/casdoor/global.rb +34 -0
  12. data/lib/casdoor/group.rb +48 -0
  13. data/lib/casdoor/invitation.rb +57 -0
  14. data/lib/casdoor/jwt.rb +75 -0
  15. data/lib/casdoor/ldap.rb +67 -0
  16. data/lib/casdoor/logout.rb +41 -0
  17. data/lib/casdoor/mfa.rb +53 -0
  18. data/lib/casdoor/model.rb +48 -0
  19. data/lib/casdoor/notification.rb +29 -0
  20. data/lib/casdoor/order.rb +59 -0
  21. data/lib/casdoor/order_pay.rb +40 -0
  22. data/lib/casdoor/organization.rb +47 -0
  23. data/lib/casdoor/payment.rb +61 -0
  24. data/lib/casdoor/permission.rb +57 -0
  25. data/lib/casdoor/plan.rb +48 -0
  26. data/lib/casdoor/policy.rb +67 -0
  27. data/lib/casdoor/pricing.rb +48 -0
  28. data/lib/casdoor/product.rb +48 -0
  29. data/lib/casdoor/provider.rb +48 -0
  30. data/lib/casdoor/record.rb +43 -0
  31. data/lib/casdoor/resource.rb +75 -0
  32. data/lib/casdoor/role.rb +52 -0
  33. data/lib/casdoor/session.rb +53 -0
  34. data/lib/casdoor/sms.rb +31 -0
  35. data/lib/casdoor/subscription.rb +48 -0
  36. data/lib/casdoor/syncer.rb +48 -0
  37. data/lib/casdoor/token.rb +60 -0
  38. data/lib/casdoor/transaction.rb +62 -0
  39. data/lib/casdoor/url.rb +47 -0
  40. data/lib/casdoor/user.rb +124 -0
  41. data/lib/casdoor/util.rb +147 -0
  42. data/lib/casdoor/util_modify.rb +65 -0
  43. data/lib/casdoor/version.rb +1 -1
  44. data/lib/casdoor/webhook.rb +48 -0
  45. data/lib/casdoor.rb +13 -5
  46. metadata +41 -6
  47. data/lib/casdoor/api/auth.rb +0 -153
  48. data/lib/casdoor/api/crud.rb +0 -122
  49. data/lib/casdoor/api/enforce.rb +0 -44
  50. data/lib/casdoor/api/users.rb +0 -83
  51. data/lib/casdoor/client.rb +0 -143
@@ -0,0 +1,65 @@
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 helpers shared by the APIs of the objects, the counterpart of util_modify.go of the Go SDK
19
+ class Client
20
+ private
21
+
22
+ def get_objects(action, klass, query_map)
23
+ (do_get_bytes(get_url(action, query_map)) || []).map { |item| klass.new(item) }
24
+ end
25
+
26
+ # Returns the objects of the page and the total count
27
+ def get_pagination_objects(action, klass, owner, page, page_size, query_map)
28
+ query = to_query_map(query_map).merge('owner' => owner, 'p' => page.to_s, 'pageSize' => page_size.to_s)
29
+ response = do_get_response(get_url(action, query))
30
+ [(response['data'] || []).map { |item| klass.new(item) }, response['data2'].to_i]
31
+ end
32
+
33
+ def get_object(action, klass, query_map)
34
+ data = do_get_bytes(get_url(action, query_map))
35
+ data && klass.new(data)
36
+ end
37
+
38
+ # Posts the object to an add/update/delete API, and returns whether the object is affected. The owner of the
39
+ # object defaults to default_owner, and columns limits the updated fields. Most APIs answer "Affected" or
40
+ # "Unaffected", while some (e.g. update-model) answer only "ok" when they succeed.
41
+ def modify_object(action, klass, object, default_owner, columns = nil, query_map = {})
42
+ object = to_entity(klass, object)
43
+ object.owner = default_owner if object.owner.to_s.empty?
44
+
45
+ query = { 'id' => object.get_id }.merge(query_map)
46
+ if columns && !columns.empty?
47
+ query['columns'] = columns.map do |column|
48
+ column.is_a?(Symbol) ? Entity.camelize(column) : column
49
+ end.join(',')
50
+ end
51
+ do_post(action, query, object)['data'] != 'Unaffected'
52
+ end
53
+
54
+ def to_entity(klass, object)
55
+ object.is_a?(Entity) ? object : klass.new(object)
56
+ end
57
+
58
+ # Symbol keys are snake_case, e.g. sort_field: "name", while String keys are the names of Casdoor
59
+ def to_query_map(query_map)
60
+ (query_map || {}).each_with_object({}) do |(key, value), query|
61
+ query[key.is_a?(Symbol) ? Entity.camelize(key) : key.to_s] = value
62
+ end
63
+ end
64
+ end
65
+ end
@@ -16,5 +16,5 @@
16
16
 
17
17
  module Casdoor
18
18
  # Set by semantic-release in CI when a new version is released, see .releaserc.json
19
- VERSION = '1.0.0'
19
+ VERSION = '1.1.0'
20
20
  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 Webhook < Entity; end
19
+
20
+ # The webhook APIs, the counterpart of webhook.go of the Go SDK
21
+ class Client
22
+ def get_webhooks
23
+ get_objects('get-webhooks', Webhook, '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_webhooks(page, page_size, query_map = {})
29
+ get_pagination_objects('get-webhooks', Webhook, organization_name, page, page_size, query_map)
30
+ end
31
+
32
+ def get_webhook(name)
33
+ get_object('get-webhook', Webhook, 'id' => get_id(name))
34
+ end
35
+
36
+ def update_webhook(webhook)
37
+ modify_object('update-webhook', Webhook, webhook, organization_name)
38
+ end
39
+
40
+ def add_webhook(webhook)
41
+ modify_object('add-webhook', Webhook, webhook, organization_name)
42
+ end
43
+
44
+ def delete_webhook(webhook)
45
+ modify_object('delete-webhook', Webhook, webhook, organization_name)
46
+ end
47
+ end
48
+ end
data/lib/casdoor.rb CHANGED
@@ -17,8 +17,16 @@
17
17
  require_relative 'casdoor/version'
18
18
  require_relative 'casdoor/error'
19
19
  require_relative 'casdoor/entity'
20
- require_relative 'casdoor/api/auth'
21
- require_relative 'casdoor/api/crud'
22
- require_relative 'casdoor/api/users'
23
- require_relative 'casdoor/api/enforce'
24
- require_relative 'casdoor/client'
20
+ require_relative 'casdoor/auth'
21
+ require_relative 'casdoor/util'
22
+ require_relative 'casdoor/util_modify'
23
+
24
+ # The files of the APIs, the same as the casdoorsdk package of the Go SDK
25
+ %w[
26
+ adapter application cert email enforce enforcer group invitation jwt ldap logout mfa model notification order
27
+ order_pay organization payment permission plan policy pricing product provider record resource role session sms
28
+ subscription syncer token transaction url user webhook
29
+ ].each { |file| require_relative "casdoor/#{file}" }
30
+
31
+ # Must be the last, it delegates all the methods of Client to the module
32
+ require_relative 'casdoor/global'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: casdoor-ruby-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yang Luo
@@ -42,14 +42,49 @@ files:
42
42
  - README.md
43
43
  - lib/casdoor-ruby-sdk.rb
44
44
  - lib/casdoor.rb
45
- - lib/casdoor/api/auth.rb
46
- - lib/casdoor/api/crud.rb
47
- - lib/casdoor/api/enforce.rb
48
- - lib/casdoor/api/users.rb
49
- - lib/casdoor/client.rb
45
+ - lib/casdoor/adapter.rb
46
+ - lib/casdoor/application.rb
47
+ - lib/casdoor/auth.rb
48
+ - lib/casdoor/cert.rb
49
+ - lib/casdoor/email.rb
50
+ - lib/casdoor/enforce.rb
51
+ - lib/casdoor/enforcer.rb
50
52
  - lib/casdoor/entity.rb
51
53
  - lib/casdoor/error.rb
54
+ - lib/casdoor/global.rb
55
+ - lib/casdoor/group.rb
56
+ - lib/casdoor/invitation.rb
57
+ - lib/casdoor/jwt.rb
58
+ - lib/casdoor/ldap.rb
59
+ - lib/casdoor/logout.rb
60
+ - lib/casdoor/mfa.rb
61
+ - lib/casdoor/model.rb
62
+ - lib/casdoor/notification.rb
63
+ - lib/casdoor/order.rb
64
+ - lib/casdoor/order_pay.rb
65
+ - lib/casdoor/organization.rb
66
+ - lib/casdoor/payment.rb
67
+ - lib/casdoor/permission.rb
68
+ - lib/casdoor/plan.rb
69
+ - lib/casdoor/policy.rb
70
+ - lib/casdoor/pricing.rb
71
+ - lib/casdoor/product.rb
72
+ - lib/casdoor/provider.rb
73
+ - lib/casdoor/record.rb
74
+ - lib/casdoor/resource.rb
75
+ - lib/casdoor/role.rb
76
+ - lib/casdoor/session.rb
77
+ - lib/casdoor/sms.rb
78
+ - lib/casdoor/subscription.rb
79
+ - lib/casdoor/syncer.rb
80
+ - lib/casdoor/token.rb
81
+ - lib/casdoor/transaction.rb
82
+ - lib/casdoor/url.rb
83
+ - lib/casdoor/user.rb
84
+ - lib/casdoor/util.rb
85
+ - lib/casdoor/util_modify.rb
52
86
  - lib/casdoor/version.rb
87
+ - lib/casdoor/webhook.rb
53
88
  homepage: https://github.com/casdoor/casdoor-ruby-sdk
54
89
  licenses:
55
90
  - Apache-2.0
@@ -1,153 +0,0 @@
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
- module Api
22
- # Signing users in with OAuth 2.0 / OIDC, and verifying the JWT tokens issued by Casdoor.
23
- #
24
- # The OAuth tokens are returned as the hashes of the Casdoor token API, e.g.
25
- # {"access_token" => "...", "id_token" => "...", "refresh_token" => "...", "token_type" => "Bearer",
26
- # "expires_in" => 604800, "scope" => "read"}
27
- module Auth
28
- JWT_ALGORITHMS = %w[RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384 PS512].freeze
29
-
30
- # The URL of the sign-in page that the browser is redirected to. After signing in, Casdoor redirects back to
31
- # redirect_uri with "code" and "state" in the query, and the code is exchanged with get_oauth_token.
32
- def get_signin_url(redirect_uri, state: application_name, scope: 'read')
33
- query = { 'client_id' => client_id, 'response_type' => 'code', 'redirect_uri' => redirect_uri,
34
- 'scope' => scope, 'state' => state }
35
- "#{endpoint}/login/oauth/authorize?#{URI.encode_www_form(query)}"
36
- end
37
-
38
- # The URL of the sign-up page. Without redirect_uri, it's the plain sign-up page of the application, otherwise
39
- # the user is signed in and redirected back to redirect_uri like get_signin_url.
40
- def get_signup_url(redirect_uri = nil, state: application_name, scope: 'read')
41
- return "#{endpoint}/signup/#{application_name}" if redirect_uri.nil?
42
-
43
- url = get_signin_url(redirect_uri, state: state, scope: scope)
44
- url.sub('/login/oauth/authorize', '/signup/oauth/authorize')
45
- end
46
-
47
- def get_user_profile_url(user_name, access_token = nil)
48
- url = "#{endpoint}/users/#{organization_name}/#{user_name}"
49
- access_token ? "#{url}?#{URI.encode_www_form('access_token' => access_token)}" : url
50
- end
51
-
52
- def get_my_profile_url(access_token = nil)
53
- url = "#{endpoint}/account"
54
- access_token ? "#{url}?#{URI.encode_www_form('access_token' => access_token)}" : url
55
- end
56
-
57
- # Exchanges the code that Casdoor passed to the redirect URI for the OAuth tokens
58
- def get_oauth_token(code)
59
- request_oauth_token('authorization_code', 'code' => code)
60
- end
61
-
62
- def refresh_oauth_token(refresh_token, scope: nil)
63
- request_oauth_token('refresh_token', 'refresh_token' => refresh_token, 'scope' => scope)
64
- end
65
-
66
- # The "password" grant type, it must be enabled in the "Grant types" of the application in Casdoor.
67
- # username is the user's name in the application's organization, like "alice".
68
- def get_oauth_token_by_password(username, password)
69
- request_oauth_token('password', 'username' => username, 'password' => password)
70
- end
71
-
72
- # A token of the application itself, the "client_credentials" grant type must be enabled in the application
73
- def get_oauth_token_by_client_credentials
74
- request_oauth_token('client_credentials')
75
- end
76
-
77
- # Verifies a JWT token (the access token or the ID token) with the certificate of the client, and returns its
78
- # claims. The token must not be expired, and must be issued to this application: pass audience: to check a
79
- # different audience (e.g. the resource of RFC 8707), or audience: false to skip the check.
80
- #
81
- # claims = client.parse_jwt_token(token["access_token"])
82
- # claims.name # => "alice"
83
- # claims.owner # => "casbin"
84
- # claims.user # => Casdoor::User
85
- def parse_jwt_token(token, audience: nil)
86
- # The expiration and the "not before" time are verified by default
87
- payload, = JWT.decode(token, jwt_public_key, true, algorithms: JWT_ALGORITHMS)
88
- check_audience(payload['aud'], audience) unless audience == false
89
- Claims.new(payload)
90
- rescue JWT::DecodeError => e
91
- raise InvalidTokenError, e.message
92
- end
93
-
94
- # Asks Casdoor whether the token is active, see RFC 7662. Returns a hash like {"active" => true, ...}.
95
- def introspect_token(token, token_type_hint: 'access_token')
96
- request = Net::HTTP::Post.new(get_url('login/oauth/introspect'))
97
- request.set_form_data('token' => token, 'token_type_hint' => token_type_hint)
98
- check_oauth_response(send_request(request))
99
- end
100
-
101
- # Signs the user out of Casdoor, from all their sessions or only the session of the access token
102
- def logout(access_token, all_sessions: true)
103
- with_access_token(access_token).post_form('sso-logout', { 'logoutAll' => all_sessions }, {})
104
- true
105
- end
106
-
107
- private
108
-
109
- def request_oauth_token(grant_type, params = {})
110
- form = { 'grant_type' => grant_type, 'client_id' => client_id, 'client_secret' => client_secret }
111
- form.merge!(params.compact)
112
-
113
- request = Net::HTTP::Post.new(get_url('login/oauth/access_token'))
114
- request.set_form_data(form)
115
- token = check_oauth_response(send_request(request, auth: false))
116
-
117
- # Older Casdoor versions put the error into the access token
118
- if token['access_token'].to_s.start_with?('error:')
119
- raise ApiError, token['access_token'].delete_prefix('error:').strip
120
- end
121
-
122
- token
123
- end
124
-
125
- def check_oauth_response(body)
126
- if body['error']
127
- message = [body['error'], body['error_description']].compact.reject(&:empty?).join(': ')
128
- raise ApiError, message
129
- end
130
-
131
- check_response(body)
132
- end
133
-
134
- def jwt_public_key
135
- pem = certificate.to_s
136
- raise Error, 'The certificate of the client is required to parse JWT tokens' if pem.strip.empty?
137
-
138
- pem.include?('CERTIFICATE') ? OpenSSL::X509::Certificate.new(pem).public_key : OpenSSL::PKey.read(pem)
139
- end
140
-
141
- # Casdoor issues the tokens to the client ID, or to "<client ID>-org-<organization>" for shared applications
142
- def check_audience(aud, audience)
143
- auds = Array(aud)
144
- valid = if audience
145
- auds.include?(audience)
146
- else
147
- auds.any? { |item| item == client_id || item.to_s.start_with?("#{client_id}-org-") }
148
- end
149
- raise InvalidTokenError, "The token is issued to #{auds.inspect}, not this application" unless valid
150
- end
151
- end
152
- end
153
- end
@@ -1,122 +0,0 @@
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
- module Api
19
- # The add/get/update/delete APIs that all the Casdoor objects share. For each object, e.g. the user, it defines:
20
- #
21
- # get_users(**query) # => [User]
22
- # get_pagination_users(page, page_size, **query) # => [[User], total count]
23
- # get_user(name) # => User or nil, name can be "name" or "owner/name"
24
- # add_user(user) # => true if added
25
- # update_user(user, columns: nil) # => true if changed, columns limits the updated fields
26
- # delete_user(user_or_name) # => true if deleted
27
- #
28
- # The objects belong to the client's organization, except the ones in ADMIN_OWNED, which belong to "admin".
29
- # A different owner can be passed with "owner/name", the owner field of the object, or owner: in the query.
30
- # Extra query parameters of the list APIs can be passed in snake_case, e.g. get_users(sort_field: "name").
31
- module Crud
32
- OBJECTS = {
33
- adapter: Adapter,
34
- application: Application,
35
- cert: Cert,
36
- enforcer: Enforcer,
37
- group: Group,
38
- invitation: Invitation,
39
- model: Model,
40
- order: Order,
41
- organization: Organization,
42
- payment: Payment,
43
- permission: Permission,
44
- plan: Plan,
45
- pricing: Pricing,
46
- product: Product,
47
- provider: Provider,
48
- resource: Resource,
49
- role: Role,
50
- subscription: Subscription,
51
- syncer: Syncer,
52
- token: Token,
53
- transaction: Transaction,
54
- user: User,
55
- webhook: Webhook
56
- }.freeze
57
-
58
- ADMIN_OWNED = %i[application organization token].freeze
59
-
60
- OBJECTS.each do |object, klass|
61
- plural = "#{object}s"
62
-
63
- define_method("get_#{plural}") do |**query|
64
- data = get_data("get-#{plural}", list_query(object, query)) || []
65
- data.map { |item| klass.new(item) }
66
- end
67
-
68
- define_method("get_pagination_#{plural}") do |page, page_size, **query|
69
- query = list_query(object, query).merge('p' => page, 'pageSize' => page_size)
70
- response = get_response("get-#{plural}", query)
71
- [(response['data'] || []).map { |item| klass.new(item) }, response['data2'].to_i]
72
- end
73
-
74
- define_method("get_#{object}") do |name|
75
- data = get_data("get-#{object}", 'id' => object_id_of(object, name))
76
- data && klass.new(data)
77
- end
78
-
79
- define_method("add_#{object}") do |entity|
80
- modify_object("add-#{object}", object, entity)
81
- end
82
-
83
- define_method("update_#{object}") do |entity, columns: nil|
84
- modify_object("update-#{object}", object, entity, columns: columns)
85
- end
86
-
87
- # Casdoor deletes an object by the whole object, e.g. an application is only deleted when its organization
88
- # matches too, so the object is fetched first when only its name is given
89
- define_method("delete_#{object}") do |entity|
90
- entity = send("get_#{object}", entity) unless entity.is_a?(Entity)
91
- return false if entity.nil?
92
-
93
- modify_object("delete-#{object}", object, entity)
94
- end
95
- end
96
-
97
- private
98
-
99
- def default_owner(object)
100
- ADMIN_OWNED.include?(object) ? 'admin' : organization_name
101
- end
102
-
103
- def object_id_of(object, name)
104
- name.to_s.include?('/') ? name.to_s : "#{default_owner(object)}/#{name}"
105
- end
106
-
107
- def list_query(object, query)
108
- query = query.each_with_object({}) { |(key, value), hash| hash[Entity.camelize(key)] = value }
109
- { 'owner' => default_owner(object) }.merge(query)
110
- end
111
-
112
- def modify_object(action, object, entity, columns: nil, query: {})
113
- entity = OBJECTS.fetch(object).new(entity) if entity.is_a?(Hash)
114
- entity.owner = default_owner(object) if entity.owner.to_s.empty?
115
-
116
- query = { 'id' => "#{entity.owner}/#{entity.name}" }.merge(query)
117
- query['columns'] = Array(columns).map { |column| Entity.camelize(column) }.join(',') if columns
118
- post_json(action, query, entity)['data'] == 'Affected'
119
- end
120
- end
121
- end
122
- end
@@ -1,44 +0,0 @@
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
- module Api
19
- # The permission checks of Casdoor. Pass one of permission_id, model_id, resource_id, enforcer_id or owner
20
- # ("owner/name" for the IDs) to choose which policies to check against.
21
- module Enforce
22
- # request is a Casbin request like ["alice", "data1", "read"]. Returns true if any of the checked
23
- # permissions allows it.
24
- def enforce(request, permission_id: nil, model_id: nil, resource_id: nil, enforcer_id: nil, owner: nil)
25
- query = enforce_query(permission_id, model_id, resource_id, enforcer_id, owner)
26
- Array(post_json('enforce', query, request)['data']).any?(true)
27
- end
28
-
29
- # requests is a list of Casbin requests. Returns a list of results for each checked permission, like
30
- # [[true, false]] for two requests checked against one permission.
31
- def batch_enforce(requests, permission_id: nil, model_id: nil, resource_id: nil, enforcer_id: nil, owner: nil)
32
- query = enforce_query(permission_id, model_id, resource_id, enforcer_id, owner)
33
- post_json('batch-enforce', query, requests)['data'] || []
34
- end
35
-
36
- private
37
-
38
- def enforce_query(permission_id, model_id, resource_id, enforcer_id, owner)
39
- { 'permissionId' => permission_id, 'modelId' => model_id, 'resourceId' => resource_id,
40
- 'enforcerId' => enforcer_id, 'owner' => owner }
41
- end
42
- end
43
- end
44
- end
@@ -1,83 +0,0 @@
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
- module Api
19
- # The user APIs besides the ones in Crud
20
- module Users
21
- # The user that the client is authenticated as, meant to be used with with_access_token:
22
- #
23
- # user = client.with_access_token(access_token).get_account
24
- def get_account
25
- data = get_data('get-account')
26
- data && User.new(data)
27
- end
28
-
29
- # The users of all the organizations, only allowed for global admins
30
- def get_global_users
31
- (get_data('get-global-users') || []).map { |item| User.new(item) }
32
- end
33
-
34
- def get_sorted_users(sorter, limit)
35
- query = { 'owner' => organization_name, 'sorter' => sorter, 'limit' => limit }
36
- (get_data('get-sorted-users', query) || []).map { |item| User.new(item) }
37
- end
38
-
39
- # is_online: nil counts all the users, true or false counts the online or offline ones
40
- def get_user_count(is_online: nil)
41
- online = { nil => '', true => '1', false => '0' }.fetch(is_online)
42
- query = { 'owner' => organization_name, 'isOnline' => online }
43
- get_data('get-user-count', query).to_i
44
- end
45
-
46
- def get_user_by_email(email)
47
- find_user('email' => email)
48
- end
49
-
50
- def get_user_by_phone(phone)
51
- find_user('phone' => phone)
52
- end
53
-
54
- # user_id is the "id" field of the user (a UUID), not "owner/name"
55
- def get_user_by_user_id(user_id)
56
- find_user('userId' => user_id)
57
- end
58
-
59
- # Sets the user's password. old_password can be empty when an admin sets the password of another user.
60
- def set_password(owner, name, new_password, old_password: '')
61
- form = { 'userOwner' => owner, 'userName' => name, 'oldPassword' => old_password,
62
- 'newPassword' => new_password }
63
- post_form('set-password', {}, form)['status'] == 'ok'
64
- end
65
-
66
- # Checks the password of a user, e.g. User.new(owner: "casbin", name: "alice", password: "123")
67
- def check_user_password(user)
68
- user = User.new(user) if user.is_a?(Hash)
69
- user.owner = organization_name if user.owner.to_s.empty?
70
- post_json('check-user-password', { 'id' => "#{user.owner}/#{user.name}" }, user)['status'] == 'ok'
71
- rescue ApiError
72
- false
73
- end
74
-
75
- private
76
-
77
- def find_user(query)
78
- data = get_data('get-user', { 'owner' => organization_name }.merge(query))
79
- data && User.new(data)
80
- end
81
- end
82
- end
83
- end