workos 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) 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 +54 -0
  6. data/lib/workos/client.rb +2 -0
  7. data/lib/workos/directory_sync.rb +1 -0
  8. data/lib/workos/errors.rb +3 -1
  9. data/lib/workos/factor.rb +58 -0
  10. data/lib/workos/mfa.rb +165 -0
  11. data/lib/workos/sso.rb +38 -15
  12. data/lib/workos/types/challenge_struct.rb +18 -0
  13. data/lib/workos/types/factor_struct.rb +19 -0
  14. data/lib/workos/types/verify_factor_struct.rb +15 -0
  15. data/lib/workos/types.rb +3 -0
  16. data/lib/workos/verify_factor.rb +39 -0
  17. data/lib/workos/version.rb +1 -1
  18. data/lib/workos/webhooks.rb +9 -7
  19. data/lib/workos.rb +5 -0
  20. data/spec/lib/workos/mfa_spec.rb +232 -0
  21. data/spec/lib/workos/sso_spec.rb +140 -4
  22. data/spec/lib/workos/webhooks_spec.rb +1 -1
  23. data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_generic_valid.yml +82 -0
  24. data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_sms_valid.yml +82 -0
  25. data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_totp_valid.yml +82 -0
  26. data/spec/support/fixtures/vcr_cassettes/mfa/delete_factor.yml +80 -0
  27. data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_generic_valid.yml +82 -0
  28. data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_sms_valid.yml +82 -0
  29. data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_totp_valid.yml +82 -0
  30. data/spec/support/fixtures/vcr_cassettes/mfa/get_factor_invalid.yml +82 -0
  31. data/spec/support/fixtures/vcr_cassettes/mfa/get_factor_valid.yml +82 -0
  32. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_expired.yml +84 -0
  33. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_invalid.yml +84 -0
  34. data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_valid.yml +82 -0
  35. metadata +36 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 739e4734f5caa4b4c8180e125a206106242fea489c1dccc19f1bc45ad514bc7e
4
- data.tar.gz: '029c0a8ef19f9b9b933a73eec53a9770851ea2a338a81060c040b72a06e39189'
3
+ metadata.gz: 983d578de3e27144af8a7947eebfb770ad7ee640954511586617505c520ee657
4
+ data.tar.gz: 92cb0b75234f56a1e18c47d9cb339b2f389e17463798141bc7a3a2977f5f9372
5
5
  SHA512:
6
- metadata.gz: 18631e0e0cdc5033b7df32d3ff95e2eeadcd7babd6c3b11063e174006ed3e8abd7769bfe4b0c828967e79b724ce0d8a79243960b5f2922eeb242051b56395b41
7
- data.tar.gz: 2a2b2d48b1410ad0fc86943a168d584234fd5c01ca5ee3e3b4b3117f9924ddc4199d55d10d338b1f07daa193edc0144312ec6271a68c65b89ec8fa2243064aa0
6
+ metadata.gz: 1143a28ee95755c80fe36aa5fba02e069143ebdb96e67f909d566bbf091928176ac29f23ccfa7764da163a248268f7a882616e0db7bd73612eda060c78cf8515
7
+ data.tar.gz: a2e279f2f2427dd8089eddcc692e677d21978fdd16f3918ffe162822d116b7904f1dbc6826d151f583ba1c60cd5c0e8fbe8b825fb78212f772d7a1aa11faa6da
@@ -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.0.0)
4
+ workos (2.2.0)
5
5
  sorbet-runtime (~> 0.5)
6
6
 
7
7
  GEM
@@ -93,4 +93,4 @@ DEPENDENCIES
93
93
  yard
94
94
 
95
95
  BUNDLED WITH
96
- 2.2.22
96
+ 2.2.33
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,54 @@
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
+ extend T::Sig
10
+
11
+ attr_accessor :id, :object, :expires_at, :code, :authentication_factor_id, :updated_at, :created_at
12
+
13
+ sig { params(json: String).void }
14
+ def initialize(json)
15
+ raw = parse_json(json)
16
+ @id = T.let(raw.id, String)
17
+ @object = T.let(raw.object, String)
18
+ @expires_at = raw.expires_at
19
+ @code = raw.code
20
+ @authentication_factor_id = T.let(raw.authentication_factor_id, String)
21
+ @created_at = T.let(raw.created_at, String)
22
+ @updated_at = T.let(raw.updated_at, String)
23
+ end
24
+
25
+ def to_json(*)
26
+ {
27
+ id: id,
28
+ object: object,
29
+ expires_at: expires_at,
30
+ code: code,
31
+ authentication_factor_id: authentication_factor_id,
32
+ created_at: created_at,
33
+ updated_at: updated_at,
34
+ }
35
+ end
36
+
37
+ private
38
+
39
+ sig { params(json_string: String).returns(WorkOS::Types::ChallengeStruct) }
40
+ def parse_json(json_string)
41
+ hash = JSON.parse(json_string, symbolize_names: true)
42
+
43
+ WorkOS::Types::ChallengeStruct.new(
44
+ id: hash[:id],
45
+ object: hash[:object],
46
+ expires_at: hash[:expires_at],
47
+ code: hash[:code],
48
+ authentication_factor_id: hash[:authentication_factor_id],
49
+ created_at: hash[:created_at],
50
+ updated_at: hash[:updated_at],
51
+ )
52
+ end
53
+ end
54
+ 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
@@ -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
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,58 @@
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
+ # rubocop:disable Metrics/AbcSize
10
+ extend T::Sig
11
+ attr_accessor :id, :environment_id, :object, :type, :sms, :totp, :updated_at, :created_at
12
+
13
+ sig { params(json: String).void }
14
+ def initialize(json)
15
+ raw = parse_json(json)
16
+ @id = T.let(raw.id, String)
17
+ @environment_id = T.let(raw.environment_id, String)
18
+ @object = T.let(raw.object, String)
19
+ @type = T.let(raw.type, String)
20
+ @created_at = T.let(raw.created_at, String)
21
+ @updated_at = T.let(raw.updated_at, String)
22
+ @totp = raw.totp
23
+ @sms = raw.sms
24
+ end
25
+
26
+ def to_json(*)
27
+ {
28
+ id: id,
29
+ environment_id: environment_id,
30
+ object: object,
31
+ type: type,
32
+ totp: totp,
33
+ sms: sms,
34
+ created_at: created_at,
35
+ updated_at: updated_at,
36
+ }
37
+ end
38
+
39
+ private
40
+
41
+ sig { params(json_string: String).returns(WorkOS::Types::FactorStruct) }
42
+ def parse_json(json_string)
43
+ hash = JSON.parse(json_string, symbolize_names: true)
44
+
45
+ WorkOS::Types::FactorStruct.new(
46
+ id: hash[:id],
47
+ environment_id: hash[:environment_id],
48
+ object: hash[:object],
49
+ type: hash[:type],
50
+ totp: hash[:totp],
51
+ sms: hash[:sms],
52
+ created_at: hash[:created_at],
53
+ updated_at: hash[:updated_at],
54
+ )
55
+ end
56
+ # rubocop:enable Metrics/AbcSize
57
+ end
58
+ 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
data/lib/workos/sso.rb CHANGED
@@ -21,23 +21,27 @@ module WorkOS
21
21
  # Generate an Oauth2 authorization URL where your users will
22
22
  # authenticate using the configured SSO Identity Provider.
23
23
  #
24
+ # @param [String] redirect_uri The URI where users are directed
25
+ # after completing the authentication step. Must match a
26
+ # configured redirect URI on your WorkOS dashboard.
27
+ # @param [String] client_id The WorkOS client ID for the environment
28
+ # where you've configured your SSO connection.
24
29
  # @param [String] domain The domain for the relevant SSO Connection
25
- # configured on your WorkOS dashboard. One of provider or domain is
26
- # required
30
+ # configured on your WorkOS dashboard. One of provider, domain,
31
+ # connection, or organization is required.
32
+ # The domain is deprecated.
27
33
  # @param [String] provider A provider name for an Identity Provider
28
- # configured on your WorkOS dashboard. Only 'Google' is supported.
34
+ # configured on your WorkOS dashboard. Only 'GoogleOAuth' and
35
+ # 'MicrosoftOAuth' are supported.
29
36
  # @param [String] connection The ID for a Connection configured on
30
37
  # WorkOS.
31
- # @param [String] client_id The WorkOS client ID for the environment
32
- # where you've configured your SSO connection.
33
- # @param [String] redirect_uri The URI where users are directed
34
- # after completing the authentication step. Must match a
35
- # configured redirect URI on your WorkOS dashboard.
36
- # @param [String] state An aribtrary state object
38
+ # @param [String] organization The ID for an Organization configured
39
+ # on WorkOS.
40
+ # @param [String] state An arbitrary state object
37
41
  # that is preserved and available to the client in the response.
38
42
  # @example
39
43
  # WorkOS::SSO.authorization_url(
40
- # domain: 'acme.com',
44
+ # connection: 'conn_123',
41
45
  # client_id: 'project_01DG5TGK363GRVXP3ZS40WNGEZ',
42
46
  # redirect_uri: 'https://workos.com/callback',
43
47
  # state: {
@@ -45,19 +49,23 @@ module WorkOS
45
49
  # }.to_s
46
50
  # )
47
51
  #
48
- # => "https://api.workos.com/sso/authorize?domain=acme.com" \
52
+ # => "https://api.workos.com/sso/authorize?connection=conn_123" \
49
53
  # "&client_id=project_01DG5TGK363GRVXP3ZS40WNGEZ" \
50
54
  # "&redirect_uri=https%3A%2F%2Fworkos.com%2Fcallback&" \
51
55
  # "response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdocs%22%7D"
52
56
  #
53
57
  # @return [String]
58
+ # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
54
59
  sig do
55
60
  params(
56
61
  redirect_uri: String,
57
62
  client_id: T.nilable(String),
58
63
  domain: T.nilable(String),
64
+ domain_hint: T.nilable(String),
65
+ login_hint: T.nilable(String),
59
66
  provider: T.nilable(String),
60
67
  connection: T.nilable(String),
68
+ organization: T.nilable(String),
61
69
  state: T.nilable(String),
62
70
  ).returns(String)
63
71
  end
@@ -65,14 +73,23 @@ module WorkOS
65
73
  redirect_uri:,
66
74
  client_id: nil,
67
75
  domain: nil,
76
+ domain_hint: nil,
77
+ login_hint: nil,
68
78
  provider: nil,
69
79
  connection: nil,
80
+ organization: nil,
70
81
  state: ''
71
82
  )
83
+ if domain
84
+ warn '[DEPRECATION] `domain` is deprecated.
85
+ Please use `organization` instead.'
86
+ end
87
+
72
88
  validate_authorization_url_arguments(
73
89
  provider: provider,
74
90
  domain: domain,
75
91
  connection: connection,
92
+ organization: organization,
76
93
  )
77
94
 
78
95
  query = URI.encode_www_form({
@@ -81,12 +98,16 @@ module WorkOS
81
98
  response_type: 'code',
82
99
  state: state,
83
100
  domain: domain,
101
+ domain_hint: domain_hint,
102
+ login_hint: login_hint,
84
103
  provider: provider,
85
104
  connection: connection,
105
+ organization: organization,
86
106
  }.compact)
87
107
 
88
108
  "https://#{WorkOS::API_HOSTNAME}/sso/authorize?#{query}"
89
109
  end
110
+ # rubocop:enable Metrics/MethodLength, Metrics/ParameterLists
90
111
 
91
112
  sig do
92
113
  params(
@@ -229,16 +250,18 @@ module WorkOS
229
250
  domain: T.nilable(String),
230
251
  provider: T.nilable(String),
231
252
  connection: T.nilable(String),
253
+ organization: T.nilable(String),
232
254
  ).void
233
255
  end
234
256
  def validate_authorization_url_arguments(
235
257
  domain:,
236
258
  provider:,
237
- connection:
259
+ connection:,
260
+ organization:
238
261
  )
239
- if [domain, provider, connection].all?(&:nil?)
240
- raise ArgumentError, 'Either connection, domain, or ' \
241
- 'provider is required.'
262
+ if [domain, provider, connection, organization].all?(&:nil?)
263
+ raise ArgumentError, 'Either connection, domain, ' \
264
+ 'provider, or organization is required.'
242
265
  end
243
266
 
244
267
  return unless provider && !PROVIDERS.include?(provider)
@@ -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
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module WorkOS
5
+ module Types
6
+ # This FactorStruct acts as a typed interface
7
+ # for the Factor class
8
+ class FactorStruct < T::Struct
9
+ const :id, String
10
+ const :environment_id, String
11
+ const :object, String
12
+ const :type, String
13
+ const :totp, T.nilable(T::Hash[Symbol, Object])
14
+ const :sms, T.nilable(T::Hash[Symbol, Object])
15
+ const :created_at, String
16
+ const :updated_at, String
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module WorkOS
5
+ module Types
6
+ # This VerifyFactorStruct acts as a typed interface
7
+ # for the Factor class
8
+ class VerifyFactorStruct < T::Struct
9
+ const :challenge, T.nilable(T::Hash[Symbol, Object])
10
+ const :valid, T.nilable(TrueClass)
11
+ const :code, T.nilable(String)
12
+ const :message, T.nilable(String)
13
+ end
14
+ end
15
+ end
data/lib/workos/types.rb CHANGED
@@ -16,5 +16,8 @@ module WorkOS
16
16
  require_relative 'types/provider_enum'
17
17
  require_relative 'types/directory_user_struct'
18
18
  require_relative 'types/webhook_struct'
19
+ require_relative 'types/factor_struct'
20
+ require_relative 'types/challenge_struct'
21
+ require_relative 'types/verify_factor_struct'
19
22
  end
20
23
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ module WorkOS
5
+ # The VerifyFactor 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 VerifyFactor
9
+ extend T::Sig
10
+
11
+ attr_accessor :challenge, :valid
12
+
13
+ sig { params(json: String).void }
14
+ def initialize(json)
15
+ raw = parse_json(json)
16
+ @challenge = T.let(raw.challenge, Hash)
17
+ @valid = raw.valid
18
+ end
19
+
20
+ def to_json(*)
21
+ {
22
+ challenge: challenge,
23
+ valid: valid,
24
+ }
25
+ end
26
+
27
+ private
28
+
29
+ sig { params(json_string: String).returns(WorkOS::Types::VerifyFactorStruct) }
30
+ def parse_json(json_string)
31
+ hash = JSON.parse(json_string, symbolize_names: true)
32
+
33
+ WorkOS::Types::VerifyFactorStruct.new(
34
+ challenge: hash[:challenge],
35
+ valid: hash[:valid],
36
+ )
37
+ end
38
+ end
39
+ end
@@ -2,5 +2,5 @@
2
2
  # typed: strong
3
3
 
4
4
  module WorkOS
5
- VERSION = '2.0.0'
5
+ VERSION = '2.2.0'
6
6
  end