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
data/lib/casdoor/role.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
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 Role < Entity; end
|
|
19
|
+
|
|
20
|
+
# The role APIs, the counterpart of role.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_roles
|
|
23
|
+
get_objects('get-roles', Role, '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_roles(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-roles', Role, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_role(name)
|
|
33
|
+
get_object('get-role', Role, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_role(role)
|
|
37
|
+
modify_object('update-role', Role, role, organization_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_role_for_columns(role, columns)
|
|
41
|
+
modify_object('update-role', Role, role, organization_name, columns)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_role(role)
|
|
45
|
+
modify_object('add-role', Role, role, organization_name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def delete_role(role)
|
|
49
|
+
modify_object('delete-role', Role, role, organization_name)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
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
|
+
class Session < Entity; end
|
|
19
|
+
|
|
20
|
+
# The session APIs, the counterpart of session.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_sessions
|
|
23
|
+
get_objects('get-sessions', Session, '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_sessions(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-sessions', Session, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# A session is identified by its user and application
|
|
33
|
+
def get_session(name, application)
|
|
34
|
+
get_object('get-session', Session, 'sessionPkId' => "#{get_id(name)}/#{application}")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def update_session(session)
|
|
38
|
+
modify_object('update-session', Session, session, organization_name)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def update_session_for_columns(session, columns)
|
|
42
|
+
modify_object('update-session', Session, session, organization_name, columns)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def add_session(session)
|
|
46
|
+
modify_object('add-session', Session, session, organization_name)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def delete_session(session)
|
|
50
|
+
modify_object('delete-session', Session, session, organization_name)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/casdoor/sms.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
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 SMS with the SMS provider of the application, the counterpart of sms.go of the Go SDK
|
|
19
|
+
class Client
|
|
20
|
+
def send_sms(content, *receivers)
|
|
21
|
+
do_post('send-sms', nil, { 'content' => content, 'receivers' => receivers.flatten })
|
|
22
|
+
true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Sends with the given SMS provider instead of the application's one
|
|
26
|
+
def send_sms_by_provider(content, provider, *receivers)
|
|
27
|
+
do_post('send-sms', { 'provider' => provider }, { 'content' => content, 'receivers' => receivers.flatten })
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
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 Subscription < Entity; end
|
|
19
|
+
|
|
20
|
+
# The subscription APIs, the counterpart of subscription.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_subscriptions
|
|
23
|
+
get_objects('get-subscriptions', Subscription, '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_subscriptions(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-subscriptions', Subscription, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_subscription(name)
|
|
33
|
+
get_object('get-subscription', Subscription, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_subscription(subscription)
|
|
37
|
+
modify_object('update-subscription', Subscription, subscription, organization_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_subscription(subscription)
|
|
41
|
+
modify_object('add-subscription', Subscription, subscription, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def delete_subscription(subscription)
|
|
45
|
+
modify_object('delete-subscription', Subscription, subscription, organization_name)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
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 Syncer < Entity; end
|
|
19
|
+
|
|
20
|
+
# The syncer APIs, the counterpart of syncer.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_syncers
|
|
23
|
+
get_objects('get-syncers', Syncer, '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_syncers(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-syncers', Syncer, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_syncer(name)
|
|
33
|
+
get_object('get-syncer', Syncer, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_syncer(syncer)
|
|
37
|
+
modify_object('update-syncer', Syncer, syncer, organization_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_syncer(syncer)
|
|
41
|
+
modify_object('add-syncer', Syncer, syncer, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def delete_syncer(syncer)
|
|
45
|
+
modify_object('delete-syncer', Syncer, syncer, organization_name)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
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 Token < Entity; end
|
|
19
|
+
|
|
20
|
+
# The token APIs, the counterpart of token.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_tokens
|
|
23
|
+
get_objects('get-tokens', Token, 'owner' => 'admin')
|
|
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_tokens(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-tokens', Token, 'admin', page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_token(name)
|
|
33
|
+
get_object('get-token', Token, 'id' => get_admin_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_token(token)
|
|
37
|
+
modify_object('update-token', Token, token, 'admin')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_token_for_columns(token, columns)
|
|
41
|
+
modify_object('update-token', Token, token, 'admin', columns)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_token(token)
|
|
45
|
+
modify_object('add-token', Token, token, 'admin')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def delete_token(token)
|
|
49
|
+
modify_object('delete-token', Token, token, 'admin')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Asks Casdoor whether the token is active, see RFC 7662. Returns a hash like
|
|
53
|
+
# {"active" => true, "client_id" => "...", "username" => "alice", "exp" => 1700000000, ...}.
|
|
54
|
+
def introspect_token(token, token_type_hint = 'access_token')
|
|
55
|
+
request = Net::HTTP::Post.new(URI(get_url('login/oauth/introspect')))
|
|
56
|
+
request.set_form_data('token' => token, 'token_type_hint' => token_type_hint)
|
|
57
|
+
check_oauth_response(send_request(request))
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
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 Transaction < Entity; end
|
|
19
|
+
|
|
20
|
+
# The transaction APIs, the counterpart of transaction.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
def get_transactions
|
|
23
|
+
get_objects('get-transactions', Transaction, '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_transactions(page, page_size, query_map = {})
|
|
29
|
+
get_pagination_objects('get-transactions', Transaction, organization_name, page, page_size, query_map)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_transaction(name)
|
|
33
|
+
get_object('get-transaction', Transaction, 'id' => get_id(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def get_user_transactions(user_name)
|
|
37
|
+
get_objects('get-user-transactions', Transaction, 'owner' => organization_name, 'user' => user_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_transaction(transaction)
|
|
41
|
+
modify_object('update-transaction', Transaction, transaction, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns [true, the ID (name) of the new transaction]
|
|
45
|
+
def add_transaction(transaction)
|
|
46
|
+
add_transaction_with_dry_run(transaction, false)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# With dry_run, Casdoor only validates the transaction without saving it
|
|
50
|
+
def add_transaction_with_dry_run(transaction, dry_run)
|
|
51
|
+
transaction = to_entity(Transaction, transaction)
|
|
52
|
+
transaction.owner = organization_name if transaction.owner.to_s.empty?
|
|
53
|
+
query = { 'id' => transaction.get_id }
|
|
54
|
+
query['dryRun'] = '1' if dry_run
|
|
55
|
+
[true, do_post('add-transaction', query, transaction)['data'].to_s]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def delete_transaction(transaction)
|
|
59
|
+
modify_object('delete-transaction', Transaction, transaction, organization_name)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/casdoor/url.rb
ADDED
|
@@ -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 URLs of the Casdoor pages, the counterpart of url.go of the Go SDK
|
|
19
|
+
class Client
|
|
20
|
+
# The sign-up page. With enable_password, it's the plain sign-up page of the application and redirect_uri can be
|
|
21
|
+
# empty; otherwise the user is signed in after signing up and redirected back to redirect_uri like
|
|
22
|
+
# get_signin_url.
|
|
23
|
+
def get_signup_url(enable_password, redirect_uri)
|
|
24
|
+
return "#{endpoint}/signup/#{application_name}" if enable_password
|
|
25
|
+
|
|
26
|
+
get_signin_url(redirect_uri).sub('/login/oauth/authorize', '/signup/oauth/authorize')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The sign-in page that the browser is redirected to. After signing in, Casdoor redirects back to redirect_uri
|
|
30
|
+
# with "code" and "state" in the query, and the code is exchanged with get_oauth_token.
|
|
31
|
+
def get_signin_url(redirect_uri, state: application_name, scope: 'read')
|
|
32
|
+
query = { 'client_id' => client_id, 'response_type' => 'code', 'redirect_uri' => redirect_uri,
|
|
33
|
+
'scope' => scope, 'state' => state }
|
|
34
|
+
"#{endpoint}/login/oauth/authorize?#{URI.encode_www_form(query)}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def get_user_profile_url(user_name, access_token = '')
|
|
38
|
+
url = "#{endpoint}/users/#{organization_name}/#{user_name}"
|
|
39
|
+
access_token.to_s.empty? ? url : "#{url}?#{URI.encode_www_form('access_token' => access_token)}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_my_profile_url(access_token = '')
|
|
43
|
+
url = "#{endpoint}/account"
|
|
44
|
+
access_token.to_s.empty? ? url : "#{url}?#{URI.encode_www_form('access_token' => access_token)}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/casdoor/user.rb
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
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 User < Entity; end
|
|
19
|
+
|
|
20
|
+
# The user APIs, the counterpart of user.go of the Go SDK
|
|
21
|
+
class Client
|
|
22
|
+
# The users of all the organizations, only allowed for global admins
|
|
23
|
+
def get_global_users
|
|
24
|
+
get_objects('get-global-users', User, nil)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def get_users
|
|
28
|
+
get_objects('get-users', User, 'owner' => organization_name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# sorter is the DB column to sort by, e.g. "created_time"
|
|
32
|
+
def get_sorted_users(sorter, limit)
|
|
33
|
+
get_objects('get-sorted-users', User, 'owner' => organization_name, 'sorter' => sorter, 'limit' => limit.to_s)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns the users of the page and the total count. query_map can filter and sort them, e.g.
|
|
37
|
+
# { field: "name", value: "alice", sort_field: "created_time", sort_order: "descend" }
|
|
38
|
+
def get_pagination_users(page, page_size, query_map = {})
|
|
39
|
+
get_pagination_objects('get-users', User, organization_name, page, page_size, query_map)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# is_online is "" to count all the users, "1" or true for the online ones, "0" or false for the offline ones
|
|
43
|
+
def get_user_count(is_online = '')
|
|
44
|
+
is_online = { true => '1', false => '0', nil => '' }.fetch(is_online, is_online)
|
|
45
|
+
do_get_bytes(get_url('get-user-count', 'owner' => organization_name, 'isOnline' => is_online)).to_i
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def get_user(name)
|
|
49
|
+
get_object('get-user', User, 'id' => get_id(name))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The user that the client is authenticated as. It's meant to be used with a client returned by
|
|
53
|
+
# with_access_token, so that the user of an access token can be retrieved:
|
|
54
|
+
#
|
|
55
|
+
# user = client.with_access_token(token["access_token"]).get_account
|
|
56
|
+
def get_account
|
|
57
|
+
get_object('get-account', User, nil)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_user_by_email(email)
|
|
61
|
+
get_object('get-user', User, 'owner' => organization_name, 'email' => email)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def get_user_by_phone(phone)
|
|
65
|
+
get_object('get-user', User, 'owner' => organization_name, 'phone' => phone)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# user_id is the "id" field of the user (a UUID), not "owner/name"
|
|
69
|
+
def get_user_by_user_id(user_id)
|
|
70
|
+
get_object('get-user', User, 'owner' => organization_name, 'userId' => user_id)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# old_password isn't required when an admin sets the password of another user, pass an empty string then
|
|
74
|
+
def set_password(owner, name, old_password, new_password)
|
|
75
|
+
form = { 'userOwner' => owner, 'userName' => name, 'oldPassword' => old_password, 'newPassword' => new_password }
|
|
76
|
+
do_post('set-password', nil, form, true)['status'] == 'ok'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Updates the user of the ID ("owner/name"), e.g. to rename the user
|
|
80
|
+
def update_user_by_id(id, user)
|
|
81
|
+
modify_user_by_id('update-user', id, user)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Updates the user of the user ID (the "id" field of the user)
|
|
85
|
+
def update_user_by_user_id(owner, user_id, user)
|
|
86
|
+
user = to_entity(User, user)
|
|
87
|
+
do_post('update-user', { 'owner' => owner, 'userId' => user_id }, user)['data'] == 'Affected'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def update_user(user)
|
|
91
|
+
modify_object('update-user', User, user, organization_name)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def update_user_for_columns(user, columns)
|
|
95
|
+
modify_object('update-user', User, user, organization_name, columns)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def add_user(user)
|
|
99
|
+
modify_object('add-user', User, user, organization_name)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def delete_user(user)
|
|
103
|
+
modify_object('delete-user', User, user, organization_name)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Checks the password of a user, e.g. User.new(owner: "casbin", name: "alice", password: "123").
|
|
107
|
+
# Returns false when the password is wrong.
|
|
108
|
+
def check_user_password(user)
|
|
109
|
+
user = to_entity(User, user)
|
|
110
|
+
user.owner = organization_name if user.owner.to_s.empty?
|
|
111
|
+
do_post('check-user-password', { 'id' => user.get_id }, user)['status'] == 'ok'
|
|
112
|
+
rescue ApiError
|
|
113
|
+
false
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
def modify_user_by_id(action, id, user)
|
|
119
|
+
user = to_entity(User, user)
|
|
120
|
+
user.owner = organization_name if user.owner.to_s.empty?
|
|
121
|
+
do_post(action, { 'id' => id }, user)['data'] == 'Affected'
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
data/lib/casdoor/util.rb
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
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 'json'
|
|
18
|
+
require 'net/http'
|
|
19
|
+
require 'securerandom'
|
|
20
|
+
require 'time'
|
|
21
|
+
require 'uri'
|
|
22
|
+
|
|
23
|
+
module Casdoor
|
|
24
|
+
# The current time in RFC 3339, the format of the "createdTime" of Casdoor
|
|
25
|
+
def self.get_current_time
|
|
26
|
+
Time.now.iso8601
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The HTTP layer, the counterpart of util.go of the Go SDK. Any Casdoor API can be called with these methods,
|
|
30
|
+
# authenticated as the client. The responses of Casdoor are hashes like
|
|
31
|
+
# {"status" => "ok", "msg" => "", "data" => ..., "data2" => ...}.
|
|
32
|
+
class Client
|
|
33
|
+
def get_url(action, query_map = nil)
|
|
34
|
+
query = (query_map || {}).compact.transform_keys(&:to_s)
|
|
35
|
+
url = "#{endpoint}/api/#{action}"
|
|
36
|
+
query.empty? ? url : "#{url}?#{URI.encode_www_form(query)}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# "owner/name" with the client's organization as the owner, unless name is already "owner/name"
|
|
40
|
+
def get_id(name)
|
|
41
|
+
get_owner_id(name, organization_name)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Calls a GET API, and returns the whole response
|
|
45
|
+
def do_get_response(url)
|
|
46
|
+
body = parse_body(perform(Net::HTTP::Get.new(URI(url))))
|
|
47
|
+
raise ApiError, body['msg'].to_s unless body.is_a?(Hash) && body['status'] == 'ok'
|
|
48
|
+
|
|
49
|
+
body
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Calls a GET API, and returns the "data" of the response
|
|
53
|
+
def do_get_bytes(url)
|
|
54
|
+
do_get_response(url)['data']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Calls a GET API, and returns the raw body of the response
|
|
58
|
+
def do_get_bytes_raw(url)
|
|
59
|
+
response = perform(Net::HTTP::Get.new(URI(url)))
|
|
60
|
+
check_response(parse_body(response)) if response['Content-Type'].to_s.include?('json')
|
|
61
|
+
response.body
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Calls a POST API, and returns the whole response. The body is posted as JSON, or as form fields when is_form,
|
|
65
|
+
# or as a file named "file" when is_file.
|
|
66
|
+
def do_post(action, query_map, post_body, is_form = false, is_file = false)
|
|
67
|
+
request = Net::HTTP::Post.new(URI(get_url(action, query_map)))
|
|
68
|
+
if is_file
|
|
69
|
+
request.set_form([['file', post_body.to_s, { filename: 'file' }]], 'multipart/form-data')
|
|
70
|
+
elsif is_form
|
|
71
|
+
request.set_form((post_body || {}).to_h.transform_keys(&:to_s).transform_values(&:to_s), 'multipart/form-data')
|
|
72
|
+
else
|
|
73
|
+
request['Content-Type'] = 'application/json'
|
|
74
|
+
request.body = post_body.nil? || post_body.is_a?(String) ? post_body.to_s : post_body.to_json
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
body = parse_body(perform(request))
|
|
78
|
+
raise ApiError, body['msg'].to_s unless body.is_a?(Hash) && body['status'] == 'ok'
|
|
79
|
+
|
|
80
|
+
body
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Calls a POST API, and returns the raw body of the response
|
|
84
|
+
def do_post_bytes_raw(url, content_type, body)
|
|
85
|
+
request = Net::HTTP::Post.new(URI(url))
|
|
86
|
+
request['Content-Type'] = content_type.to_s.empty? ? 'text/plain;charset=UTF-8' : content_type
|
|
87
|
+
request.body = body
|
|
88
|
+
perform(request).body
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def get_owner_id(name, default_owner)
|
|
94
|
+
name.to_s.include?('/') ? name.to_s : "#{default_owner}/#{name}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def get_admin_id(name)
|
|
98
|
+
get_owner_id(name, 'admin')
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def set_auth_header(request)
|
|
102
|
+
if access_token
|
|
103
|
+
request['Authorization'] = "Bearer #{access_token}"
|
|
104
|
+
else
|
|
105
|
+
request.basic_auth(client_id.to_s, client_secret.to_s)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def perform(request, auth: true)
|
|
110
|
+
set_auth_header(request) if auth
|
|
111
|
+
request['Accept'] ||= 'application/json'
|
|
112
|
+
custom_headers.each { |key, value| request[key] = value }
|
|
113
|
+
|
|
114
|
+
uri = request.uri
|
|
115
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', open_timeout: open_timeout,
|
|
116
|
+
read_timeout: read_timeout) do |http|
|
|
117
|
+
http.request(request)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Parses the JSON body. Errors of the HTTP layer are raised, while the {"status": "error"} responses are left to
|
|
122
|
+
# the caller.
|
|
123
|
+
def parse_body(response)
|
|
124
|
+
begin
|
|
125
|
+
body = JSON.parse(response.body.to_s)
|
|
126
|
+
rescue JSON::ParserError
|
|
127
|
+
raise HttpError.new(response.code.to_i, response.body)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
return body if response.is_a?(Net::HTTPSuccess)
|
|
131
|
+
# Casdoor answers some errors with a non-2xx status and a JSON body that explains the error
|
|
132
|
+
return body if body.is_a?(Hash) && (body['status'] == 'error' || body['error'])
|
|
133
|
+
|
|
134
|
+
raise HttpError.new(response.code.to_i, response.body)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def send_request(request, auth: true)
|
|
138
|
+
parse_body(perform(request, auth: auth))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def check_response(body)
|
|
142
|
+
raise ApiError, body['msg'].to_s if body.is_a?(Hash) && body['status'] == 'error'
|
|
143
|
+
|
|
144
|
+
body
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|