workos 2.1.1 → 2.3.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/.semaphore/semaphore.yml +13 -39
- data/Gemfile.lock +2 -2
- data/README.md +4 -0
- data/lib/workos/audit_trail.rb +1 -0
- data/lib/workos/challenge.rb +55 -0
- data/lib/workos/client.rb +2 -0
- data/lib/workos/connection.rb +1 -0
- data/lib/workos/deprecated_hash_wrapper.rb +76 -0
- data/lib/workos/directory.rb +1 -0
- data/lib/workos/directory_group.rb +22 -2
- data/lib/workos/directory_sync.rb +12 -8
- data/lib/workos/directory_user.rb +9 -1
- data/lib/workos/errors.rb +3 -1
- data/lib/workos/factor.rb +54 -0
- data/lib/workos/hash_provider.rb +19 -0
- data/lib/workos/mfa.rb +165 -0
- data/lib/workos/organization.rb +1 -0
- data/lib/workos/organizations.rb +1 -0
- data/lib/workos/profile.rb +1 -0
- data/lib/workos/profile_and_token.rb +1 -0
- data/lib/workos/sso.rb +1 -0
- data/lib/workos/types/challenge_struct.rb +18 -0
- data/lib/workos/types/directory_group_struct.rb +5 -0
- data/lib/workos/types/factor_struct.rb +18 -0
- data/lib/workos/types/passwordless_session_struct.rb +2 -0
- data/lib/workos/types/verify_factor_struct.rb +13 -0
- data/lib/workos/types.rb +3 -0
- data/lib/workos/verify_factor.rb +40 -0
- data/lib/workos/version.rb +1 -1
- data/lib/workos/webhook.rb +1 -0
- data/lib/workos/webhooks.rb +1 -1
- data/lib/workos.rb +7 -0
- data/spec/lib/workos/directory_sync_spec.rb +26 -18
- data/spec/lib/workos/directory_user_spec.rb +36 -0
- data/spec/lib/workos/mfa_spec.rb +262 -0
- data/spec/lib/workos/sso_spec.rb +0 -2
- data/spec/support/fixtures/vcr_cassettes/directory_sync/get_group.yml +48 -28
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_after.yml +46 -32
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_before.yml +47 -31
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_directory.yml +46 -34
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_limit.yml +41 -31
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_no_options.yml +36 -26
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_user.yml +38 -28
- data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_generic_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_sms_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_totp_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/delete_factor.yml +80 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_generic_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_sms_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_totp_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/get_factor_invalid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/get_factor_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_expired.yml +84 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_invalid.yml +84 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_valid.yml +82 -0
- data/spec/support/fixtures/vcr_cassettes/mfa/verify_factor_generic_valid_is_false.yml +82 -0
- metadata +42 -3
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/organization.rb
CHANGED
@@ -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
|
data/lib/workos/organizations.rb
CHANGED
@@ -21,6 +21,7 @@ module WorkOS
|
|
21
21
|
# @param [String] after A pagination argument used to request
|
22
22
|
# organizations after the provided Organization ID.
|
23
23
|
# @param [Integer] limit A pagination argument used to limit the number
|
24
|
+
# @param [String] order The order in which to paginate records
|
24
25
|
# of listed Organizations that are returned.
|
25
26
|
sig do
|
26
27
|
params(
|
data/lib/workos/profile.rb
CHANGED
data/lib/workos/sso.rb
CHANGED
@@ -163,6 +163,7 @@ module WorkOS
|
|
163
163
|
# @option options [String] organization_id The id of the organization
|
164
164
|
# of the connections to be retrieved.
|
165
165
|
# @option options [String] limit Maximum number of records to return.
|
166
|
+
# @option options [String] order The order in which to paginate records
|
166
167
|
# @option options [String] before Pagination cursor to receive records
|
167
168
|
# before a provided Connection ID.
|
168
169
|
# @option options [String] after Pagination cursor to receive records
|
@@ -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, 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
|
@@ -7,7 +7,12 @@ module WorkOS
|
|
7
7
|
# for the DirectoryGroup class
|
8
8
|
class DirectoryGroupStruct < T::Struct
|
9
9
|
const :id, String
|
10
|
+
const :directory_id, String
|
11
|
+
const :idp_id, String
|
10
12
|
const :name, String
|
13
|
+
const :created_at, String
|
14
|
+
const :updated_at, String
|
15
|
+
const :raw_attributes, T::Hash[Symbol, Object]
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
@@ -0,0 +1,18 @@
|
|
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 :object, String
|
11
|
+
const :type, String
|
12
|
+
const :totp, T.nilable(T::Hash[Symbol, Object])
|
13
|
+
const :sms, T.nilable(T::Hash[Symbol, Object])
|
14
|
+
const :created_at, String
|
15
|
+
const :updated_at, String
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
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::Boolean
|
11
|
+
end
|
12
|
+
end
|
13
|
+
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,40 @@
|
|
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
|
+
include HashProvider
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
attr_accessor :challenge, :valid
|
13
|
+
|
14
|
+
sig { params(json: String).void }
|
15
|
+
def initialize(json)
|
16
|
+
raw = parse_json(json)
|
17
|
+
@challenge = T.let(raw.challenge, Hash)
|
18
|
+
@valid = raw.valid
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_json(*)
|
22
|
+
{
|
23
|
+
challenge: challenge,
|
24
|
+
valid: valid,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
sig { params(json_string: String).returns(WorkOS::Types::VerifyFactorStruct) }
|
31
|
+
def parse_json(json_string)
|
32
|
+
hash = JSON.parse(json_string, symbolize_names: true)
|
33
|
+
|
34
|
+
WorkOS::Types::VerifyFactorStruct.new(
|
35
|
+
challenge: hash[:challenge],
|
36
|
+
valid: hash[:valid],
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/workos/version.rb
CHANGED
data/lib/workos/webhook.rb
CHANGED
data/lib/workos/webhooks.rb
CHANGED
data/lib/workos.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
require 'workos/version'
|
5
5
|
require 'sorbet-runtime'
|
6
6
|
require 'json'
|
7
|
+
require 'workos/hash_provider'
|
7
8
|
|
8
9
|
# Use the WorkOS module to authenticate your
|
9
10
|
# requests to the WorkOS API. The gem will read
|
@@ -44,6 +45,12 @@ module WorkOS
|
|
44
45
|
autoload :DirectoryUser, 'workos/directory_user'
|
45
46
|
autoload :Webhook, 'workos/webhook'
|
46
47
|
autoload :Webhooks, 'workos/webhooks'
|
48
|
+
autoload :MFA, 'workos/mfa'
|
49
|
+
autoload :Factor, 'workos/factor'
|
50
|
+
autoload :Challenge, 'workos/challenge'
|
51
|
+
autoload :VerifyFactor, 'workos/verify_factor'
|
52
|
+
autoload :DeprecatedHashWrapper, 'workos/deprecated_hash_wrapper'
|
53
|
+
|
47
54
|
|
48
55
|
# Errors
|
49
56
|
autoload :APIError, 'workos/errors'
|
@@ -189,7 +189,7 @@ describe WorkOS::DirectorySync do
|
|
189
189
|
context 'with directory option' do
|
190
190
|
it 'forms the proper request to the API' do
|
191
191
|
request_args = [
|
192
|
-
'/directory_groups?directory=
|
192
|
+
'/directory_groups?directory=directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
193
193
|
'Content-Type' => 'application/json'
|
194
194
|
]
|
195
195
|
|
@@ -200,10 +200,11 @@ describe WorkOS::DirectorySync do
|
|
200
200
|
|
201
201
|
VCR.use_cassette 'directory_sync/list_groups/with_directory' do
|
202
202
|
groups = described_class.list_groups(
|
203
|
-
directory: '
|
203
|
+
directory: 'directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
204
204
|
)
|
205
205
|
|
206
206
|
expect(groups.data.size).to eq(10)
|
207
|
+
expect(groups.data[0].name).to eq(groups.data[0]['name'])
|
207
208
|
end
|
208
209
|
end
|
209
210
|
end
|
@@ -211,7 +212,7 @@ describe WorkOS::DirectorySync do
|
|
211
212
|
context 'with user option' do
|
212
213
|
it 'forms the proper request to the API' do
|
213
214
|
request_args = [
|
214
|
-
'/directory_groups?user=
|
215
|
+
'/directory_groups?user=directory_user_01G2Z8D4FDB28ZNSRRBVCF2E0P',
|
215
216
|
'Content-Type' => 'application/json'
|
216
217
|
]
|
217
218
|
|
@@ -222,7 +223,7 @@ describe WorkOS::DirectorySync do
|
|
222
223
|
|
223
224
|
VCR.use_cassette 'directory_sync/list_groups/with_user' do
|
224
225
|
groups = described_class.list_groups(
|
225
|
-
user: '
|
226
|
+
user: 'directory_user_01G2Z8D4FDB28ZNSRRBVCF2E0P',
|
226
227
|
)
|
227
228
|
|
228
229
|
expect(groups.data.size).to eq(3)
|
@@ -233,8 +234,8 @@ describe WorkOS::DirectorySync do
|
|
233
234
|
context 'with the before option' do
|
234
235
|
it 'forms the proper request to the API' do
|
235
236
|
request_args = [
|
236
|
-
'/directory_groups?before=
|
237
|
-
'directory=
|
237
|
+
'/directory_groups?before=directory_group_01G2Z8D4ZR8RJ03Y1W7P9K8NMG&' \
|
238
|
+
'directory=directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
238
239
|
'Content-Type' => 'application/json'
|
239
240
|
]
|
240
241
|
|
@@ -245,11 +246,11 @@ describe WorkOS::DirectorySync do
|
|
245
246
|
|
246
247
|
VCR.use_cassette 'directory_sync/list_groups/with_before' do
|
247
248
|
groups = described_class.list_groups(
|
248
|
-
before: '
|
249
|
-
directory: '
|
249
|
+
before: 'directory_group_01G2Z8D4ZR8RJ03Y1W7P9K8NMG',
|
250
|
+
directory: 'directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
250
251
|
)
|
251
252
|
|
252
|
-
expect(groups.data.size).to eq(
|
253
|
+
expect(groups.data.size).to eq(10)
|
253
254
|
end
|
254
255
|
end
|
255
256
|
end
|
@@ -257,8 +258,8 @@ describe WorkOS::DirectorySync do
|
|
257
258
|
context 'with the after option' do
|
258
259
|
it 'forms the proper request to the API' do
|
259
260
|
request_args = [
|
260
|
-
'/directory_groups?after=
|
261
|
-
'directory=
|
261
|
+
'/directory_groups?after=directory_group_01G2Z8D4ZR8RJ03Y1W7P9K8NMG&' \
|
262
|
+
'directory=directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
262
263
|
'Content-Type' => 'application/json'
|
263
264
|
]
|
264
265
|
|
@@ -269,11 +270,11 @@ describe WorkOS::DirectorySync do
|
|
269
270
|
|
270
271
|
VCR.use_cassette 'directory_sync/list_groups/with_after' do
|
271
272
|
groups = described_class.list_groups(
|
272
|
-
after: '
|
273
|
-
directory: '
|
273
|
+
after: 'directory_group_01G2Z8D4ZR8RJ03Y1W7P9K8NMG',
|
274
|
+
directory: 'directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
274
275
|
)
|
275
276
|
|
276
|
-
expect(groups.data.size).to eq(
|
277
|
+
expect(groups.data.size).to eq(9)
|
277
278
|
end
|
278
279
|
end
|
279
280
|
end
|
@@ -282,7 +283,7 @@ describe WorkOS::DirectorySync do
|
|
282
283
|
it 'forms the proper request to the API' do
|
283
284
|
request_args = [
|
284
285
|
'/directory_groups?limit=2&' \
|
285
|
-
'directory=
|
286
|
+
'directory=directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
286
287
|
'Content-Type' => 'application/json'
|
287
288
|
]
|
288
289
|
|
@@ -294,7 +295,7 @@ describe WorkOS::DirectorySync do
|
|
294
295
|
VCR.use_cassette 'directory_sync/list_groups/with_limit' do
|
295
296
|
groups = described_class.list_groups(
|
296
297
|
limit: 2,
|
297
|
-
directory: '
|
298
|
+
directory: 'directory_01G2Z8ADK5NPMVTWF48MVVE4HT',
|
298
299
|
)
|
299
300
|
|
300
301
|
expect(groups.data.size).to eq(2)
|
@@ -332,6 +333,7 @@ describe WorkOS::DirectorySync do
|
|
332
333
|
)
|
333
334
|
|
334
335
|
expect(users.data.size).to eq(4)
|
336
|
+
expect(users.data[0].first_name).to eq(users.data[0]['first_name'])
|
335
337
|
end
|
336
338
|
end
|
337
339
|
end
|
@@ -436,10 +438,15 @@ describe WorkOS::DirectorySync do
|
|
436
438
|
it 'returns a group' do
|
437
439
|
VCR.use_cassette('directory_sync/get_group') do
|
438
440
|
group = WorkOS::DirectorySync.get_group(
|
439
|
-
'
|
441
|
+
'directory_group_01G2Z8D4ZR8RJ03Y1W7P9K8NMG',
|
440
442
|
)
|
441
443
|
|
442
|
-
expect(group['
|
444
|
+
expect(group['directory_id']).to eq('directory_01G2Z8ADK5NPMVTWF48MVVE4HT')
|
445
|
+
expect(group['idp_id']).to eq('01jlao4614two3d')
|
446
|
+
expect(group['name']).to eq('Sales')
|
447
|
+
expect(group.name).to eq('Sales')
|
448
|
+
expect(group['created_at']).to eq('2022-05-13T17:45:31.732Z')
|
449
|
+
expect(group['updated_at']).to eq('2022-06-07T17:45:35.739Z')
|
443
450
|
end
|
444
451
|
end
|
445
452
|
end
|
@@ -464,6 +471,7 @@ describe WorkOS::DirectorySync do
|
|
464
471
|
)
|
465
472
|
|
466
473
|
expect(user['first_name']).to eq('Logan')
|
474
|
+
expect(user.first_name).to eq('Logan')
|
467
475
|
end
|
468
476
|
end
|
469
477
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: false
|
3
|
+
|
4
|
+
describe WorkOS::DirectoryUser do
|
5
|
+
# rubocop:disable Layout/LineLength
|
6
|
+
describe '.get_primary_email' do
|
7
|
+
context 'with one primary email' do
|
8
|
+
it 'returns the primary email' do
|
9
|
+
user = WorkOS::DirectoryUser.new('{"object":"directory_user","id":"directory_user_01FAZYNPC8M0HRYTKFP2GNX852","directory_id":"directory_01FAZYMST676QMTFN1DDJZZX87","idp_id":"6092c280a3f1e19ef6d8cef8","username":"logan@workos.com","emails":[{"primary":true,"value":"logan@workos.com"}, {"primary":false,"value":"logan@gmail.com"}],"first_name":"Logan","last_name":"Gingerich","state":"active","raw_attributes":{},"custom_attributes":{},"groups":[]}')
|
10
|
+
expect(user.primary_email).to eq('logan@workos.com')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'with multiple primary emails' do
|
15
|
+
it 'returns the first email marked as primary' do
|
16
|
+
user = WorkOS::DirectoryUser.new('{"object":"directory_user","id":"directory_user_01FAZYNPC8M0HRYTKFP2GNX852","directory_id":"directory_01FAZYMST676QMTFN1DDJZZX87","idp_id":"6092c280a3f1e19ef6d8cef8","username":"logan@workos.com","emails":[{"primary":true,"value":"logan@workos.com"}, {"primary":true,"value":"logan@gmail.com"}],"first_name":"Logan","last_name":"Gingerich","state":"active","raw_attributes":{},"custom_attributes":{},"groups":[]}')
|
17
|
+
expect(user.primary_email).to eq('logan@workos.com')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with no primary emails' do
|
22
|
+
it 'returns nil' do
|
23
|
+
user = WorkOS::DirectoryUser.new('{"object":"directory_user","id":"directory_user_01FAZYNPC8M0HRYTKFP2GNX852","directory_id":"directory_01FAZYMST676QMTFN1DDJZZX87","idp_id":"6092c280a3f1e19ef6d8cef8","username":"logan@workos.com","emails":[{"primary":false,"value":"logan@gmail.com"}],"first_name":"Logan","last_name":"Gingerich","state":"active","raw_attributes":{},"custom_attributes":{},"groups":[]}')
|
24
|
+
expect(user.primary_email).to eq(nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with an empty email array' do
|
29
|
+
it 'returns nil' do
|
30
|
+
user = WorkOS::DirectoryUser.new('{"object":"directory_user","id":"directory_user_01FAZYNPC8M0HRYTKFP2GNX852","directory_id":"directory_01FAZYMST676QMTFN1DDJZZX87","idp_id":"6092c280a3f1e19ef6d8cef8","username":"logan@workos.com","emails":[],"first_name":"Logan","last_name":"Gingerich","state":"active","raw_attributes":{},"custom_attributes":{},"groups":[]}')
|
31
|
+
expect(user.primary_email).to eq(nil)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
# rubocop:enable Layout/LineLength
|
36
|
+
end
|