descope 1.0.7 → 1.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +51 -12
- data/.github/workflows/publish-gem.yaml +6 -33
- data/.github/workflows/release-please.yaml +36 -0
- data/.gitignore +3 -2
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +31 -0
- data/Gemfile +7 -6
- data/Gemfile.lock +46 -45
- data/README.md +244 -1
- data/examples/ruby-on-rails-api/descope/package-lock.json +16 -10
- data/examples/ruby-on-rails-api/descope/yarn.lock +3 -3
- data/lib/descope/api/v1/auth/enchantedlink.rb +76 -9
- data/lib/descope/api/v1/management/access_key.rb +8 -7
- data/lib/descope/api/v1/management/analytics.rb +62 -0
- data/lib/descope/api/v1/management/audit.rb +2 -2
- data/lib/descope/api/v1/management/authz.rb +15 -15
- data/lib/descope/api/v1/management/common.rb +76 -0
- data/lib/descope/api/v1/management/descoper.rb +45 -0
- data/lib/descope/api/v1/management/engine.rb +44 -0
- data/lib/descope/api/v1/management/fga.rb +64 -0
- data/lib/descope/api/v1/management/flow.rb +5 -5
- data/lib/descope/api/v1/management/group.rb +42 -0
- data/lib/descope/api/v1/management/jwt_template.rb +49 -0
- data/lib/descope/api/v1/management/lists.rb +96 -0
- data/lib/descope/api/v1/management/management_key.rb +54 -0
- data/lib/descope/api/v1/management/outbound_app.rb +112 -0
- data/lib/descope/api/v1/management/password.rb +2 -2
- data/lib/descope/api/v1/management/permission.rb +4 -4
- data/lib/descope/api/v1/management/project.rb +5 -5
- data/lib/descope/api/v1/management/role.rb +5 -5
- data/lib/descope/api/v1/management/scim.rb +14 -14
- data/lib/descope/api/v1/management/scope_claim_mapping.rb +34 -0
- data/lib/descope/api/v1/management/sso_application.rb +7 -7
- data/lib/descope/api/v1/management/sso_settings.rb +5 -5
- data/lib/descope/api/v1/management/tenant.rb +8 -6
- data/lib/descope/api/v1/management/third_party_application.rb +190 -0
- data/lib/descope/api/v1/management/user.rb +36 -36
- data/lib/descope/api/v1/management.rb +22 -0
- data/lib/descope/http_client.rb +30 -0
- data/lib/descope/mixins/common.rb +1 -0
- data/lib/descope/mixins/http.rb +25 -18
- data/lib/descope/mixins/initializer.rb +23 -11
- data/lib/descope/mixins/requests.rb +24 -0
- data/lib/descope/mixins.rb +2 -1
- data/lib/descope/version.rb +1 -1
- data/spec/integration/lib.descope/api/v1/auth/enchantedlink_spec.rb +19 -21
- data/spec/integration/lib.descope/api/v1/auth/magiclink_spec.rb +5 -1
- data/spec/integration/lib.descope/api/v1/auth/otp_spec.rb +5 -1
- data/spec/integration/lib.descope/api/v1/auth/session_spec.rb +24 -5
- data/spec/integration/lib.descope/api/v1/auth/totp_spec.rb +5 -1
- data/spec/integration/lib.descope/api/v1/management/access_key_spec.rb +10 -2
- data/spec/integration/lib.descope/api/v1/management/authz_spec.rb +26 -5
- data/spec/integration/lib.descope/api/v1/management/permissions_spec.rb +20 -2
- data/spec/integration/lib.descope/api/v1/management/project_spec.rb +16 -2
- data/spec/integration/lib.descope/api/v1/management/roles_spec.rb +114 -36
- data/spec/integration/lib.descope/api/v1/management/user_spec.rb +21 -4
- data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +163 -1
- data/spec/lib.descope/api/v1/management/access_key_spec.rb +7 -7
- data/spec/lib.descope/api/v1/management/analytics_spec.rb +82 -0
- data/spec/lib.descope/api/v1/management/audit_spec.rb +2 -2
- data/spec/lib.descope/api/v1/management/authz_spec.rb +16 -16
- data/spec/lib.descope/api/v1/management/descoper_spec.rb +101 -0
- data/spec/lib.descope/api/v1/management/engine_spec.rb +115 -0
- data/spec/lib.descope/api/v1/management/fga_spec.rb +169 -0
- data/spec/lib.descope/api/v1/management/flow_spec.rb +5 -5
- data/spec/lib.descope/api/v1/management/group_spec.rb +72 -0
- data/spec/lib.descope/api/v1/management/jwt_template_spec.rb +103 -0
- data/spec/lib.descope/api/v1/management/lists_spec.rb +285 -0
- data/spec/lib.descope/api/v1/management/management_key_spec.rb +109 -0
- data/spec/lib.descope/api/v1/management/outbound_app_spec.rb +236 -0
- data/spec/lib.descope/api/v1/management/password_spec.rb +2 -2
- data/spec/lib.descope/api/v1/management/permission_spec.rb +4 -4
- data/spec/lib.descope/api/v1/management/project_spec.rb +4 -4
- data/spec/lib.descope/api/v1/management/role_spec.rb +5 -5
- data/spec/lib.descope/api/v1/management/scim_spec.rb +14 -14
- data/spec/lib.descope/api/v1/management/scope_claim_mapping_spec.rb +59 -0
- data/spec/lib.descope/api/v1/management/sso_application_spec.rb +6 -6
- data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +5 -5
- data/spec/lib.descope/api/v1/management/tenant_spec.rb +6 -6
- data/spec/lib.descope/api/v1/management/third_party_application_spec.rb +171 -0
- data/spec/lib.descope/api/v1/management/user_spec.rb +36 -36
- data/spec/lib.descope/auth_management_key_spec.rb +151 -0
- data/spec/lib.descope/mixins/http_spec.rb +17 -6
- data/spec/support/client_config.rb +1 -0
- data/spec/support/dummy_class.rb +12 -9
- data/spec/support/utils.rb +15 -0
- metadata +29 -3
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'descope/http_client'
|
|
4
5
|
|
|
5
6
|
module Descope
|
|
6
7
|
module Mixins
|
|
7
8
|
# Helper class for initializing the Descope API
|
|
8
9
|
module Initializer
|
|
9
10
|
attr_accessor :public_keys, :mlock
|
|
11
|
+
attr_reader :base_uri, :headers
|
|
10
12
|
|
|
11
13
|
def initialize(config)
|
|
12
14
|
options = Hash[config.map { |(k, v)| [k.to_sym, v] }]
|
|
@@ -16,8 +18,10 @@ module Descope
|
|
|
16
18
|
@headers['x-descope-project-id'] = @project_id
|
|
17
19
|
@public_key = options[:public_key] || ENV['DESCOPE_PUBLIC_KEY']
|
|
18
20
|
@mlock = Mutex.new
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
@logger = options[:logger] || begin
|
|
22
|
+
log_level = options[:log_level] || ENV['DESCOPE_LOG_LEVEL'] || 'info'
|
|
23
|
+
Descope::Mixins::Logging.logger_for(self.class.name, log_level, @project_id)
|
|
24
|
+
end
|
|
21
25
|
|
|
22
26
|
@logger.debug("Initializing Descope API with project_id: #{@project_id} and base_uri: #{@base_uri}")
|
|
23
27
|
|
|
@@ -31,7 +35,10 @@ module Descope
|
|
|
31
35
|
@skip_verify = options[:skip_verify]
|
|
32
36
|
@secure = !@skip_verify
|
|
33
37
|
@management_key = options[:management_key] || ENV['DESCOPE_MANAGEMENT_KEY']
|
|
34
|
-
|
|
38
|
+
# Sent with every authentication request so that methods whose public access has been
|
|
39
|
+
# disabled can still be used. Never sent on management requests, and can - and probably
|
|
40
|
+
# should - be a different management key than @management_key.
|
|
41
|
+
@auth_management_key = options[:auth_management_key] || ENV['DESCOPE_AUTH_MANAGEMENT_KEY']
|
|
35
42
|
@timeout_seconds = options[:timeout_seconds] || Common::DEFAULT_TIMEOUT_SECONDS
|
|
36
43
|
@jwt_validation_leeway = options[:jwt_validation_leeway] || Common::DEFAULT_JWT_VALIDATION_LEEWAY
|
|
37
44
|
|
|
@@ -58,16 +65,21 @@ module Descope
|
|
|
58
65
|
|
|
59
66
|
end
|
|
60
67
|
|
|
61
|
-
def authorization_header(pswd = nil)
|
|
62
|
-
pswd = @default_pswd if pswd.nil? || pswd.empty?
|
|
63
|
-
bearer = "#{@project_id}:#{pswd}"
|
|
64
|
-
add_headers('Authorization' => "Bearer #{bearer}")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
68
|
def initialize_api(options)
|
|
68
69
|
initialize_v1(options)
|
|
69
|
-
@
|
|
70
|
-
|
|
70
|
+
@auth_http = http_client(@auth_management_key)
|
|
71
|
+
@mgmt_http = http_client(@management_key)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def http_client(key)
|
|
75
|
+
HttpClient.new(
|
|
76
|
+
base_uri: @base_uri,
|
|
77
|
+
project_id: @project_id,
|
|
78
|
+
key: key,
|
|
79
|
+
headers: @headers,
|
|
80
|
+
logger: @logger,
|
|
81
|
+
timeout: @timeout_seconds
|
|
82
|
+
)
|
|
71
83
|
end
|
|
72
84
|
|
|
73
85
|
def initialize_v1(_options)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'descope/mixins/http'
|
|
4
|
+
|
|
5
|
+
module Descope
|
|
6
|
+
module Mixins
|
|
7
|
+
# Routes an API call to the HTTP client that holds the right key: the bare verbs serve the
|
|
8
|
+
# authentication APIs and go out with the auth management key, the mgmt_ prefixed verbs serve
|
|
9
|
+
# the management APIs and go out with the management key.
|
|
10
|
+
module Requests
|
|
11
|
+
attr_reader :auth_http, :mgmt_http
|
|
12
|
+
|
|
13
|
+
Descope::Mixins::HTTP::HTTP_METHODS.each do |method|
|
|
14
|
+
define_method(method) do |*args|
|
|
15
|
+
@auth_http.public_send(method, *args)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
define_method(:"mgmt_#{method}") do |*args|
|
|
19
|
+
@mgmt_http.public_send(method, *args)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/descope/mixins.rb
CHANGED
|
@@ -4,6 +4,7 @@ require 'logger'
|
|
|
4
4
|
require 'jwt'
|
|
5
5
|
require 'descope/mixins/headers'
|
|
6
6
|
require 'descope/mixins/http'
|
|
7
|
+
require 'descope/mixins/requests'
|
|
7
8
|
require 'descope/mixins/initializer'
|
|
8
9
|
require 'descope/mixins/validation'
|
|
9
10
|
require 'descope/mixins/logging'
|
|
@@ -15,7 +16,7 @@ module Descope
|
|
|
15
16
|
module Mixins
|
|
16
17
|
include Descope::Mixins::Common
|
|
17
18
|
include Descope::Mixins::Headers
|
|
18
|
-
include Descope::Mixins::
|
|
19
|
+
include Descope::Mixins::Requests
|
|
19
20
|
include Descope::Mixins::Initializer
|
|
20
21
|
include Descope::Mixins::Logging
|
|
21
22
|
end
|
data/lib/descope/version.rb
CHANGED
|
@@ -3,31 +3,25 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
def poll_for_session(descope_client, pending_ref)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
while !done && i < max_tries
|
|
6
|
+
@client.logger.info('Waiting for session to be created...')
|
|
7
|
+
|
|
8
|
+
SpecUtils.wait_for_condition(max_wait: 60, interval: 3, description: 'enchanted link session') do
|
|
10
9
|
begin
|
|
11
|
-
i += 1
|
|
12
|
-
@client.logger.info('waiting 4 seconds for session to be created...')
|
|
13
|
-
sleep(4)
|
|
14
|
-
print '.'
|
|
15
10
|
@client.logger.info("Getting session for pending_ref: #{pending_ref}...")
|
|
16
11
|
jwt_response = descope_client.enchanted_link_get_session(pending_ref)
|
|
17
|
-
|
|
12
|
+
|
|
13
|
+
if jwt_response
|
|
14
|
+
@client.logger.info("jwt_response: #{jwt_response}")
|
|
15
|
+
refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME]['jwt']
|
|
16
|
+
@client.logger.info("refresh_token: #{refresh_token}")
|
|
17
|
+
return refresh_token
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
false
|
|
18
21
|
rescue Descope::AuthException, Descope::Unauthorized => e
|
|
19
|
-
@client.logger.info("
|
|
20
|
-
|
|
22
|
+
@client.logger.info("Waiting for session, err: #{e}")
|
|
23
|
+
false
|
|
21
24
|
end
|
|
22
|
-
|
|
23
|
-
next unless jwt_response
|
|
24
|
-
|
|
25
|
-
@client.logger.info("jwt_response: #{jwt_response}")
|
|
26
|
-
refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME]['jwt']
|
|
27
|
-
|
|
28
|
-
@client.logger.info("refresh_token: #{refresh_token}")
|
|
29
|
-
done = true
|
|
30
|
-
return refresh_token
|
|
31
25
|
end
|
|
32
26
|
end
|
|
33
27
|
|
|
@@ -62,7 +56,11 @@ describe Descope::Api::V1::Auth::EnchantedLink do
|
|
|
62
56
|
all_users['users'].each do |user|
|
|
63
57
|
if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
|
|
64
58
|
@client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
|
|
65
|
-
|
|
59
|
+
begin
|
|
60
|
+
@client.delete_user(user['loginIds'][0])
|
|
61
|
+
rescue Descope::NotFound => e
|
|
62
|
+
@client.logger.info("User already deleted: #{e.message}")
|
|
63
|
+
end
|
|
66
64
|
end
|
|
67
65
|
end
|
|
68
66
|
end
|
|
@@ -13,7 +13,11 @@ describe Descope::Api::V1::Auth::MagicLink do
|
|
|
13
13
|
all_users['users'].each do |user|
|
|
14
14
|
if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
|
|
15
15
|
@client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
|
|
16
|
-
|
|
16
|
+
begin
|
|
17
|
+
@client.delete_user(user['loginIds'][0])
|
|
18
|
+
rescue Descope::NotFound => e
|
|
19
|
+
@client.logger.info("User already deleted: #{e.message}")
|
|
20
|
+
end
|
|
17
21
|
end
|
|
18
22
|
end
|
|
19
23
|
end
|
|
@@ -21,7 +21,11 @@ describe Descope::Api::V1::Auth::OTP do
|
|
|
21
21
|
all_users['users'].each do |user|
|
|
22
22
|
if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
|
|
23
23
|
@client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
|
|
24
|
-
|
|
24
|
+
begin
|
|
25
|
+
@client.delete_user(user['loginIds'][0])
|
|
26
|
+
rescue Descope::NotFound => e
|
|
27
|
+
@client.logger.info("User already deleted: #{e.message}")
|
|
28
|
+
end
|
|
25
29
|
end
|
|
26
30
|
end
|
|
27
31
|
end
|
|
@@ -5,6 +5,20 @@ require 'spec_helper'
|
|
|
5
5
|
describe Descope::Api::V1::Session do
|
|
6
6
|
before(:all) do
|
|
7
7
|
@client = DescopeClient.new(Configuration.config)
|
|
8
|
+
|
|
9
|
+
# Cleanup any existing test users before starting
|
|
10
|
+
@client.logger.info('Cleaning up any existing test users before starting...')
|
|
11
|
+
all_users = @client.search_all_users
|
|
12
|
+
all_users['users'].each do |user|
|
|
13
|
+
if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
|
|
14
|
+
@client.logger.info("Deleting existing ruby spec test user #{user['loginIds'][0]}")
|
|
15
|
+
begin
|
|
16
|
+
@client.delete_user(user['loginIds'][0])
|
|
17
|
+
rescue Descope::NotFound => e
|
|
18
|
+
@client.logger.info("User already deleted: #{e.message}")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
8
22
|
end
|
|
9
23
|
|
|
10
24
|
after(:all) do
|
|
@@ -13,7 +27,11 @@ describe Descope::Api::V1::Session do
|
|
|
13
27
|
all_users['users'].each do |user|
|
|
14
28
|
if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
|
|
15
29
|
@client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
|
|
16
|
-
|
|
30
|
+
begin
|
|
31
|
+
@client.delete_user(user['loginIds'][0])
|
|
32
|
+
rescue Descope::NotFound => e
|
|
33
|
+
@client.logger.info("User already deleted: #{e.message}")
|
|
34
|
+
end
|
|
17
35
|
end
|
|
18
36
|
end
|
|
19
37
|
end
|
|
@@ -21,9 +39,10 @@ describe Descope::Api::V1::Session do
|
|
|
21
39
|
context 'test session methods' do
|
|
22
40
|
it 'should refresh session with refresh token' do
|
|
23
41
|
@password = SpecUtils.generate_password
|
|
24
|
-
|
|
42
|
+
# Add timestamp to ensure unique login_id across multiple test runs
|
|
43
|
+
user = build(:user, login_id: "session_test_#{Time.now.to_i}_#{SecureRandom.hex(4)}")
|
|
25
44
|
|
|
26
|
-
@client.logger.info(
|
|
45
|
+
@client.logger.info("1. Sign up with password for user: #{user[:login_id]}")
|
|
27
46
|
res = @client.password_sign_up(login_id: user[:login_id], password: @password, user:)
|
|
28
47
|
@client.logger.info("sign up with password res: #{res}")
|
|
29
48
|
original_refresh_token = res[REFRESH_SESSION_TOKEN_NAME]['jwt']
|
|
@@ -32,8 +51,8 @@ describe Descope::Api::V1::Session do
|
|
|
32
51
|
login_res = @client.password_sign_in(login_id: user[:login_id], password: @password)
|
|
33
52
|
@client.logger.info("sign_in res: #{login_res}")
|
|
34
53
|
|
|
35
|
-
@client.logger.info('3.
|
|
36
|
-
sleep(
|
|
54
|
+
@client.logger.info('3. Wait briefly to ensure token timestamps differ')
|
|
55
|
+
sleep(2) # Wait 2 seconds to ensure new token will have different 'iat' timestamp
|
|
37
56
|
|
|
38
57
|
@client.logger.info('4. Refresh session')
|
|
39
58
|
refresh_session_res = @client.refresh_session(refresh_token: login_res[REFRESH_SESSION_TOKEN_NAME]['jwt'])
|
|
@@ -14,7 +14,11 @@ describe Descope::Api::V1::Auth::TOTP do
|
|
|
14
14
|
all_users['users'].each do |user|
|
|
15
15
|
if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
|
|
16
16
|
@client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
|
|
17
|
-
|
|
17
|
+
begin
|
|
18
|
+
@client.delete_user(user['loginIds'][0])
|
|
19
|
+
rescue Descope::NotFound => e
|
|
20
|
+
@client.logger.info("User already deleted: #{e.message}")
|
|
21
|
+
end
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
end
|
|
@@ -30,8 +30,16 @@ describe Descope::Api::V1::Management::AccessKey do
|
|
|
30
30
|
@tenant_id = @client.create_tenant(name: 'some-new-tenant')['id']
|
|
31
31
|
@client.logger.info('creating access key')
|
|
32
32
|
@access_key = @client.create_access_key(name: @key_name, key_tenants: [{ tenant_id: @tenant_id }])
|
|
33
|
-
@client.logger.info("waiting for access key #{@access_key['key']['id']} to be active
|
|
34
|
-
|
|
33
|
+
@client.logger.info("waiting for access key #{@access_key['key']['id']} to be active")
|
|
34
|
+
SpecUtils.wait_for_condition(max_wait: 65, interval: 3, description: 'access key to be active') do
|
|
35
|
+
begin
|
|
36
|
+
key = @client.load_access_key(@access_key['key']['id'])
|
|
37
|
+
key['key']['status'] == 'active'
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
@client.logger.info("Waiting for key activation: #{e.message}")
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
end
|
|
35
43
|
end
|
|
36
44
|
|
|
37
45
|
it 'should create the access key and load it' do
|
|
@@ -12,7 +12,12 @@ describe Descope::Api::V1::Management::Authz do
|
|
|
12
12
|
|
|
13
13
|
context 'authz ops' do
|
|
14
14
|
before(:all) do
|
|
15
|
-
|
|
15
|
+
# Instead of deleting the entire schema, we'll work with it
|
|
16
|
+
# This allows parallel test execution
|
|
17
|
+
# Only delete schema if we're running in isolation
|
|
18
|
+
if ENV['AUTHZ_FULL_TEST'] == 'true'
|
|
19
|
+
@client.authz_delete_schema
|
|
20
|
+
end
|
|
16
21
|
end
|
|
17
22
|
|
|
18
23
|
it 'should create a new schema' do
|
|
@@ -160,13 +165,17 @@ describe Descope::Api::V1::Management::Authz do
|
|
|
160
165
|
end
|
|
161
166
|
|
|
162
167
|
it 'should create a relation between a resource and user' do
|
|
168
|
+
# Use unique resource name to avoid conflicts between parallel tests
|
|
169
|
+
unique_resource = "#{SpecUtils.build_prefix}some-doc"
|
|
170
|
+
unique_user = "#{SpecUtils.build_prefix}user1"
|
|
171
|
+
|
|
163
172
|
@client.authz_create_relations(
|
|
164
173
|
[
|
|
165
174
|
{
|
|
166
|
-
"resource":
|
|
175
|
+
"resource": unique_resource,
|
|
167
176
|
"relationDefinition": 'owner',
|
|
168
177
|
"namespace": 'note',
|
|
169
|
-
"target":
|
|
178
|
+
"target": unique_user
|
|
170
179
|
}
|
|
171
180
|
]
|
|
172
181
|
)
|
|
@@ -176,14 +185,26 @@ describe Descope::Api::V1::Management::Authz do
|
|
|
176
185
|
relations = @client.authz_has_relations?(
|
|
177
186
|
[
|
|
178
187
|
{
|
|
179
|
-
"resource":
|
|
188
|
+
"resource": unique_resource,
|
|
180
189
|
"relationDefinition": 'viewer',
|
|
181
190
|
"namespace": 'note',
|
|
182
|
-
"target":
|
|
191
|
+
"target": unique_user
|
|
183
192
|
}
|
|
184
193
|
]
|
|
185
194
|
)
|
|
186
195
|
expect(relations['relationQueries'][0]['hasRelation']).to be_truthy
|
|
196
|
+
|
|
197
|
+
# Clean up the test relations
|
|
198
|
+
@client.authz_delete_relations(
|
|
199
|
+
[
|
|
200
|
+
{
|
|
201
|
+
"resource": unique_resource,
|
|
202
|
+
"relationDefinition": 'owner',
|
|
203
|
+
"namespace": 'note',
|
|
204
|
+
"target": unique_user
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
)
|
|
187
208
|
end
|
|
188
209
|
end
|
|
189
210
|
end
|
|
@@ -7,16 +7,34 @@ describe Descope::Api::V1::Management::Permission do
|
|
|
7
7
|
raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
|
|
8
8
|
|
|
9
9
|
@client = DescopeClient.new(Configuration.config)
|
|
10
|
+
@test_description = "#{SpecUtils.build_prefix} Ruby SDK"
|
|
11
|
+
|
|
12
|
+
# Cleanup any leftover permissions from previous failed runs
|
|
10
13
|
@client.load_all_permissions['permissions'].each do |perm|
|
|
11
|
-
if perm['description'] ==
|
|
14
|
+
if perm['description'] == @test_description
|
|
12
15
|
puts "Deleting permission: #{perm['name']}"
|
|
13
16
|
@client.delete_permission(perm['name'])
|
|
14
17
|
end
|
|
15
18
|
end
|
|
16
19
|
end
|
|
20
|
+
|
|
21
|
+
after(:all) do
|
|
22
|
+
# Safety cleanup to ensure no test permissions are left behind
|
|
23
|
+
@client.logger.info('Cleaning up test permissions...')
|
|
24
|
+
begin
|
|
25
|
+
@client.load_all_permissions['permissions'].each do |perm|
|
|
26
|
+
if perm['description'] == @test_description
|
|
27
|
+
@client.logger.info("Deleting leftover permission: #{perm['name']}")
|
|
28
|
+
@client.delete_permission(perm['name'])
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
@client.logger.info("Error during permission cleanup: #{e.message}")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
17
35
|
|
|
18
36
|
it 'should create update and delete a permission' do
|
|
19
|
-
@client.create_permission(name: 'test_permission', description:
|
|
37
|
+
@client.create_permission(name: 'test_permission', description: @test_description)
|
|
20
38
|
all_permissions = @client.load_all_permissions['permissions']
|
|
21
39
|
expect(all_permissions.any? { |perm| perm['name'] == 'test_permission' }).to eq(true)
|
|
22
40
|
@client.update_permission(name: 'test_permission', new_name: 'test_permission_2')
|
|
@@ -8,15 +8,29 @@ describe Descope::Api::V1::Management::Project do
|
|
|
8
8
|
|
|
9
9
|
@client = DescopeClient.new(Configuration.config)
|
|
10
10
|
@export_output = @client.export_project
|
|
11
|
+
@original_project_name = nil
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
context 'Test project methods' do
|
|
15
|
+
before(:all) do
|
|
16
|
+
# Get the current project name before we modify it
|
|
17
|
+
# Store it so we can restore it later
|
|
18
|
+
begin
|
|
19
|
+
@original_project_name = @client.export_project['project']['name']
|
|
20
|
+
rescue StandardError
|
|
21
|
+
@original_project_name = 'Ruby-SDK-Prod'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
14
25
|
after(:all) do
|
|
15
|
-
|
|
26
|
+
# Restore the original project name
|
|
27
|
+
@client.rename_project(@original_project_name) if @original_project_name
|
|
16
28
|
end
|
|
17
29
|
|
|
18
30
|
it 'should rename a project' do
|
|
19
|
-
|
|
31
|
+
# Use a unique name based on build prefix to avoid conflicts
|
|
32
|
+
unique_name = "#{SpecUtils.build_prefix}TEST-Ruby-SDK-Prod"
|
|
33
|
+
@client.rename_project(unique_name)
|
|
20
34
|
end
|
|
21
35
|
|
|
22
36
|
it 'should export a project' do
|
|
@@ -7,74 +7,144 @@ describe Descope::Api::V1::Management::Role do
|
|
|
7
7
|
raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
|
|
8
8
|
|
|
9
9
|
@client = DescopeClient.new(Configuration.config)
|
|
10
|
-
@
|
|
11
|
-
@client.logger.info(
|
|
10
|
+
@test_prefix = SpecUtils.build_prefix
|
|
11
|
+
@client.logger.info("Starting cleanup before tests with prefix: #{@test_prefix}...")
|
|
12
|
+
|
|
13
|
+
# Define resource names with unique prefix for parallel execution
|
|
14
|
+
@permission_viewer = "#{@test_prefix}viewer"
|
|
15
|
+
@permission_editor = "#{@test_prefix}editor"
|
|
16
|
+
@permission_admin = "#{@test_prefix}admin"
|
|
17
|
+
@role_viewer = "#{@test_prefix}Ruby-SDK-test-viewer"
|
|
18
|
+
@role_editor = "#{@test_prefix}Ruby-SDK-test-editor"
|
|
19
|
+
@role_admin = "#{@test_prefix}Ruby-SDK-test-admin"
|
|
20
|
+
@tenant_name = "#{@test_prefix}Ruby-SDK-test"
|
|
21
|
+
@description = "#{@test_prefix}Ruby SDK"
|
|
22
|
+
|
|
23
|
+
# Cleanup any leftover resources from previous failed runs
|
|
24
|
+
@client.logger.info('Deleting all permissions for this test run...')
|
|
12
25
|
@client.load_all_permissions['permissions'].each do |perm|
|
|
13
|
-
if perm['description']
|
|
26
|
+
if perm['description'] == @description
|
|
14
27
|
@client.logger.info("Deleting permission: #{perm['name']}")
|
|
15
28
|
@client.delete_permission(perm['name'])
|
|
16
29
|
end
|
|
17
30
|
end
|
|
18
31
|
|
|
19
|
-
@client.logger.info('Deleting all roles for
|
|
32
|
+
@client.logger.info('Deleting all roles for this test run...')
|
|
20
33
|
@client.load_all_roles['roles'].each do |role|
|
|
21
|
-
|
|
22
|
-
if role['description'] == 'Ruby SDK'
|
|
34
|
+
if role['description'] == @description
|
|
23
35
|
@client.logger.info("Deleting role: #{role['name']}")
|
|
24
36
|
@client.delete_role(name: role['name'], tenant_id: role['tenantId'])
|
|
25
37
|
end
|
|
26
38
|
end
|
|
27
39
|
|
|
28
|
-
@client.logger.info('Deleting all tenants for
|
|
29
|
-
@client.search_all_tenants(names: [
|
|
40
|
+
@client.logger.info('Deleting all tenants for this test run...')
|
|
41
|
+
@client.search_all_tenants(names: [@tenant_name])['tenants'].each do |tenant|
|
|
30
42
|
@client.logger.info("Deleting tenant: #{tenant['name']}")
|
|
31
43
|
@client.delete_tenant(tenant['id'])
|
|
32
44
|
end
|
|
33
45
|
@client.logger.info('Cleanup completed. Starting tests...')
|
|
34
46
|
end
|
|
47
|
+
|
|
48
|
+
after(:all) do
|
|
49
|
+
# Cleanup after tests to ensure no resources are left behind
|
|
50
|
+
@client.logger.info('Cleaning up test resources...')
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
@client.delete_permission(@permission_viewer) if defined?(@permission_viewer)
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
@client.logger.info("Permission #{@permission_viewer} already deleted or doesn't exist: #{e.message}")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
begin
|
|
59
|
+
@client.delete_permission(@permission_editor) if defined?(@permission_editor)
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
@client.logger.info("Permission #{@permission_editor} already deleted or doesn't exist: #{e.message}")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
begin
|
|
65
|
+
@client.delete_permission(@permission_admin) if defined?(@permission_admin)
|
|
66
|
+
rescue StandardError => e
|
|
67
|
+
@client.logger.info("Permission #{@permission_admin} already deleted or doesn't exist: #{e.message}")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Delete any roles with our test description
|
|
71
|
+
begin
|
|
72
|
+
@client.load_all_roles['roles'].each do |role|
|
|
73
|
+
if role['description'] == @description
|
|
74
|
+
@client.delete_role(name: role['name'], tenant_id: role['tenantId'])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
rescue StandardError => e
|
|
78
|
+
@client.logger.info("Error cleaning up roles: #{e.message}")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Delete tenant
|
|
82
|
+
begin
|
|
83
|
+
@client.search_all_tenants(names: [@tenant_name])['tenants'].each do |tenant|
|
|
84
|
+
@client.delete_tenant(tenant['id'])
|
|
85
|
+
end
|
|
86
|
+
rescue StandardError => e
|
|
87
|
+
@client.logger.info("Error cleaning up tenant: #{e.message}")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
@client.logger.info('Cleanup completed.')
|
|
91
|
+
end
|
|
35
92
|
|
|
36
93
|
it 'should create update and delete a role' do
|
|
37
94
|
@client.logger.info('Testing role creation, update, deletion and search...')
|
|
38
95
|
|
|
39
96
|
# Create permissions
|
|
40
97
|
@client.logger.info('creating viewer permission for role')
|
|
41
|
-
@client.create_permission(name:
|
|
98
|
+
@client.create_permission(name: @permission_viewer, description: @description)
|
|
42
99
|
|
|
43
100
|
@client.logger.info('creating editor permission for role')
|
|
44
|
-
@client.create_permission(name:
|
|
101
|
+
@client.create_permission(name: @permission_editor, description: @description)
|
|
45
102
|
|
|
46
103
|
@client.logger.info('creating admin permission for role')
|
|
47
|
-
@client.create_permission(name:
|
|
104
|
+
@client.create_permission(name: @permission_admin, description: @description)
|
|
48
105
|
|
|
49
106
|
# Create tenants
|
|
50
|
-
@client.logger.info(
|
|
51
|
-
tenant_id = @client.create_tenant(name:
|
|
107
|
+
@client.logger.info("creating #{@tenant_name} tenant")
|
|
108
|
+
tenant_id = @client.create_tenant(name: @tenant_name)['id']
|
|
109
|
+
@client.logger.info("Created tenant with id: #{tenant_id}")
|
|
110
|
+
|
|
111
|
+
# Wait for tenant to be available (polling, up to 5 seconds)
|
|
112
|
+
timeout = 5.0
|
|
113
|
+
interval = 0.1
|
|
114
|
+
waited = 0.0
|
|
115
|
+
loop do
|
|
116
|
+
tenants = @client.search_all_tenants(names: [@tenant_name])['tenants']
|
|
117
|
+
break if tenants.any? { |t| t['id'] == tenant_id }
|
|
118
|
+
raise "Tenant #{@tenant_name} not available after #{timeout} seconds" if waited >= timeout
|
|
119
|
+
sleep(interval)
|
|
120
|
+
waited += interval
|
|
121
|
+
end
|
|
52
122
|
|
|
53
123
|
# Create roles
|
|
54
|
-
@client.logger.info(
|
|
55
|
-
@client.create_role(name:
|
|
56
|
-
@client.logger.info(
|
|
57
|
-
@client.create_role(name:
|
|
124
|
+
@client.logger.info("creating #{@role_viewer} role")
|
|
125
|
+
@client.create_role(name: @role_viewer, description: @description, permission_names: [@permission_viewer])
|
|
126
|
+
@client.logger.info("creating #{@role_admin} role")
|
|
127
|
+
@client.create_role(name: @role_admin, description: @description, permission_names: [@permission_admin], tenant_id:)
|
|
58
128
|
|
|
59
129
|
# check all roles matching the correct permission
|
|
60
130
|
@client.logger.info('check all roles matching the correct permission (load roles)')
|
|
61
131
|
roles = @client.load_all_roles['roles']
|
|
62
132
|
roles.each do |role|
|
|
63
|
-
expect(role['permissionNames']).to include(
|
|
64
|
-
expect(role['permissionNames']).to include(
|
|
133
|
+
expect(role['permissionNames']).to include(@permission_viewer) if role['name'] == @role_viewer
|
|
134
|
+
expect(role['permissionNames']).to include(@permission_admin) if role['name'] == @role_admin
|
|
65
135
|
end
|
|
66
136
|
|
|
67
137
|
@client.logger.info('updating role')
|
|
68
138
|
@client.update_role(
|
|
69
|
-
name:
|
|
70
|
-
new_name:
|
|
71
|
-
description:
|
|
72
|
-
permission_names: [
|
|
139
|
+
name: @role_viewer,
|
|
140
|
+
new_name: @role_editor,
|
|
141
|
+
description: @description,
|
|
142
|
+
permission_names: [@permission_editor]
|
|
73
143
|
)
|
|
74
144
|
|
|
75
145
|
@client.logger.info('searching for roles by role names...')
|
|
76
|
-
all_roles = @client.search_roles(role_names:
|
|
77
|
-
expected_roles =
|
|
146
|
+
all_roles = @client.search_roles(role_names: [@role_admin, @role_editor])['roles']
|
|
147
|
+
expected_roles = [@role_editor, @role_admin]
|
|
78
148
|
role_count = 0
|
|
79
149
|
expected_roles.each do |expected_role|
|
|
80
150
|
expect(all_roles.map { |role| role['name'] }).to include(expected_role)
|
|
@@ -83,8 +153,8 @@ describe Descope::Api::V1::Management::Role do
|
|
|
83
153
|
expect(role_count).to eq(2)
|
|
84
154
|
|
|
85
155
|
@client.logger.info('searching for roles with role name like...')
|
|
86
|
-
all_roles = @client.search_roles(role_name_like:
|
|
87
|
-
expected_roles =
|
|
156
|
+
all_roles = @client.search_roles(role_name_like: "#{@test_prefix}Ruby-SDK-test")['roles']
|
|
157
|
+
expected_roles = [@role_editor, @role_admin]
|
|
88
158
|
role_count = 0
|
|
89
159
|
expected_roles.each do |expected_role|
|
|
90
160
|
expect(all_roles.map { |role| role['name'] }).to include(expected_role)
|
|
@@ -94,25 +164,33 @@ describe Descope::Api::V1::Management::Role do
|
|
|
94
164
|
expect(role_count).to eq(2)
|
|
95
165
|
|
|
96
166
|
@client.logger.info('searching for roles with permission names...')
|
|
97
|
-
all_roles = @client.search_roles(permission_names:
|
|
98
|
-
expect(all_roles.map { |role| role['name'] }).to include(
|
|
167
|
+
all_roles = @client.search_roles(permission_names: [@permission_admin])['roles']
|
|
168
|
+
expect(all_roles.map { |role| role['name'] }).to include(@role_admin)
|
|
99
169
|
|
|
100
170
|
@client.logger.info('searching for roles with tenant ids...')
|
|
101
|
-
all_roles = @client.search_roles(role_name_like:
|
|
102
|
-
expect(all_roles.map { |role| role['name'] }).to include(
|
|
171
|
+
all_roles = @client.search_roles(role_name_like: "#{@test_prefix}Ruby-SDK-test", tenant_ids: [tenant_id])['roles']
|
|
172
|
+
expect(all_roles.map { |role| role['name'] }).to include(@role_admin)
|
|
103
173
|
|
|
104
174
|
@client.logger.info('deleting permission')
|
|
105
175
|
|
|
106
|
-
@client.delete_permission(
|
|
107
|
-
@client.delete_permission(
|
|
176
|
+
@client.delete_permission(@permission_editor)
|
|
177
|
+
@client.delete_permission(@permission_admin)
|
|
108
178
|
|
|
109
179
|
@client.logger.info('deleting editor role')
|
|
110
|
-
@client.delete_role(name:
|
|
180
|
+
@client.delete_role(name: @role_editor)
|
|
111
181
|
|
|
112
182
|
@client.logger.info('deleting admin role')
|
|
113
|
-
|
|
183
|
+
begin
|
|
184
|
+
@client.delete_role(name: @role_admin, tenant_id:)
|
|
185
|
+
rescue Descope::Unauthorized, Descope::NotFound => e
|
|
186
|
+
@client.logger.info("Admin role already deleted or tenant invalid: #{e.message}")
|
|
187
|
+
end
|
|
114
188
|
|
|
115
189
|
@client.logger.info('deleting tenant')
|
|
116
|
-
|
|
190
|
+
begin
|
|
191
|
+
@client.delete_tenant(tenant_id)
|
|
192
|
+
rescue Descope::NotFound => e
|
|
193
|
+
@client.logger.info("Tenant already deleted: #{e.message}")
|
|
194
|
+
end
|
|
117
195
|
end
|
|
118
196
|
end
|