descope 1.0.6 → 1.0.7

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +2 -2
  3. data/.github/workflows/publish-gem.yaml +10 -3
  4. data/.gitignore +2 -0
  5. data/.ruby-version +1 -1
  6. data/Gemfile +7 -7
  7. data/Gemfile.lock +68 -55
  8. data/README.md +159 -51
  9. data/examples/ruby-on-rails-api/descope/Gemfile +8 -8
  10. data/examples/ruby-on-rails-api/descope/Gemfile.lock +1 -1
  11. data/examples/ruby-on-rails-api/descope/package-lock.json +187 -131
  12. data/examples/ruby-on-rails-api/descope/package.json +1 -1
  13. data/examples/ruby-on-rails-api/descope/yarn.lock +182 -84
  14. data/lib/descope/api/v1/auth/enchantedlink.rb +3 -1
  15. data/lib/descope/api/v1/auth/magiclink.rb +3 -1
  16. data/lib/descope/api/v1/auth/otp.rb +3 -1
  17. data/lib/descope/api/v1/auth/password.rb +6 -2
  18. data/lib/descope/api/v1/auth/totp.rb +3 -1
  19. data/lib/descope/api/v1/auth.rb +47 -12
  20. data/lib/descope/api/v1/management/common.rb +20 -5
  21. data/lib/descope/api/v1/management/sso_application.rb +236 -0
  22. data/lib/descope/api/v1/management/sso_settings.rb +2 -24
  23. data/lib/descope/api/v1/management/user.rb +151 -13
  24. data/lib/descope/api/v1/management.rb +2 -0
  25. data/lib/descope/api/v1/session.rb +37 -4
  26. data/lib/descope/mixins/common.rb +1 -0
  27. data/lib/descope/mixins/http.rb +60 -9
  28. data/lib/descope/mixins/initializer.rb +2 -1
  29. data/lib/descope/mixins/logging.rb +12 -4
  30. data/lib/descope/version.rb +1 -1
  31. data/spec/descope/api/v1/auth_spec.rb +29 -0
  32. data/spec/descope/api/v1/auth_token_extraction_spec.rb +126 -0
  33. data/spec/descope/api/v1/session_refresh_spec.rb +98 -0
  34. data/spec/factories/user.rb +1 -1
  35. data/spec/integration/lib.descope/api/v1/auth/enchantedlink_spec.rb +1 -1
  36. data/spec/integration/lib.descope/api/v1/auth/magiclink_spec.rb +1 -1
  37. data/spec/integration/lib.descope/api/v1/auth/otp_spec.rb +1 -1
  38. data/spec/integration/lib.descope/api/v1/auth/session_spec.rb +49 -0
  39. data/spec/integration/lib.descope/api/v1/auth/totp_spec.rb +1 -1
  40. data/spec/integration/lib.descope/api/v1/management/access_key_spec.rb +3 -0
  41. data/spec/integration/lib.descope/api/v1/management/audit_spec.rb +5 -3
  42. data/spec/integration/lib.descope/api/v1/management/authz_spec.rb +2 -0
  43. data/spec/integration/lib.descope/api/v1/management/flow_spec.rb +3 -1
  44. data/spec/integration/lib.descope/api/v1/management/permissions_spec.rb +4 -2
  45. data/spec/integration/lib.descope/api/v1/management/project_spec.rb +2 -0
  46. data/spec/integration/lib.descope/api/v1/management/roles_spec.rb +2 -0
  47. data/spec/integration/lib.descope/api/v1/management/user_spec.rb +55 -6
  48. data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +11 -2
  49. data/spec/lib.descope/api/v1/auth/password_spec.rb +10 -1
  50. data/spec/lib.descope/api/v1/auth_spec.rb +167 -5
  51. data/spec/lib.descope/api/v1/cookie_domain_fix_integration_spec.rb +245 -0
  52. data/spec/lib.descope/api/v1/management/sso_application_spec.rb +217 -0
  53. data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +2 -2
  54. data/spec/lib.descope/api/v1/management/user_spec.rb +134 -46
  55. data/spec/lib.descope/api/v1/session_spec.rb +119 -6
  56. data/spec/lib.descope/mixins/http_spec.rb +218 -0
  57. data/spec/support/client_config.rb +0 -1
  58. data/spec/support/utils.rb +6 -0
  59. metadata +13 -8
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require "addressable/uri"
2
+ require 'descope/mixins/common'
3
+ require 'addressable/uri'
3
4
  require 'retryable'
4
5
  require_relative '../exception'
5
6
 
@@ -7,6 +8,7 @@ module Descope
7
8
  module Mixins
8
9
  # HTTP-related methods
9
10
  module HTTP
11
+ include Descope::Mixins::Common
10
12
  attr_accessor :headers, :base_uri, :timeout, :retry_count
11
13
 
12
14
  DEFAULT_RETRIES = 3
@@ -44,13 +46,61 @@ module Descope
44
46
  }
45
47
  end
46
48
 
47
- def safe_parse_json(body)
49
+ def safe_parse_json(body, cookies: {}, headers: {})
48
50
  @logger.debug "response => #{JSON.parse(body.to_s)}"
49
- JSON.parse(body.to_s)
51
+ res = JSON.parse(body.to_s)
52
+
53
+ # Handle DS and DSR cookies in response.
54
+ # First check RestClient's cookies (works for same-domain cookies)
55
+ extracted_cookies = {}
56
+ if cookies.key?(SESSION_COOKIE_NAME)
57
+ extracted_cookies[SESSION_COOKIE_NAME] = cookies[SESSION_COOKIE_NAME]
58
+ end
59
+ if cookies.key?(REFRESH_SESSION_COOKIE_NAME)
60
+ extracted_cookies[REFRESH_SESSION_COOKIE_NAME] = cookies[REFRESH_SESSION_COOKIE_NAME]
61
+ end
62
+
63
+ # If no cookies found via RestClient, parse Set-Cookie headers directly
64
+ # This handles custom domain cookies that RestClient filters out
65
+ if extracted_cookies.empty? && headers.respond_to?(:[])
66
+ set_cookie_headers = headers['set-cookie'] || headers['Set-Cookie'] || []
67
+ set_cookie_headers = [set_cookie_headers] unless set_cookie_headers.is_a?(Array)
68
+
69
+ set_cookie_headers.each do |cookie_header|
70
+ next unless cookie_header.is_a?(String)
71
+
72
+ # Parse DS cookie (session token)
73
+ if cookie_header.include?("#{SESSION_COOKIE_NAME}=")
74
+ cookie_value = parse_cookie_value(cookie_header, SESSION_COOKIE_NAME)
75
+ extracted_cookies[SESSION_COOKIE_NAME] = cookie_value if cookie_value
76
+ end
77
+
78
+ # Parse DSR cookie (refresh token)
79
+ if cookie_header.include?("#{REFRESH_SESSION_COOKIE_NAME}=")
80
+ cookie_value = parse_cookie_value(cookie_header, REFRESH_SESSION_COOKIE_NAME)
81
+ extracted_cookies[REFRESH_SESSION_COOKIE_NAME] = cookie_value if cookie_value
82
+ end
83
+ end
84
+ end
85
+
86
+ # Add extracted cookies to response if any were found
87
+ unless extracted_cookies.empty?
88
+ res['cookies'] = extracted_cookies
89
+ end
90
+
91
+ res
50
92
  rescue JSON::ParserError
51
93
  body
52
94
  end
53
95
 
96
+ def parse_cookie_value(cookie_header, cookie_name)
97
+ # Extract cookie value from Set-Cookie header
98
+ # Format: "cookieName=cookieValue; attribute1=value1; attribute2=value2"
99
+ # Only match valid cookie value characters (RFC 6265: exclude whitespace, semicolon, comma)
100
+ match = cookie_header.match(/#{Regexp.escape(cookie_name)}=([^;]+)/)
101
+ match ? match[1].strip : nil
102
+ end
103
+
54
104
  def encode_uri(uri)
55
105
  encoded_uri = base_uri ? Addressable::URI.parse(uri).normalize : Addressable::URI.escape(uri)
56
106
  @logger.debug "will call #{url(encoded_uri)}"
@@ -94,11 +144,12 @@ module Descope
94
144
  call(method, encode_uri(uri), timeout, @headers, body.to_json)
95
145
  end
96
146
 
97
- raise Descope::Unsupported.new("No response from server", code: 400) unless result && result.respond_to?(:code)
147
+ raise Descope::Unsupported.new('No response from server', code: 400) unless result.respond_to?(:code)
98
148
 
99
149
  @logger.info("API Request: [#{method}] #{uri} - Response Code: #{result.code}")
150
+
100
151
  case result.code
101
- when 200...226 then safe_parse_json(result.body)
152
+ when 200...226 then safe_parse_json(result.body, cookies: result.cookies, headers: result.headers)
102
153
  when 400 then raise Descope::BadRequest.new(result.body, code: result.code, headers: result.headers)
103
154
  when 401 then raise Descope::Unauthorized.new(result.body, code: result.code, headers: result.headers)
104
155
  when 403 then raise Descope::AccessDenied.new(result.body, code: result.code, headers: result.headers)
@@ -113,10 +164,10 @@ module Descope
113
164
 
114
165
  def call(method, url, timeout, headers, body = nil)
115
166
  RestClient::Request.execute(
116
- method:,
117
- url:,
118
- timeout:,
119
- headers:,
167
+ method: method,
168
+ url: url,
169
+ timeout: timeout,
170
+ headers: headers,
120
171
  payload: body
121
172
  )
122
173
  rescue RestClient::Exception => e
@@ -13,10 +13,11 @@ module Descope
13
13
  @base_uri = base_url(options)
14
14
  @headers = client_headers
15
15
  @project_id = options[:project_id] || ENV['DESCOPE_PROJECT_ID'] || ''
16
+ @headers['x-descope-project-id'] = @project_id
16
17
  @public_key = options[:public_key] || ENV['DESCOPE_PUBLIC_KEY']
17
18
  @mlock = Mutex.new
18
19
  log_level = options[:log_level] || ENV['DESCOPE_LOG_LEVEL'] || 'info'
19
- @logger ||= Descope::Mixins::Logging.logger_for(self.class.name, log_level)
20
+ @logger ||= Descope::Mixins::Logging.logger_for(self.class.name, log_level, @project_id)
20
21
 
21
22
  @logger.debug("Initializing Descope API with project_id: #{@project_id} and base_uri: #{@base_uri}")
22
23
 
@@ -7,21 +7,29 @@ module Descope
7
7
 
8
8
  def logger
9
9
  # This is the magical bit that gets mixed into the other modules
10
- @logger ||= Logging.logger_for(self.class.name, 'info')
10
+ @logger ||= Logging.logger_for(self.class.name, 'info', @project_id)
11
11
  end
12
12
 
13
13
  # Use a hash class-ivar to cache a unique Logger per class:
14
14
  @loggers = {}
15
15
 
16
16
  class << self
17
- def logger_for(classname, level)
18
- @loggers[classname] ||= configure_logger_for(classname, level)
17
+ def logger_for(classname, level, project_id = nil)
18
+ key = "#{classname}-#{project_id}"
19
+ @loggers[key] ||= configure_logger_for(classname, level, project_id)
19
20
  end
20
21
 
21
- def configure_logger_for(classname, level = 'info')
22
+ def configure_logger_for(classname, level = 'info', project_id = nil)
22
23
  logger = Logger.new(STDOUT)
23
24
  logger.level = Object.const_get("Logger::#{level.upcase}")
24
25
  logger.progname = classname
26
+
27
+ # Adding Custom Formatter for Project ID
28
+ logger.formatter = proc do |severity, datetime, progname, msg|
29
+ project_info = project_id ? "PRID: #{project_id}" : ""
30
+ "[#{datetime}] #{severity} #{project_info} #{progname}: #{msg}\n"
31
+ end
32
+
25
33
  logger
26
34
  end
27
35
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  # Current version of gem
4
4
  module Descope
5
- VERSION = '1.0.6'
5
+ VERSION = '1.0.7'
6
6
  SDK_VERSION = '1.0.0'
7
7
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Descope::Api::V1::Auth do
6
+ let(:client) { Class.new { include Descope::Api::V1::Auth }.new }
7
+ let(:valid_token) { 'valid_token' }
8
+ let(:refresh_token) { 'refresh_token' }
9
+
10
+ describe 'token extraction with empty strings' do
11
+ it 'handles empty string tokens correctly' do
12
+ response_body = {
13
+ 'sessionJwt' => '',
14
+ 'refreshJwt' => '',
15
+ 'cookies' => {
16
+ 'DS' => valid_token,
17
+ 'DSR' => refresh_token
18
+ }
19
+ }
20
+
21
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
22
+
23
+ result = client.generate_jwt_response(response_body: response_body)
24
+
25
+ expect(result).to have_key('sessionToken')
26
+ expect(result).to have_key('refreshSessionToken')
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Descope::Api::V1::Auth do
6
+ let(:client) { Descope::Client.new(project_id: 'test_project_id', management_key: 'test_key') }
7
+ let(:valid_session_token) { 'valid.session.token' }
8
+ let(:valid_refresh_token) { 'valid.refresh.token' }
9
+
10
+ describe '#generate_auth_info (private method)' do
11
+ context 'session token extraction' do
12
+ it 'extracts session token from sessionJwt field' do
13
+ response_body = {
14
+ 'sessionJwt' => valid_session_token,
15
+ 'refreshJwt' => valid_refresh_token,
16
+ 'cookies' => {}
17
+ }
18
+
19
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
20
+
21
+ result = client.send(:generate_auth_info, response_body, nil, true, nil)
22
+
23
+ expect(result).to have_key('sessionToken')
24
+ end
25
+
26
+ it 'extracts session token from cookies with DS name' do
27
+ response_body = {
28
+ 'sessionJwt' => '',
29
+ 'refreshJwt' => valid_refresh_token,
30
+ 'cookies' => {
31
+ 'DS' => valid_session_token
32
+ }
33
+ }
34
+
35
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
36
+
37
+ result = client.send(:generate_auth_info, response_body, nil, true, nil)
38
+
39
+ expect(result).to have_key('sessionToken')
40
+ end
41
+
42
+ it 'extracts session token from cookies with SESSION_COOKIE_NAME' do
43
+ stub_const('Descope::Api::V1::Auth::SESSION_COOKIE_NAME', 'CustomSession')
44
+
45
+ response_body = {
46
+ 'sessionJwt' => '',
47
+ 'refreshJwt' => valid_refresh_token,
48
+ 'cookies' => {
49
+ 'CustomSession' => valid_session_token
50
+ }
51
+ }
52
+
53
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
54
+
55
+ result = client.send(:generate_auth_info, response_body, nil, true, nil)
56
+
57
+ expect(result).to have_key('sessionToken')
58
+ end
59
+ end
60
+
61
+ context 'refresh token extraction' do
62
+ it 'extracts refresh token from refreshJwt field' do
63
+ response_body = {
64
+ 'sessionJwt' => valid_session_token,
65
+ 'refreshJwt' => valid_refresh_token,
66
+ 'cookies' => {}
67
+ }
68
+
69
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
70
+
71
+ result = client.send(:generate_auth_info, response_body, nil, true, nil)
72
+
73
+ expect(result).to have_key('refreshSessionToken')
74
+ end
75
+
76
+ it 'extracts refresh token from cookies when refreshJwt is empty' do
77
+ stub_const('Descope::Api::V1::Auth::REFRESH_SESSION_COOKIE_NAME', 'DSR')
78
+
79
+ response_body = {
80
+ 'sessionJwt' => valid_session_token,
81
+ 'refreshJwt' => '',
82
+ 'cookies' => {
83
+ 'DSR' => valid_refresh_token
84
+ }
85
+ }
86
+
87
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
88
+
89
+ result = client.send(:generate_auth_info, response_body, nil, true, nil)
90
+
91
+ expect(result).to have_key('refreshSessionToken')
92
+ end
93
+
94
+ it 'falls back to parameter refresh token when cookie has empty string' do
95
+ response_body = {
96
+ 'sessionJwt' => valid_session_token,
97
+ 'refreshJwt' => '',
98
+ 'cookies' => {
99
+ 'DSR' => ''
100
+ }
101
+ }
102
+
103
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
104
+
105
+ result = client.send(:generate_auth_info, response_body, valid_refresh_token, true, nil)
106
+
107
+ expect(result).to have_key('refreshSessionToken')
108
+ expect(client).to have_received(:validate_token).with(valid_refresh_token, nil)
109
+ end
110
+
111
+ it 'raises error when no refresh token is available' do
112
+ response_body = {
113
+ 'sessionJwt' => valid_session_token,
114
+ 'refreshJwt' => '',
115
+ 'cookies' => {}
116
+ }
117
+
118
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123', 'iss' => 'test_project_id' })
119
+
120
+ expect {
121
+ client.send(:generate_auth_info, response_body, nil, true, nil)
122
+ }.to raise_error(Descope::AuthException, /Could not find refresh token/)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Descope::Api::V1::Session do
6
+ let(:client) { Descope::Client.new(project_id: 'test_project_id', management_key: 'test_key') }
7
+ let(:valid_token) { 'valid.jwt.token' }
8
+ let(:refresh_token) { 'refresh.jwt.token' }
9
+
10
+ describe '#refresh_session' do
11
+ context 'when refresh token is in cookie' do
12
+ it 'uses the cookie refresh token' do
13
+ response_body = {
14
+ 'sessionJwt' => '',
15
+ 'refreshJwt' => '',
16
+ 'cookieData' => {
17
+ 'DSR' => refresh_token
18
+ },
19
+ 'cookies' => {
20
+ 'DS' => valid_token
21
+ }
22
+ }
23
+
24
+ allow(client).to receive(:post).and_return(response_body)
25
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123' })
26
+
27
+ result = client.refresh_session(refresh_token: refresh_token)
28
+
29
+ expect(result).to be_a(Hash)
30
+ expect(client).to have_received(:validate_token).with(refresh_token, nil)
31
+ end
32
+ end
33
+
34
+ context 'when refresh token is in response body' do
35
+ it 'uses the refreshJwt from response body' do
36
+ response_body = {
37
+ 'sessionJwt' => '',
38
+ 'refreshJwt' => refresh_token,
39
+ 'cookieData' => {},
40
+ 'cookies' => {
41
+ 'DS' => valid_token
42
+ }
43
+ }
44
+
45
+ allow(client).to receive(:post).and_return(response_body)
46
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123' })
47
+
48
+ result = client.refresh_session(refresh_token: 'old_refresh_token')
49
+
50
+ expect(result).to be_a(Hash)
51
+ end
52
+ end
53
+
54
+ context 'when refresh token is only in parameter' do
55
+ it 'falls back to the parameter refresh token' do
56
+ response_body = {
57
+ 'sessionJwt' => '',
58
+ 'refreshJwt' => '',
59
+ 'cookieData' => {},
60
+ 'cookies' => {
61
+ 'DS' => valid_token
62
+ }
63
+ }
64
+
65
+ allow(client).to receive(:post).and_return(response_body)
66
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123' })
67
+
68
+ result = client.refresh_session(refresh_token: refresh_token)
69
+
70
+ expect(result).to be_a(Hash)
71
+ expect(client).to have_received(:validate_token).with(refresh_token, nil).at_least(:once)
72
+ end
73
+ end
74
+
75
+ context 'when refresh token values are empty strings' do
76
+ it 'falls back to parameter refresh token when cookie and body have empty strings' do
77
+ response_body = {
78
+ 'sessionJwt' => '',
79
+ 'refreshJwt' => '',
80
+ 'cookieData' => {
81
+ 'DSR' => ''
82
+ },
83
+ 'cookies' => {
84
+ 'DS' => valid_token
85
+ }
86
+ }
87
+
88
+ allow(client).to receive(:post).and_return(response_body)
89
+ allow(client).to receive(:validate_token).and_return({ 'sub' => 'user123' })
90
+
91
+ result = client.refresh_session(refresh_token: refresh_token)
92
+
93
+ expect(result).to be_a(Hash)
94
+ expect(client).to have_received(:validate_token).with(refresh_token, nil).at_least(:once)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -10,7 +10,7 @@ FactoryBot.define do
10
10
  phone { "+1#{Faker::Number.number(digits: 10)}" }
11
11
  name { Faker::Name.name }
12
12
  given_name { Faker::Name.first_name }
13
- middle_name { 'Ruby SDK User' }
13
+ middle_name { "#{SpecUtils.build_prefix}Ruby-SDK-User" }
14
14
  family_name { Faker::Name.last_name }
15
15
  end
16
16
  end
@@ -60,7 +60,7 @@ describe Descope::Api::V1::Auth::EnchantedLink do
60
60
  @client.logger.info('Cleaning up test users...')
61
61
  all_users = @client.search_all_users
62
62
  all_users['users'].each do |user|
63
- if user['middleName'] == 'Ruby SDK User'
63
+ if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
64
64
  @client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
65
65
  @client.delete_user(user['loginIds'][0])
66
66
  end
@@ -11,7 +11,7 @@ describe Descope::Api::V1::Auth::MagicLink do
11
11
  @client.logger.info('Cleaning up test users...')
12
12
  all_users = @client.search_all_users
13
13
  all_users['users'].each do |user|
14
- if user['middleName'] == 'Ruby SDK User'
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
  @client.delete_user(user['loginIds'][0])
17
17
  end
@@ -19,7 +19,7 @@ describe Descope::Api::V1::Auth::OTP do
19
19
  @client.logger.info('Cleaning up test users...')
20
20
  all_users = @client.search_all_users
21
21
  all_users['users'].each do |user|
22
- if user['middleName'] == 'Ruby SDK User'
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
  @client.delete_user(user['loginIds'][0])
25
25
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Descope::Api::V1::Session do
6
+ before(:all) do
7
+ @client = DescopeClient.new(Configuration.config)
8
+ end
9
+
10
+ after(:all) do
11
+ @client.logger.info('Cleaning up test users...')
12
+ all_users = @client.search_all_users
13
+ all_users['users'].each do |user|
14
+ if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
15
+ @client.logger.info("Deleting ruby spec test user #{user['loginIds'][0]}")
16
+ @client.delete_user(user['loginIds'][0])
17
+ end
18
+ end
19
+ end
20
+
21
+ context 'test session methods' do
22
+ it 'should refresh session with refresh token' do
23
+ @password = SpecUtils.generate_password
24
+ user = build(:user)
25
+
26
+ @client.logger.info('1. Sign up with password')
27
+ res = @client.password_sign_up(login_id: user[:login_id], password: @password, user:)
28
+ @client.logger.info("sign up with password res: #{res}")
29
+ original_refresh_token = res[REFRESH_SESSION_TOKEN_NAME]['jwt']
30
+
31
+ @client.logger.info('2. Sign in with password')
32
+ login_res = @client.password_sign_in(login_id: user[:login_id], password: @password)
33
+ @client.logger.info("sign_in res: #{login_res}")
34
+
35
+ @client.logger.info('3. sleep 1 second before calling refresh_session')
36
+ sleep(1)
37
+
38
+ @client.logger.info('4. Refresh session')
39
+ refresh_session_res = @client.refresh_session(refresh_token: login_res[REFRESH_SESSION_TOKEN_NAME]['jwt'])
40
+ @client.logger.info("refresh_session_res: #{refresh_session_res}")
41
+
42
+ new_refresh_token = refresh_session_res[REFRESH_SESSION_TOKEN_NAME]['jwt']
43
+ @client.logger.info("new_refresh_token: #{new_refresh_token}")
44
+
45
+ @client.logger.info('5. Check new refresh token is not the same as the original one')
46
+ expect(original_refresh_token).not_to eq(new_refresh_token)
47
+ end
48
+ end
49
+ end
@@ -12,7 +12,7 @@ describe Descope::Api::V1::Auth::TOTP do
12
12
  @client.logger.info('Cleaning up test users...')
13
13
  all_users = @client.search_all_users
14
14
  all_users['users'].each do |user|
15
- if user['middleName'] == 'Ruby SDK User'
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
  @client.delete_user(user['loginIds'][0])
18
18
  end
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::AccessKey do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  end
9
11
 
@@ -28,6 +30,7 @@ describe Descope::Api::V1::Management::AccessKey do
28
30
  @tenant_id = @client.create_tenant(name: 'some-new-tenant')['id']
29
31
  @client.logger.info('creating access key')
30
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 60 seconds")
31
34
  sleep 60
32
35
  end
33
36
 
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::Audit do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  @client.logger.info('Deleting all tenants for Ruby SDK...')
9
11
  @client.search_all_tenants(names: ['Ruby-SDK-test'])['tenants'].each do |tenant|
@@ -16,7 +18,7 @@ describe Descope::Api::V1::Management::Audit do
16
18
  after(:all) do
17
19
  all_users = @client.search_all_users
18
20
  all_users['users'].each do |user|
19
- if user['middleName'] == 'Ruby SDK User'
21
+ if user['middleName'] == "#{SpecUtils.build_prefix}Ruby-SDK-User"
20
22
  puts "Deleting ruby spec test user #{user['loginIds'][0]}"
21
23
  @client.delete_user(user['loginIds'][0])
22
24
  end
@@ -39,14 +41,14 @@ describe Descope::Api::V1::Management::Audit do
39
41
  created_user = @client.create_user(**user)['user']
40
42
 
41
43
  expect do
42
- res = @client.audit_create_event(
44
+ @client.audit_create_event(
45
+ user_id: created_user['loginId'],
43
46
  action: 'pencil.created',
44
47
  type: 'info',
45
48
  tenant_id:,
46
49
  actor_id: created_user['loginIds'][0],
47
50
  data: { 'key' => 'value' }
48
51
  )
49
- expect(res).to eq({})
50
52
  end.not_to raise_error
51
53
  end
52
54
  end
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::Authz do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  puts 'authz schema delete'
9
11
  end
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::Flow do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  end
9
11
 
@@ -38,7 +40,7 @@ describe Descope::Api::V1::Management::Flow do
38
40
  it 'should import the current project theme' do
39
41
  export_theme = @client.export_theme
40
42
  export_theme_current_version = export_theme['theme']['version']
41
- imported_theme = @client.import_theme(export_theme)
43
+ imported_theme = @client.import_theme(export_theme['theme'])
42
44
  expect(imported_theme['theme']['version']).to be(export_theme_current_version + 1)
43
45
  end
44
46
  end
@@ -4,9 +4,11 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::Permission do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  @client.load_all_permissions['permissions'].each do |perm|
9
- if perm['description'] == 'Ruby SDK'
11
+ if perm['description'] == "#{SpecUtils.build_prefix} Ruby SDK"
10
12
  puts "Deleting permission: #{perm['name']}"
11
13
  @client.delete_permission(perm['name'])
12
14
  end
@@ -14,7 +16,7 @@ describe Descope::Api::V1::Management::Permission do
14
16
  end
15
17
 
16
18
  it 'should create update and delete a permission' do
17
- @client.create_permission(name: 'test_permission', description: 'Ruby SDK')
19
+ @client.create_permission(name: 'test_permission', description: "#{SpecUtils.build_prefix} Ruby SDK")
18
20
  all_permissions = @client.load_all_permissions['permissions']
19
21
  expect(all_permissions.any? { |perm| perm['name'] == 'test_permission' }).to eq(true)
20
22
  @client.update_permission(name: 'test_permission', new_name: 'test_permission_2')
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::Project do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  @export_output = @client.export_project
9
11
  end
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Descope::Api::V1::Management::Role do
6
6
  before(:all) do
7
+ raise 'DESCOPE_MANAGEMENT_KEY is not set' if ENV['DESCOPE_MANAGEMENT_KEY'].nil?
8
+
7
9
  @client = DescopeClient.new(Configuration.config)
8
10
  @client.logger.info('Staring cleanup before tests...')
9
11
  @client.logger.info('Deleting all permissions for Ruby SDK...')