workos 2.1.0 → 2.2.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.semaphore/semaphore.yml +13 -39
  3. data/Gemfile.lock +2 -2
  4. data/README.md +4 -0
  5. data/lib/workos/challenge.rb +55 -0
  6. data/lib/workos/client.rb +2 -0
  7. data/lib/workos/connection.rb +1 -0
  8. data/lib/workos/deprecated_hash_wrapper.rb +76 -0
  9. data/lib/workos/directory.rb +1 -0
  10. data/lib/workos/directory_group.rb +5 -2
  11. data/lib/workos/directory_sync.rb +9 -8
  12. data/lib/workos/directory_user.rb +4 -1
  13. data/lib/workos/errors.rb +3 -1
  14. data/lib/workos/factor.rb +59 -0
  15. data/lib/workos/hash_provider.rb +19 -0
  16. data/lib/workos/mfa.rb +165 -0
  17. data/lib/workos/organization.rb +1 -0
  18. data/lib/workos/profile.rb +1 -0
  19. data/lib/workos/profile_and_token.rb +1 -0
  20. data/lib/workos/types/challenge_struct.rb +18 -0
  21. data/lib/workos/types/factor_struct.rb +19 -0
  22. data/lib/workos/types/passwordless_session_struct.rb +2 -0
  23. data/lib/workos/types/verify_factor_struct.rb +13 -0
  24. data/lib/workos/types.rb +3 -0
  25. data/lib/workos/verify_factor.rb +40 -0
  26. data/lib/workos/version.rb +1 -1
  27. data/lib/workos/webhook.rb +1 -0
  28. data/lib/workos/webhooks.rb +9 -7
  29. data/lib/workos.rb +7 -0
  30. data/spec/lib/workos/directory_sync_spec.rb +4 -0
  31. data/spec/lib/workos/mfa_spec.rb +262 -0
  32. data/spec/lib/workos/sso_spec.rb +0 -2
  33. data/spec/lib/workos/webhooks_spec.rb +1 -1
  34. data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_generic_valid.yml +82 -0
  35. data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_sms_valid.yml +82 -0
  36. data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_totp_valid.yml +82 -0
  37. data/spec/support/fixtures/vcr_cassettes/mfa/delete_factor.yml +80 -0
  38. data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_generic_valid.yml +82 -0
  39. data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_sms_valid.yml +82 -0
  40. data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_totp_valid.yml +82 -0
  41. data/spec/support/fixtures/vcr_cassettes/mfa/get_factor_invalid.yml +82 -0
  42. data/spec/support/fixtures/vcr_cassettes/mfa/get_factor_valid.yml +82 -0
  43. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_expired.yml +84 -0
  44. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_invalid.yml +84 -0
  45. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_valid.yml +82 -0
  46. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_valid_is_false.yml +82 -0
  47. metadata +40 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0500b789496692e53bc6d47d80a21a0b8b802325e1e0f876fe0b94a775aa4f05
4
- data.tar.gz: a7e8e350e7fb1336496e9a09ee7543a120e1b6ed62cc60dffbe1b4ccd2dd4712
3
+ metadata.gz: 286a2f14af16bfc7b9c77e7938c2b8d7366f4a03f9fca4c7892f85f60562e433
4
+ data.tar.gz: 8970807084e7022beb9bb1523c270e645c340e42e452d7f0d7ea0d64958cf1ea
5
5
  SHA512:
6
- metadata.gz: 549c9210c2d765b2d6f264e62f285f7b96c9225e53724798216eb08167be5451825a729f36273fbda7fb713b9a1db49025b3cc6a308a98b969ca0a3631c8ffd9
7
- data.tar.gz: 4a3fdf8d50681db812a0de37c56d93b03c6bb194a892280cfc9d287612ba7494a1bd777f92b28538b12d978b0a1dc354ca7c82e12fd1707c440643c7215685cb
6
+ metadata.gz: e4d3af795ee51a5cb807fda2bdffc2217e0150ec2f4ffe51fb86daab6e376ecd240f03f1b204db2a72265ebc61d5a9c227a13924a262bb6cf7011ce9c87df177
7
+ data.tar.gz: a8977f9bff244978c9c1935e46a411e4e564a86ed51d7523780feab31212857771813190c523f64d5640f13b393ba5f5a3df3ced5729a7ad34df0cdfa3b6014e
@@ -31,45 +31,19 @@ blocks:
31
31
  - name: codecov-workos-ruby
32
32
  jobs:
33
33
  - name: Ruby 1.9.3
34
- commands:
35
- - checkout
36
- - sem-version ruby 1.9.3-p551
37
- - bundle install
38
- - bundle exec rspec
39
- - name: Ruby 2.0.0
40
- commands:
41
- - checkout
42
- - sem-version ruby 2.0.0-p648
43
- - bundle install
44
- - bundle exec rspec
45
- - name: Ruby 2.3.4
46
- commands:
47
- - checkout
48
- - sem-version ruby 2.3.4
49
- - bundle install
50
- - bundle exec rspec
51
- - name: Ruby 2.5.7
52
- commands:
53
- - checkout
54
- - sem-version ruby 2.5.7
55
- - bundle install
56
- - bundle exec rspec
57
- - name: Ruby 2.6.5
58
- commands:
59
- - checkout
60
- - sem-version ruby 2.6.5
61
- - bundle install
62
- - bundle exec rspec
63
- - name: Ruby 2.7.3
64
- commands:
65
- - checkout
66
- - sem-version ruby 2.7.3
67
- - bundle install
68
- - bundle exec rspec
69
- - name: Ruby 3.0.2
70
- commands:
71
- - checkout
72
- - sem-version ruby 3.0.2
34
+ matrix:
35
+ - env_var: RUBY_VERSION
36
+ values:
37
+ - 1.9.3-p551
38
+ - 2.0.0-p648
39
+ - 2.3.4
40
+ - 2.5.7
41
+ - 2.6.5
42
+ - 2.7.3
43
+ - 3.0.2
44
+ commands:
45
+ - checkout
46
+ - sem-version ruby $RUBY_VERSION
73
47
  - bundle install
74
48
  - bundle exec rspec
75
49
  promotions:
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- workos (2.1.0)
4
+ workos (2.2.1)
5
5
  sorbet-runtime (~> 0.5)
6
6
 
7
7
  GEM
@@ -60,7 +60,7 @@ GEM
60
60
  simplecov_json_formatter (0.1.2)
61
61
  sorbet (0.5.6388)
62
62
  sorbet-static (= 0.5.6388)
63
- sorbet-runtime (0.5.9300)
63
+ sorbet-runtime (0.5.9944)
64
64
  sorbet-static (0.5.6388-universal-darwin-14)
65
65
  sorbet-static (0.5.6388-universal-darwin-15)
66
66
  sorbet-static (0.5.6388-universal-darwin-16)
data/README.md CHANGED
@@ -38,6 +38,10 @@ Or, you may set the key yourself, such as in an initializer in your application
38
38
  WorkOS.key = '[your api key]'
39
39
  ```
40
40
 
41
+ ## SDK Versioning
42
+
43
+ For our SDKs WorkOS follows a Semantic Versioning ([SemVer](https://semver.org/)) process where all releases will have a version X.Y.Z (like 1.0.0) pattern wherein Z would be a bug fix (e.g., 1.0.1), Y would be a minor release (1.1.0) and X would be a major release (2.0.0). We permit any breaking changes to only be released in major versions and strongly recommend reading changelogs before making any major version upgrades.
44
+
41
45
  ## More Information
42
46
 
43
47
  * [Single Sign-On Guide](https://workos.com/docs/sso/guide)
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ module WorkOS
5
+ # The Challnge class provides a lightweight wrapper around
6
+ # a WorkOS DirectoryUser resource. This class is not meant to be instantiated
7
+ # in DirectoryUser space, and is instantiated internally but exposed.
8
+ class Challenge
9
+ include HashProvider
10
+ extend T::Sig
11
+
12
+ attr_accessor :id, :object, :expires_at, :code, :authentication_factor_id, :updated_at, :created_at
13
+
14
+ sig { params(json: String).void }
15
+ def initialize(json)
16
+ raw = parse_json(json)
17
+ @id = T.let(raw.id, String)
18
+ @object = T.let(raw.object, String)
19
+ @expires_at = raw.expires_at
20
+ @code = raw.code
21
+ @authentication_factor_id = T.let(raw.authentication_factor_id, String)
22
+ @created_at = T.let(raw.created_at, String)
23
+ @updated_at = T.let(raw.updated_at, String)
24
+ end
25
+
26
+ def to_json(*)
27
+ {
28
+ id: id,
29
+ object: object,
30
+ expires_at: expires_at,
31
+ code: code,
32
+ authentication_factor_id: authentication_factor_id,
33
+ created_at: created_at,
34
+ updated_at: updated_at,
35
+ }
36
+ end
37
+
38
+ private
39
+
40
+ sig { params(json_string: String).returns(WorkOS::Types::ChallengeStruct) }
41
+ def parse_json(json_string)
42
+ hash = JSON.parse(json_string, symbolize_names: true)
43
+
44
+ WorkOS::Types::ChallengeStruct.new(
45
+ id: hash[:id],
46
+ object: hash[:object],
47
+ expires_at: hash[:expires_at],
48
+ code: hash[:code],
49
+ authentication_factor_id: hash[:authentication_factor_id],
50
+ created_at: hash[:created_at],
51
+ updated_at: hash[:updated_at],
52
+ )
53
+ end
54
+ end
55
+ end
data/lib/workos/client.rb CHANGED
@@ -144,6 +144,7 @@ module WorkOS
144
144
  )
145
145
  when 422
146
146
  message = json['message']
147
+ code = json['code']
147
148
  errors = extract_error(json['errors']) if json['errors']
148
149
  message += " (#{errors})" if errors
149
150
 
@@ -151,6 +152,7 @@ module WorkOS
151
152
  message: message,
152
153
  http_status: http_status,
153
154
  request_id: response['x-request-id'],
155
+ code: code,
154
156
  )
155
157
  end
156
158
  end
@@ -7,6 +7,7 @@ module WorkOS
7
7
  # in user space, and is instantiated internally but exposed.
8
8
  # Note: status is deprecated - use state instead
9
9
  class Connection
10
+ include HashProvider
10
11
  extend T::Sig
11
12
 
12
13
  attr_accessor :id, :name, :connection_type, :domains, :organization_id,
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkOS
4
+ # A Temporary wrapper class for a Hash, currently the base class for
5
+ # WorOS::DirectoryGroup and WorkOS::DirectoryUser. Makes all the Hash
6
+ # methods available to those classes, but will also emit a deprecation
7
+ # warning whenever any of them are used.
8
+ #
9
+ # Once we deprecate Hash compatibility, this model can be deleted.
10
+ class DeprecatedHashWrapper < Hash
11
+ (public_instance_methods - Object.methods).each do |method_name|
12
+ define_method method_name do |*args, &block|
13
+ print_deprecation_warning(method_name)
14
+ super(*args, &block)
15
+ end
16
+ end
17
+
18
+ # call the original implementation of :replace in Hash,
19
+ # so we don't show the deprecation warning
20
+ def replace_without_warning(new_hash)
21
+ method(:replace).super_method&.call(new_hash)
22
+ end
23
+
24
+ def [](attribute_name)
25
+ usage = "#{object_name}.#{attribute_name}"
26
+ warning_message = "WARNING: The Hash style access for #{class_name} attributes is deprecated
27
+ and will be removed in a future version. Please use `#{usage}` or equivalent accessor.\n"
28
+
29
+ print_deprecation_warning('[]', warning_message)
30
+
31
+ super(attribute_name.to_sym)
32
+ end
33
+
34
+ private
35
+
36
+ def deprecation_warning(method_name)
37
+ usage = "#{object_name}.to_h.#{method_name}"
38
+
39
+ "WARNING: Hash compatibility for #{class_name} is deprecated and will be removed
40
+ in a future version. Please use `#{usage}` to access methods on the attribute Hash object.\n"
41
+ end
42
+
43
+ def print_deprecation_warning(method_name, warning_message = deprecation_warning(method_name))
44
+ if RUBY_VERSION > '3'
45
+ warn warning_message, category: :deprecated
46
+ else
47
+ warn warning_message
48
+ end
49
+ end
50
+
51
+ def class_name
52
+ self.class.name
53
+ end
54
+
55
+ # We want to do class_name.demodulize.underscore here, but that's not available in Ruby 1.9, so
56
+ # implementing the demodulize and underscore methods here.
57
+ def object_name
58
+ i = class_name.rindex('::')
59
+ object_name = i ? class_name[(i + 2)..-1] : class_name
60
+ underscore(object_name)
61
+ end
62
+
63
+ def underscore(camel_cased_word)
64
+ return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
65
+
66
+ word = camel_cased_word.to_s.gsub('::', '/')
67
+ word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)((?=a)b)(?=\b|[^a-z])/) do
68
+ "#{Regexp.last_match(1) && '_'}#{Regexp.last_match(2).downcase}"
69
+ end
70
+ word.gsub!(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { (Regexp.last_match(1) || Regexp.last_match(2)) << '_' }
71
+ word.tr!('-', '_')
72
+ word.downcase!
73
+ word
74
+ end
75
+ end
76
+ end
@@ -6,6 +6,7 @@ module WorkOS
6
6
  # a WorkOS Directory resource. This class is not meant to be instantiated
7
7
  # in user space, and is instantiated internally but exposed.
8
8
  class Directory
9
+ include HashProvider
9
10
  extend T::Sig
10
11
 
11
12
  attr_accessor :id, :domain, :name, :type, :state, :organization_id, :created_at, :updated_at
@@ -5,10 +5,11 @@ module WorkOS
5
5
  # The DirectoryGroup class provides a lightweight wrapper around
6
6
  # a WorkOS DirectoryGroup resource. This class is not meant to be instantiated
7
7
  # in user space, and is instantiated internally but exposed.
8
- class DirectoryGroup
8
+ class DirectoryGroup < DeprecatedHashWrapper
9
+ include HashProvider
9
10
  extend T::Sig
10
11
 
11
- attr_accessor :id, :name
12
+ attr_accessor :id, :name, :custom_attributes, :raw_attributes
12
13
 
13
14
  sig { params(json: String).void }
14
15
  def initialize(json)
@@ -16,6 +17,8 @@ module WorkOS
16
17
 
17
18
  @id = T.let(raw.id, String)
18
19
  @name = T.let(raw.name, String)
20
+
21
+ replace_without_warning(to_json)
19
22
  end
20
23
 
21
24
  def to_json(*)
@@ -26,6 +26,7 @@ module WorkOS
26
26
  # before a provided Directory ID.
27
27
  # @option options [String] after Pagination cursor to receive records
28
28
  # before a provided Directory ID.
29
+ # @option options [String] organization_id The ID for an Organization configured on WorkOS.
29
30
  #
30
31
  # @return [Hash]
31
32
  sig do
@@ -95,7 +96,7 @@ module WorkOS
95
96
  # @option options [String] after Pagination cursor to receive records
96
97
  # before a provided Directory Group ID.
97
98
  #
98
- # @return [Hash]
99
+ # @return [WorkOS::DirectoryGroup]
99
100
  sig do
100
101
  params(
101
102
  options: T::Hash[Symbol, String],
@@ -134,7 +135,7 @@ module WorkOS
134
135
  # @option options [String] after Pagination cursor to receive records
135
136
  # before a provided Directory User ID.
136
137
  #
137
- # @return [Hash]
138
+ # @return [WorkOS::DirectoryUser]
138
139
  sig do
139
140
  params(
140
141
  options: T::Hash[Symbol, String],
@@ -164,8 +165,8 @@ module WorkOS
164
165
  #
165
166
  # @param [String] id The ID of the directory group.
166
167
  #
167
- # @return Hash
168
- sig { params(id: String).returns(T::Hash[String, T.untyped]) }
168
+ # @return WorkOS::DirectoryGroup
169
+ sig { params(id: String).returns(WorkOS::DirectoryGroup) }
169
170
  def get_group(id)
170
171
  response = execute_request(
171
172
  request: get_request(
@@ -174,15 +175,15 @@ module WorkOS
174
175
  ),
175
176
  )
176
177
 
177
- JSON.parse(response.body)
178
+ ::WorkOS::DirectoryGroup.new(response.body)
178
179
  end
179
180
 
180
181
  # Retrieve the directory user with the given ID.
181
182
  #
182
183
  # @param [String] id The ID of the directory user.
183
184
  #
184
- # @return Hash
185
- sig { params(id: String).returns(T::Hash[String, T.untyped]) }
185
+ # @return WorkOS::DirectoryUser
186
+ sig { params(id: String).returns(WorkOS::DirectoryUser) }
186
187
  def get_user(id)
187
188
  response = execute_request(
188
189
  request: get_request(
@@ -191,7 +192,7 @@ module WorkOS
191
192
  ),
192
193
  )
193
194
 
194
- JSON.parse(response.body)
195
+ ::WorkOS::DirectoryUser.new(response.body)
195
196
  end
196
197
 
197
198
  # Delete the directory with the given ID.
@@ -5,7 +5,8 @@ module WorkOS
5
5
  # The DirectoryUser class provides a lightweight wrapper around
6
6
  # a WorkOS DirectoryUser resource. This class is not meant to be instantiated
7
7
  # in DirectoryUser space, and is instantiated internally but exposed.
8
- class DirectoryUser
8
+ class DirectoryUser < DeprecatedHashWrapper
9
+ include HashProvider
9
10
  extend T::Sig
10
11
 
11
12
  attr_accessor :id, :idp_id, :emails, :first_name, :last_name, :username, :state,
@@ -26,6 +27,8 @@ module WorkOS
26
27
  @groups = T.let(raw.groups, Array)
27
28
  @custom_attributes = raw.custom_attributes
28
29
  @raw_attributes = raw.raw_attributes
30
+
31
+ replace_without_warning(to_json)
29
32
  end
30
33
  # rubocop:enable Metrics/AbcSize
31
34
 
data/lib/workos/errors.rb CHANGED
@@ -17,14 +17,16 @@ module WorkOS
17
17
  error_description: T.nilable(String),
18
18
  http_status: T.nilable(Integer),
19
19
  request_id: T.nilable(String),
20
+ code: T.nilable(String),
20
21
  ).void
21
22
  end
22
- def initialize(message: nil, error: nil, error_description: nil, http_status: nil, request_id: nil)
23
+ def initialize(message: nil, error: nil, error_description: nil, http_status: nil, request_id: nil, code: nil)
23
24
  @message = message
24
25
  @error = error
25
26
  @error_description = error_description
26
27
  @http_status = http_status
27
28
  @request_id = request_id
29
+ @code = code
28
30
  end
29
31
 
30
32
  sig { returns(String) }
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ module WorkOS
5
+ # The Factor class provides a lightweight wrapper around
6
+ # a WorkOS DirectoryUser resource. This class is not meant to be instantiated
7
+ # in DirectoryUser space, and is instantiated internally but exposed.
8
+ class Factor
9
+ include HashProvider
10
+ # rubocop:disable Metrics/AbcSize
11
+ extend T::Sig
12
+ attr_accessor :id, :environment_id, :object, :type, :sms, :totp, :updated_at, :created_at
13
+
14
+ sig { params(json: String).void }
15
+ def initialize(json)
16
+ raw = parse_json(json)
17
+ @id = T.let(raw.id, String)
18
+ @environment_id = T.let(raw.environment_id, String)
19
+ @object = T.let(raw.object, String)
20
+ @type = T.let(raw.type, String)
21
+ @created_at = T.let(raw.created_at, String)
22
+ @updated_at = T.let(raw.updated_at, String)
23
+ @totp = raw.totp
24
+ @sms = raw.sms
25
+ end
26
+
27
+ def to_json(*)
28
+ {
29
+ id: id,
30
+ environment_id: environment_id,
31
+ object: object,
32
+ type: type,
33
+ totp: totp,
34
+ sms: sms,
35
+ created_at: created_at,
36
+ updated_at: updated_at,
37
+ }
38
+ end
39
+
40
+ private
41
+
42
+ sig { params(json_string: String).returns(WorkOS::Types::FactorStruct) }
43
+ def parse_json(json_string)
44
+ hash = JSON.parse(json_string, symbolize_names: true)
45
+
46
+ WorkOS::Types::FactorStruct.new(
47
+ id: hash[:id],
48
+ environment_id: hash[:environment_id],
49
+ object: hash[:object],
50
+ type: hash[:type],
51
+ totp: hash[:totp],
52
+ sms: hash[:sms],
53
+ created_at: hash[:created_at],
54
+ updated_at: hash[:updated_at],
55
+ )
56
+ end
57
+ # rubocop:enable Metrics/AbcSize
58
+ end
59
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ module WorkOS
5
+ # Module to include an explicit method for converting a model into a Hash containing
6
+ # its attributes. Default implementation will simply call to_json. Individual classes
7
+ # may override.
8
+ module HashProvider
9
+ include Kernel
10
+
11
+ def to_json(*)
12
+ raise 'Must be implemented by including class.'
13
+ end
14
+
15
+ def to_h
16
+ to_json
17
+ end
18
+ end
19
+ end
data/lib/workos/mfa.rb ADDED
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+
5
+ require 'net/http'
6
+ require 'uri'
7
+
8
+ module WorkOS
9
+ # The MFA module provides convenience methods for working with the WorkOS
10
+ # MFA platform. You'll need a valid API key
11
+ module MFA
12
+ class << self
13
+ extend T::Sig
14
+ include Base
15
+ include Client
16
+ sig { params(id: String).returns(T::Boolean) }
17
+ def delete_factor(id:)
18
+ response = execute_request(
19
+ request: delete_request(
20
+ path: "/auth/factors/#{id}",
21
+ auth: true,
22
+ ),
23
+ )
24
+ response.is_a? Net::HTTPSuccess
25
+ end
26
+
27
+ sig do
28
+ params(id: String).returns(WorkOS::Factor)
29
+ end
30
+ def get_factor(
31
+ id:
32
+ )
33
+ response = execute_request(
34
+ request: get_request(
35
+ path: "/auth/factors/#{id}",
36
+ auth: true,
37
+ ),
38
+ )
39
+ WorkOS::Factor.new(response.body)
40
+ end
41
+
42
+ sig do
43
+ params(
44
+ type: String,
45
+ totp_issuer: T.nilable(String),
46
+ totp_user: T.nilable(String),
47
+ phone_number: T.nilable(String),
48
+ ).void
49
+ end
50
+ # rubocop:disable Metrics/CyclomaticComplexity
51
+ # rubocop:disable Metrics/PerceivedComplexity
52
+
53
+ def validate_args(
54
+ type:,
55
+ totp_issuer: nil,
56
+ totp_user: nil,
57
+ phone_number: nil
58
+ )
59
+ if type != 'sms' && type != 'totp' && type != 'generic_otp'
60
+ raise ArgumentError, "Type argument must be either 'sms' or 'totp'"
61
+ end
62
+ if (type == 'totp' && totp_issuer.nil?) || (type == 'totp' && totp_user.nil?)
63
+ raise ArgumentError, 'Incomplete arguments. Need to specify both totp_issuer and totp_user when type is totp'
64
+ end
65
+ return unless type == 'sms' && phone_number.nil?
66
+
67
+ raise ArgumentError, 'Incomplete arguments. Need to specify phone_number when type is sms'
68
+ end
69
+ # rubocop:enable Metrics/CyclomaticComplexity
70
+ # rubocop:enable Metrics/PerceivedComplexity
71
+
72
+ sig do
73
+ params(
74
+ type: String,
75
+ totp_issuer: T.nilable(String),
76
+ totp_user: T.nilable(String),
77
+ phone_number: T.nilable(String),
78
+ ).returns(WorkOS::Factor)
79
+ end
80
+ # rubocop:disable Metrics/MethodLength
81
+ def enroll_factor(
82
+ type:,
83
+ totp_issuer: nil,
84
+ totp_user: nil,
85
+ phone_number: nil
86
+ )
87
+ validate_args(
88
+ type: type,
89
+ totp_issuer: totp_issuer,
90
+ totp_user: totp_user,
91
+ phone_number: phone_number,
92
+ )
93
+ response = execute_request(request: post_request(
94
+ auth: true,
95
+ body: {
96
+ type: type,
97
+ totp_issuer: totp_issuer,
98
+ totp_user: totp_user,
99
+ phone_number: phone_number,
100
+ },
101
+ path: '/auth/factors/enroll',
102
+ ))
103
+ WorkOS::Factor.new(response.body)
104
+ end
105
+ # rubocop:enable Metrics/MethodLength
106
+
107
+ sig do
108
+ params(
109
+ authentication_factor_id: T.nilable(String),
110
+ sms_template: T.nilable(String),
111
+ ).returns(WorkOS::Challenge)
112
+ end
113
+ def challenge_factor(
114
+ authentication_factor_id: nil,
115
+ sms_template: nil
116
+ )
117
+ if authentication_factor_id.nil?
118
+ raise ArgumentError, "Incomplete arguments: 'authentication_factor_id' is a required argument"
119
+ end
120
+
121
+ request = post_request(
122
+ auth: true,
123
+ body: {
124
+ sms_template: sms_template,
125
+ authentication_factor_id: authentication_factor_id,
126
+ },
127
+ path: '/auth/factors/challenge',
128
+ )
129
+
130
+ response = execute_request(request: request)
131
+ WorkOS::Challenge.new(response.body)
132
+ end
133
+
134
+ sig do
135
+ params(
136
+ authentication_challenge_id: T.nilable(String),
137
+ code: T.nilable(String),
138
+ ).returns(WorkOS::VerifyFactor)
139
+ end
140
+ def verify_factor(
141
+ authentication_challenge_id: nil,
142
+ code: nil
143
+ )
144
+
145
+ if authentication_challenge_id.nil? || code.nil?
146
+ raise ArgumentError, "Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments"
147
+ end
148
+
149
+ options = {
150
+ "authentication_challenge_id": authentication_challenge_id,
151
+ "code": code,
152
+ }
153
+
154
+ response = execute_request(
155
+ request: post_request(
156
+ path: '/auth/factors/verify',
157
+ auth: true,
158
+ body: options,
159
+ ),
160
+ )
161
+ WorkOS::VerifyFactor.new(response.body)
162
+ end
163
+ end
164
+ end
165
+ end
@@ -6,6 +6,7 @@ module WorkOS
6
6
  # a WorkOS Organization resource. This class is not meant to be instantiated
7
7
  # in user space, and is instantiated internally but exposed.
8
8
  class Organization
9
+ include HashProvider
9
10
  extend T::Sig
10
11
 
11
12
  attr_accessor :id, :domains, :name, :allow_profiles_outside_organization, :created_at, :updated_at
@@ -8,6 +8,7 @@ module WorkOS
8
8
  # is not meant to be instantiated in user space, and
9
9
  # is instantiated internally but exposed.
10
10
  class Profile
11
+ include HashProvider
11
12
  extend T::Sig
12
13
 
13
14
  sig { returns(String) }
@@ -6,6 +6,7 @@ module WorkOS
6
6
  # Access Token. This class is not meant to be instantiated in user space, and
7
7
  # is instantiated internally but exposed.
8
8
  class ProfileAndToken
9
+ include HashProvider
9
10
  extend T::Sig
10
11
 
11
12
  attr_accessor :access_token, :profile
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module WorkOS
5
+ module Types
6
+ # This ChallgengeStruct acts as a typed interface
7
+ # for the Factor class
8
+ class ChallengeStruct < T::Struct
9
+ const :id, String
10
+ const :object, String
11
+ const :expires_at, T.nilable(String)
12
+ const :code, T.nilable(String)
13
+ const :authentication_factor_id, String
14
+ const :created_at, String
15
+ const :updated_at, String
16
+ end
17
+ end
18
+ end