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,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
@@ -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. It keeps all the JSON fields returned by Casdoor, so that
21
- # updating an object never clears the fields that the SDK doesn't know about, and the fields added by newer
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[Entity.camelize(field.chomp('='))] = args.first
87
+ self[field.chomp('=').to_sym] = args.first
78
88
  elsif field.end_with?('?') && args.empty?
79
- self[Entity.camelize(field.chomp('?'))] ? true : false
89
+ self[field.chomp('?').to_sym] ? true : false
80
90
  elsif args.empty? && field.match?(/\A[a-z][a-z\d_]*\z/)
81
- self[Entity.camelize(field)]
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) ? Entity.camelize(key) : key.to_s
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
@@ -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
@@ -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' => 'admin')
32
+ end
33
+
34
+ def get_ldap(id)
35
+ get_object('get-ldap', Ldap, 'id' => get_admin_id(id))
36
+ end
37
+
38
+ def add_ldap(ldap)
39
+ modify_object('add-ldap', Ldap, ldap, 'admin')
40
+ end
41
+
42
+ def delete_ldap(ldap)
43
+ modify_object('delete-ldap', Ldap, ldap, 'admin')
44
+ end
45
+
46
+ def update_ldap(ldap)
47
+ modify_object('update-ldap', Ldap, ldap, 'admin')
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
@@ -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