workos 0.10.0 → 1.1.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/.rubocop.yml +3 -1
- data/.ruby-version +1 -1
- data/.semaphore/semaphore.yml +10 -4
- data/Gemfile.lock +49 -36
- data/LICENSE +1 -1
- data/README.md +13 -230
- data/lib/workos/client.rb +24 -6
- data/lib/workos/connection.rb +12 -1
- data/lib/workos/directory.rb +53 -0
- data/lib/workos/directory_group.rb +44 -0
- data/lib/workos/directory_sync.rb +63 -7
- data/lib/workos/directory_user.rb +63 -0
- data/lib/workos/organizations.rb +150 -0
- data/lib/workos/passwordless.rb +4 -0
- data/lib/workos/portal.rb +1 -81
- data/lib/workos/profile.rb +9 -12
- data/lib/workos/profile_and_token.rb +28 -0
- data/lib/workos/sso.rb +56 -104
- data/lib/workos/types/connection_struct.rb +3 -0
- data/lib/workos/types/directory_group_struct.rb +13 -0
- data/lib/workos/types/directory_struct.rb +16 -0
- data/lib/workos/types/directory_user_struct.rb +19 -0
- data/lib/workos/types/intent_enum.rb +1 -0
- data/lib/workos/types.rb +3 -0
- data/lib/workos/version.rb +1 -1
- data/lib/workos.rb +5 -0
- data/sorbet/rbi/gems/addressable.rbi +199 -0
- data/sorbet/rbi/gems/ast.rbi +49 -0
- data/sorbet/rbi/gems/codecov.rbi +37 -0
- data/sorbet/rbi/gems/crack.rbi +62 -0
- data/sorbet/rbi/gems/docile.rbi +36 -0
- data/sorbet/rbi/gems/hashdiff.rbi +66 -0
- data/sorbet/rbi/gems/parallel.rbi +83 -0
- data/sorbet/rbi/gems/parser.rbi +1429 -0
- data/sorbet/rbi/gems/public_suffix.rbi +104 -0
- data/sorbet/rbi/gems/rainbow.rbi +118 -0
- data/sorbet/rbi/gems/rake.rbi +644 -0
- data/sorbet/rbi/gems/regexp_parser.rbi +926 -0
- data/sorbet/rbi/gems/rexml.rbi +628 -0
- data/sorbet/rbi/gems/rspec-core.rbi +1898 -0
- data/sorbet/rbi/gems/rspec-expectations.rbi +1127 -0
- data/sorbet/rbi/gems/rspec-mocks.rbi +1099 -0
- data/sorbet/rbi/gems/rspec-support.rbi +280 -0
- data/sorbet/rbi/gems/rspec.rbi +15 -0
- data/sorbet/rbi/gems/rubocop-ast.rbi +1355 -0
- data/sorbet/rbi/gems/rubocop.rbi +7253 -0
- data/sorbet/rbi/gems/ruby-progressbar.rbi +304 -0
- data/sorbet/rbi/gems/simplecov-html.rbi +35 -0
- data/sorbet/rbi/gems/simplecov.rbi +406 -0
- data/sorbet/rbi/gems/unicode-display_width.rbi +17 -0
- data/sorbet/rbi/gems/vcr.rbi +572 -0
- data/sorbet/rbi/gems/webmock.rbi +556 -0
- data/sorbet/rbi/gems/yard.rbi +1165 -0
- data/sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi +645 -0
- data/sorbet/rbi/sorbet-typed/lib/rspec-core/all/rspec-core.rbi +1891 -0
- data/sorbet/rbi/sorbet-typed/lib/rubocop/~>0.85/rubocop.rbi +2072 -0
- data/sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi +1214 -0
- data/sorbet/rbi/todo.rbi +1 -3
- data/spec/lib/workos/audit_trail_spec.rb +0 -8
- data/spec/lib/workos/directory_sync_spec.rb +347 -40
- data/spec/lib/workos/organizations_spec.rb +164 -0
- data/spec/lib/workos/passwordless_spec.rb +0 -8
- data/spec/lib/workos/portal_spec.rb +17 -123
- data/spec/lib/workos/sso_spec.rb +172 -173
- data/spec/spec_helper.rb +2 -1
- data/spec/support/fixtures/vcr_cassettes/directory_sync/delete_directory.yml +72 -0
- data/spec/support/fixtures/vcr_cassettes/{sso/list_connections.yml → directory_sync/list_directories/with_after.yml} +7 -7
- data/spec/support/fixtures/vcr_cassettes/{sso/list_connections_with_limit_param.yml → directory_sync/list_directories/with_before.yml} +8 -8
- data/spec/support/fixtures/vcr_cassettes/{sso/list_connections_with_connection_type_param.yml → directory_sync/list_directories/with_domain.yml} +11 -10
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_limit.yml +74 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_directories.yml → list_directories/with_no_options.yml} +1 -1
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_search.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_after.yml +76 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_before.yml +74 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_directory.yml +78 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_limit.yml +74 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_groups.yml → list_groups/with_no_options.yml} +16 -6
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_user.yml +72 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_after.yml +86 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_before.yml +75 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_directory.yml +93 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_group.yml +76 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_limit.yml +75 -0
- data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_users.yml → list_users/with_no_options.yml} +16 -6
- data/spec/support/fixtures/vcr_cassettes/organization/get.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/organization/get_invalid.yml +72 -0
- data/spec/support/fixtures/vcr_cassettes/organization/update.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/organization/update_invalid.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/portal/generate_link_dsync.yml +72 -0
- data/spec/support/fixtures/vcr_cassettes/portal/{generate_link.yml → generate_link_sso.yml} +1 -1
- data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_after.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_before.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_connection_type.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/sso/{list_connections_with_domain_param.yml → list_connections/with_domain.yml} +6 -6
- data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_limit.yml +74 -0
- data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_no_options.yml +73 -0
- data/spec/support/fixtures/vcr_cassettes/sso/{list_connections_with_before_param.yml → list_connections/with_organization_id.yml} +7 -8
- data/spec/support/fixtures/vcr_cassettes/sso/profile.yml +74 -0
- data/workos.gemspec +2 -0
- metadata +114 -43
- data/sorbet/rbi/hidden-definitions/errors.txt +0 -24896
- data/sorbet/rbi/hidden-definitions/hidden.rbi +0 -38411
- data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +0 -8684
- data/sorbet/rbi/sorbet-typed/lib/ruby/all/gem.rbi +0 -4222
- data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +0 -111
- data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +0 -543
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories_with_domain_param.yml +0 -63
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups_with_directory_param.yml +0 -62
- data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users_with_directory_param.yml +0 -62
- data/spec/support/fixtures/vcr_cassettes/sso/create_connection_with_invalid_source.yml +0 -58
- data/spec/support/fixtures/vcr_cassettes/sso/create_connection_with_valid_source.yml +0 -63
- data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_after_param.yml +0 -72
|
@@ -2,56 +2,30 @@
|
|
|
2
2
|
# typed: false
|
|
3
3
|
|
|
4
4
|
describe WorkOS::Portal do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
after :all do
|
|
10
|
-
WorkOS.key = nil
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe '.create_organization' do
|
|
14
|
-
context 'with valid payload' do
|
|
15
|
-
it 'creates an organization' do
|
|
16
|
-
VCR.use_cassette 'organization/create' do
|
|
17
|
-
organization = described_class.create_organization(
|
|
18
|
-
domains: ['example.com'],
|
|
19
|
-
name: 'Test Organization',
|
|
20
|
-
)
|
|
5
|
+
describe '.generate_link' do
|
|
6
|
+
let(:organization) { 'org_01EHQMYV6MBK39QC5PZXHY59C3' }
|
|
21
7
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
8
|
+
describe 'with a valid organization' do
|
|
9
|
+
context 'with the sso intent' do
|
|
10
|
+
it 'returns an Admin Portal link' do
|
|
11
|
+
VCR.use_cassette 'portal/generate_link_sso' do
|
|
12
|
+
portal_link = described_class.generate_link(
|
|
13
|
+
intent: 'sso',
|
|
14
|
+
organization: organization,
|
|
15
|
+
)
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
VCR.use_cassette 'organization/create_invalid' do
|
|
32
|
-
expect do
|
|
33
|
-
described_class.create_organization(
|
|
34
|
-
domains: ['example.com'],
|
|
35
|
-
name: 'Test Organization 2',
|
|
17
|
+
expect(portal_link).to eq(
|
|
18
|
+
'https://id.workos.com/portal/launch?secret=secret',
|
|
36
19
|
)
|
|
37
|
-
end
|
|
38
|
-
WorkOS::APIError,
|
|
39
|
-
/An Organization with the domain example.com already exists/,
|
|
40
|
-
)
|
|
20
|
+
end
|
|
41
21
|
end
|
|
42
22
|
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
23
|
|
|
46
|
-
|
|
47
|
-
let(:organization) { 'org_01EHQMYV6MBK39QC5PZXHY59C3' }
|
|
48
|
-
|
|
49
|
-
describe 'with a valid organization' do
|
|
50
|
-
describe 'with the minimal params' do
|
|
24
|
+
describe 'with the dsync intent' do
|
|
51
25
|
it 'returns an Admin Portal link' do
|
|
52
|
-
VCR.use_cassette 'portal/
|
|
26
|
+
VCR.use_cassette 'portal/generate_link_dsync' do
|
|
53
27
|
portal_link = described_class.generate_link(
|
|
54
|
-
intent: '
|
|
28
|
+
intent: 'dsync',
|
|
55
29
|
organization: organization,
|
|
56
30
|
)
|
|
57
31
|
|
|
@@ -88,89 +62,9 @@ describe WorkOS::Portal do
|
|
|
88
62
|
)
|
|
89
63
|
end.to raise_error(
|
|
90
64
|
ArgumentError,
|
|
91
|
-
|
|
65
|
+
/bogus-intent is not a valid value/,
|
|
92
66
|
)
|
|
93
67
|
end
|
|
94
68
|
end
|
|
95
69
|
end
|
|
96
|
-
|
|
97
|
-
describe '.list_organizations' do
|
|
98
|
-
context 'with no options' do
|
|
99
|
-
it 'returns organizations and metadata' do
|
|
100
|
-
expected_metadata = {
|
|
101
|
-
'after' => nil,
|
|
102
|
-
'before' => 'before-id',
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
VCR.use_cassette 'organization/list' do
|
|
106
|
-
organizations = described_class.list_organizations
|
|
107
|
-
|
|
108
|
-
expect(organizations.data.size).to eq(7)
|
|
109
|
-
expect(organizations.list_metadata).to eq(expected_metadata)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
context 'with the before option' do
|
|
115
|
-
it 'forms the proper request to the API' do
|
|
116
|
-
request_args = [
|
|
117
|
-
'/organizations?before=before-id',
|
|
118
|
-
'Content-Type' => 'application/json'
|
|
119
|
-
]
|
|
120
|
-
|
|
121
|
-
expected_request = Net::HTTP::Get.new(*request_args)
|
|
122
|
-
|
|
123
|
-
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
124
|
-
and_return(expected_request)
|
|
125
|
-
|
|
126
|
-
VCR.use_cassette 'organization/list', match_requests_on: [:path] do
|
|
127
|
-
organizations = described_class.list_organizations(
|
|
128
|
-
before: 'before-id',
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
expect(organizations.data.size).to eq(7)
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
context 'with the after option' do
|
|
137
|
-
it 'forms the proper request to the API' do
|
|
138
|
-
request_args = [
|
|
139
|
-
'/organizations?after=after-id',
|
|
140
|
-
'Content-Type' => 'application/json'
|
|
141
|
-
]
|
|
142
|
-
|
|
143
|
-
expected_request = Net::HTTP::Get.new(*request_args)
|
|
144
|
-
|
|
145
|
-
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
146
|
-
and_return(expected_request)
|
|
147
|
-
|
|
148
|
-
VCR.use_cassette 'organization/list', match_requests_on: [:path] do
|
|
149
|
-
organizations = described_class.list_organizations(after: 'after-id')
|
|
150
|
-
|
|
151
|
-
expect(organizations.data.size).to eq(7)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
context 'with the limit option' do
|
|
157
|
-
it 'forms the proper request to the API' do
|
|
158
|
-
request_args = [
|
|
159
|
-
'/organizations?limit=10',
|
|
160
|
-
'Content-Type' => 'application/json'
|
|
161
|
-
]
|
|
162
|
-
|
|
163
|
-
expected_request = Net::HTTP::Get.new(*request_args)
|
|
164
|
-
|
|
165
|
-
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
166
|
-
and_return(expected_request)
|
|
167
|
-
|
|
168
|
-
VCR.use_cassette 'organization/list', match_requests_on: [:path] do
|
|
169
|
-
organizations = described_class.list_organizations(limit: 10)
|
|
170
|
-
|
|
171
|
-
expect(organizations.data.size).to eq(7)
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
70
|
end
|
data/spec/lib/workos/sso_spec.rb
CHANGED
|
@@ -73,9 +73,10 @@ describe WorkOS::SSO do
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
context 'with
|
|
76
|
+
context 'with a connection' do
|
|
77
77
|
let(:args) do
|
|
78
78
|
{
|
|
79
|
+
connection: 'connection_123',
|
|
79
80
|
client_id: 'workos-proj-123',
|
|
80
81
|
redirect_uri: 'foo.com/auth/callback',
|
|
81
82
|
state: {
|
|
@@ -83,20 +84,32 @@ describe WorkOS::SSO do
|
|
|
83
84
|
}.to_s,
|
|
84
85
|
}
|
|
85
86
|
end
|
|
86
|
-
it '
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
it 'returns a valid URL' do
|
|
88
|
+
authorization_url = described_class.authorization_url(**args)
|
|
89
|
+
|
|
90
|
+
expect(URI.parse(authorization_url)).to be_a URI
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'returns the expected hostname' do
|
|
94
|
+
authorization_url = described_class.authorization_url(**args)
|
|
95
|
+
|
|
96
|
+
expect(URI.parse(authorization_url).host).to eq(WorkOS::API_HOSTNAME)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'returns the expected query string' do
|
|
100
|
+
authorization_url = described_class.authorization_url(**args)
|
|
101
|
+
|
|
102
|
+
expect(URI.parse(authorization_url).query).to eq(
|
|
103
|
+
'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
|
|
104
|
+
'&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
|
|
105
|
+
'edit%22%7D&connection=connection_123',
|
|
92
106
|
)
|
|
93
107
|
end
|
|
94
108
|
end
|
|
95
109
|
|
|
96
|
-
context 'with
|
|
110
|
+
context 'with neither connection, domain, or provider' do
|
|
97
111
|
let(:args) do
|
|
98
112
|
{
|
|
99
|
-
provider: 'Okta',
|
|
100
113
|
client_id: 'workos-proj-123',
|
|
101
114
|
redirect_uri: 'foo.com/auth/callback',
|
|
102
115
|
state: {
|
|
@@ -109,60 +122,65 @@ describe WorkOS::SSO do
|
|
|
109
122
|
described_class.authorization_url(**args)
|
|
110
123
|
end.to raise_error(
|
|
111
124
|
ArgumentError,
|
|
112
|
-
'
|
|
125
|
+
'Either connection, domain, or provider is required.',
|
|
113
126
|
)
|
|
114
127
|
end
|
|
115
128
|
end
|
|
116
129
|
|
|
117
|
-
context '
|
|
130
|
+
context 'with an invalid provider' do
|
|
118
131
|
let(:args) do
|
|
119
132
|
{
|
|
120
|
-
|
|
121
|
-
|
|
133
|
+
provider: 'Okta',
|
|
134
|
+
client_id: 'workos-proj-123',
|
|
122
135
|
redirect_uri: 'foo.com/auth/callback',
|
|
123
136
|
state: {
|
|
124
137
|
next_page: '/dashboard/edit',
|
|
125
138
|
}.to_s,
|
|
126
139
|
}
|
|
127
140
|
end
|
|
128
|
-
it 'raises
|
|
141
|
+
it 'raises an error' do
|
|
129
142
|
expect do
|
|
130
143
|
described_class.authorization_url(**args)
|
|
131
|
-
end.to
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
)
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
it 'returns a valid URL' do
|
|
138
|
-
authorization_url = described_class.authorization_url(**args)
|
|
139
|
-
|
|
140
|
-
expect(URI.parse(authorization_url)).to be_a URI
|
|
144
|
+
end.to raise_error(
|
|
145
|
+
ArgumentError,
|
|
146
|
+
'Okta is not a valid value. `provider` must be in ["GoogleOAuth"]',
|
|
147
|
+
)
|
|
141
148
|
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
142
151
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
end
|
|
152
|
+
describe '.get_profile' do
|
|
153
|
+
it 'returns a profile' do
|
|
154
|
+
VCR.use_cassette 'sso/profile' do
|
|
155
|
+
profile = described_class.get_profile(access_token: 'access_token')
|
|
148
156
|
|
|
149
|
-
|
|
150
|
-
|
|
157
|
+
expectation = {
|
|
158
|
+
connection_id: 'conn_01E83FVYZHY7DM4S9503JHV0R5',
|
|
159
|
+
connection_type: 'GoogleOAuth',
|
|
160
|
+
email: 'bob.loblaw@workos.com',
|
|
161
|
+
first_name: 'Bob',
|
|
162
|
+
id: 'prof_01EEJTY9SZ1R350RB7B73SNBKF',
|
|
163
|
+
idp_id: '116485463307139932699',
|
|
164
|
+
last_name: 'Loblaw',
|
|
165
|
+
raw_attributes: {
|
|
166
|
+
email: 'bob.loblaw@workos.com',
|
|
167
|
+
family_name: 'Loblaw',
|
|
168
|
+
given_name: 'Bob',
|
|
169
|
+
hd: 'workos.com',
|
|
170
|
+
id: '116485463307139932699',
|
|
171
|
+
locale: 'en',
|
|
172
|
+
name: 'Bob Loblaw',
|
|
173
|
+
picture: 'https://lh3.googleusercontent.com/a-/AOh14GyO2hLlgZvteDQ3Ldi3_-RteZLya0hWH7247Cam=s96-c',
|
|
174
|
+
verified_email: true,
|
|
175
|
+
},
|
|
176
|
+
}
|
|
151
177
|
|
|
152
|
-
expect(
|
|
153
|
-
'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
|
|
154
|
-
'&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
|
|
155
|
-
'edit%22%7D&domain=foo.com',
|
|
156
|
-
)
|
|
178
|
+
expect(profile.to_json).to eq(expectation)
|
|
157
179
|
end
|
|
158
180
|
end
|
|
159
181
|
end
|
|
160
182
|
|
|
161
|
-
describe '.
|
|
162
|
-
before do
|
|
163
|
-
WorkOS.key = 'api-key'
|
|
164
|
-
end
|
|
165
|
-
|
|
183
|
+
describe '.profile_and_token' do
|
|
166
184
|
let(:args) do
|
|
167
185
|
{
|
|
168
186
|
code: SecureRandom.hex(10),
|
|
@@ -195,15 +213,15 @@ describe WorkOS::SSO do
|
|
|
195
213
|
end
|
|
196
214
|
|
|
197
215
|
it 'includes the SDK Version header' do
|
|
198
|
-
described_class.
|
|
216
|
+
described_class.profile_and_token(**args)
|
|
199
217
|
|
|
200
218
|
expect(a_request(:post, 'https://api.workos.com/sso/token').
|
|
201
219
|
with(headers: headers, body: request_body)).to have_been_made
|
|
202
220
|
end
|
|
203
221
|
|
|
204
|
-
it 'returns a WorkOS::
|
|
205
|
-
|
|
206
|
-
expect(
|
|
222
|
+
it 'returns a WorkOS::ProfileAndToken' do
|
|
223
|
+
profile_and_token = described_class.profile_and_token(**args)
|
|
224
|
+
expect(profile_and_token).to be_a(WorkOS::ProfileAndToken)
|
|
207
225
|
|
|
208
226
|
expectation = {
|
|
209
227
|
connection_id: 'conn_01EMH8WAK20T42N2NBMNBCYHAG',
|
|
@@ -222,7 +240,8 @@ describe WorkOS::SSO do
|
|
|
222
240
|
},
|
|
223
241
|
}
|
|
224
242
|
|
|
225
|
-
expect(
|
|
243
|
+
expect(profile_and_token.access_token).to eq('01DVX6QBS3EG6FHY2ESAA5Q65X')
|
|
244
|
+
expect(profile_and_token.profile.to_json).to eq(expectation)
|
|
226
245
|
end
|
|
227
246
|
end
|
|
228
247
|
|
|
@@ -239,7 +258,7 @@ describe WorkOS::SSO do
|
|
|
239
258
|
|
|
240
259
|
it 'raises an exception with request ID' do
|
|
241
260
|
expect do
|
|
242
|
-
described_class.
|
|
261
|
+
described_class.profile_and_token(**args)
|
|
243
262
|
end.to raise_error(
|
|
244
263
|
WorkOS::APIError,
|
|
245
264
|
'some error message - request ID: request-id',
|
|
@@ -263,7 +282,7 @@ describe WorkOS::SSO do
|
|
|
263
282
|
|
|
264
283
|
it 'raises an exception' do
|
|
265
284
|
expect do
|
|
266
|
-
described_class.
|
|
285
|
+
described_class.profile_and_token(**args)
|
|
267
286
|
end.to raise_error(
|
|
268
287
|
WorkOS::APIError,
|
|
269
288
|
"The code '01DVX3C5Z367SFHR8QNDMK7V24'" \
|
|
@@ -273,173 +292,161 @@ describe WorkOS::SSO do
|
|
|
273
292
|
end
|
|
274
293
|
end
|
|
275
294
|
|
|
276
|
-
describe '.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
context 'with a valid source' do
|
|
286
|
-
it 'creates a connection' do
|
|
287
|
-
VCR.use_cassette('sso/create_connection_with_valid_source') do
|
|
288
|
-
connection = WorkOS::SSO.create_connection(
|
|
289
|
-
source: 'draft_conn_01E6PK87QP6NQ29RRX0G100YGV',
|
|
290
|
-
)
|
|
295
|
+
describe '.list_connections' do
|
|
296
|
+
context 'with no options' do
|
|
297
|
+
it 'returns connections and metadata' do
|
|
298
|
+
expected_metadata = {
|
|
299
|
+
'after' => nil,
|
|
300
|
+
'before' => 'before_id',
|
|
301
|
+
}
|
|
291
302
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
expect(connection.name).to eq('Foo Corp')
|
|
295
|
-
expect(connection.domains.first[:domain]).to eq('example.com')
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
end
|
|
303
|
+
VCR.use_cassette 'sso/list_connections/with_no_options' do
|
|
304
|
+
connections = described_class.list_connections
|
|
299
305
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
VCR.use_cassette('sso/create_connection_with_invalid_source') do
|
|
303
|
-
expect do
|
|
304
|
-
WorkOS::SSO.create_connection(source: 'invalid')
|
|
305
|
-
end.to raise_error(
|
|
306
|
-
WorkOS::APIError,
|
|
307
|
-
'Status 404, Not Found - request ID: ',
|
|
308
|
-
)
|
|
306
|
+
expect(connections.data.size).to eq(3)
|
|
307
|
+
expect(connections.list_metadata).to eq(expected_metadata)
|
|
309
308
|
end
|
|
310
309
|
end
|
|
311
310
|
end
|
|
312
|
-
end
|
|
313
311
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
312
|
+
context 'with connection_type option' do
|
|
313
|
+
it 'forms the proper request to the API' do
|
|
314
|
+
request_args = [
|
|
315
|
+
'/connections?connection_type=OktaSAML',
|
|
316
|
+
'Content-Type' => 'application/json'
|
|
317
|
+
]
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
WorkOS.key = nil
|
|
321
|
-
end
|
|
319
|
+
expected_request = Net::HTTP::Get.new(*request_args)
|
|
322
320
|
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
322
|
+
and_return(expected_request)
|
|
325
323
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
"https://api.workos.com/draft_connections/#{token}/activate",
|
|
331
|
-
).to_return(status: 200)
|
|
332
|
-
end
|
|
333
|
-
it 'returns true' do
|
|
334
|
-
response = described_class.promote_draft_connection(
|
|
335
|
-
token: token,
|
|
336
|
-
)
|
|
324
|
+
VCR.use_cassette 'sso/list_connections/with_connection_type' do
|
|
325
|
+
connections = described_class.list_connections(
|
|
326
|
+
connection_type: 'OktaSAML',
|
|
327
|
+
)
|
|
337
328
|
|
|
338
|
-
|
|
329
|
+
expect(connections.data.size).to eq(3)
|
|
330
|
+
expect(connections.data.first.connection_type).to eq('OktaSAML')
|
|
331
|
+
end
|
|
339
332
|
end
|
|
340
333
|
end
|
|
341
334
|
|
|
342
|
-
context 'with
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
end
|
|
349
|
-
it 'returns true' do
|
|
350
|
-
response = described_class.promote_draft_connection(
|
|
351
|
-
token: token,
|
|
352
|
-
)
|
|
335
|
+
context 'with domain option' do
|
|
336
|
+
it 'forms the proper request to the API' do
|
|
337
|
+
request_args = [
|
|
338
|
+
'/connections?domain=foo-corp.com',
|
|
339
|
+
'Content-Type' => 'application/json'
|
|
340
|
+
]
|
|
353
341
|
|
|
354
|
-
|
|
355
|
-
end
|
|
356
|
-
end
|
|
357
|
-
end
|
|
342
|
+
expected_request = Net::HTTP::Get.new(*request_args)
|
|
358
343
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
WorkOS.key = 'key'
|
|
362
|
-
end
|
|
344
|
+
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
345
|
+
and_return(expected_request)
|
|
363
346
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
347
|
+
VCR.use_cassette 'sso/list_connections/with_domain' do
|
|
348
|
+
connections = described_class.list_connections(
|
|
349
|
+
domain: 'foo-corp.com',
|
|
350
|
+
)
|
|
367
351
|
|
|
368
|
-
|
|
369
|
-
it 'returns connections' do
|
|
370
|
-
VCR.use_cassette('sso/list_connections') do
|
|
371
|
-
connections = WorkOS::SSO.list_connections
|
|
372
|
-
expect(connections.size).to eq(1)
|
|
352
|
+
expect(connections.data.size).to eq(1)
|
|
373
353
|
end
|
|
374
354
|
end
|
|
375
355
|
end
|
|
376
356
|
|
|
377
|
-
context 'with
|
|
378
|
-
it '
|
|
379
|
-
|
|
380
|
-
connections
|
|
381
|
-
|
|
357
|
+
context 'with organization_id option' do
|
|
358
|
+
it 'forms the proper request to the API' do
|
|
359
|
+
request_args = [
|
|
360
|
+
'/connections?organization_id=org_01EGS4P7QR31EZ4YWD1Z1XA176',
|
|
361
|
+
'Content-Type' => 'application/json'
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
expected_request = Net::HTTP::Get.new(*request_args)
|
|
365
|
+
|
|
366
|
+
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
367
|
+
and_return(expected_request)
|
|
368
|
+
|
|
369
|
+
VCR.use_cassette 'sso/list_connections/with_organization_id' do
|
|
370
|
+
connections = described_class.list_connections(
|
|
371
|
+
organization_id: 'org_01EGS4P7QR31EZ4YWD1Z1XA176',
|
|
382
372
|
)
|
|
383
|
-
expect(connections.first['connection_type']).to eq('OktaSAML')
|
|
384
|
-
end
|
|
385
|
-
end
|
|
386
|
-
end
|
|
387
373
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
connections = WorkOS::SSO.list_connections(
|
|
392
|
-
domain: 'foo-corp.com',
|
|
374
|
+
expect(connections.data.size).to eq(1)
|
|
375
|
+
expect(connections.data.first.organization_id).to eq(
|
|
376
|
+
'org_01EGS4P7QR31EZ4YWD1Z1XA176',
|
|
393
377
|
)
|
|
394
|
-
domains = connections.first['domains']
|
|
395
|
-
expect(domains.first['domain']).to eq('foo-corp.com')
|
|
396
378
|
end
|
|
397
379
|
end
|
|
398
380
|
end
|
|
399
381
|
|
|
400
382
|
context 'with limit option' do
|
|
401
|
-
it '
|
|
402
|
-
|
|
403
|
-
connections
|
|
404
|
-
|
|
383
|
+
it 'forms the proper request to the API' do
|
|
384
|
+
request_args = [
|
|
385
|
+
'/connections?limit=2',
|
|
386
|
+
'Content-Type' => 'application/json'
|
|
387
|
+
]
|
|
388
|
+
|
|
389
|
+
expected_request = Net::HTTP::Get.new(*request_args)
|
|
390
|
+
|
|
391
|
+
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
392
|
+
and_return(expected_request)
|
|
393
|
+
|
|
394
|
+
VCR.use_cassette 'sso/list_connections/with_limit' do
|
|
395
|
+
connections = described_class.list_connections(
|
|
396
|
+
limit: 2,
|
|
405
397
|
)
|
|
406
|
-
|
|
398
|
+
|
|
399
|
+
expect(connections.data.size).to eq(2)
|
|
407
400
|
end
|
|
408
401
|
end
|
|
409
402
|
end
|
|
410
403
|
|
|
411
404
|
context 'with before option' do
|
|
412
|
-
it '
|
|
413
|
-
|
|
414
|
-
connections
|
|
405
|
+
it 'forms the proper request to the API' do
|
|
406
|
+
request_args = [
|
|
407
|
+
'/connections?before=conn_01EQKPMQAPV02H270HKVNS4CTA',
|
|
408
|
+
'Content-Type' => 'application/json'
|
|
409
|
+
]
|
|
410
|
+
|
|
411
|
+
expected_request = Net::HTTP::Get.new(*request_args)
|
|
412
|
+
|
|
413
|
+
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
414
|
+
and_return(expected_request)
|
|
415
|
+
|
|
416
|
+
VCR.use_cassette 'sso/list_connections/with_before' do
|
|
417
|
+
connections = described_class.list_connections(
|
|
415
418
|
before: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
|
|
416
419
|
)
|
|
417
|
-
|
|
420
|
+
|
|
421
|
+
expect(connections.data.size).to eq(3)
|
|
418
422
|
end
|
|
419
423
|
end
|
|
420
424
|
end
|
|
421
425
|
|
|
422
426
|
context 'with after option' do
|
|
423
|
-
it '
|
|
424
|
-
|
|
425
|
-
connections
|
|
427
|
+
it 'forms the proper request to the API' do
|
|
428
|
+
request_args = [
|
|
429
|
+
'/connections?after=conn_01EQKPMQAPV02H270HKVNS4CTA',
|
|
430
|
+
'Content-Type' => 'application/json'
|
|
431
|
+
]
|
|
432
|
+
|
|
433
|
+
expected_request = Net::HTTP::Get.new(*request_args)
|
|
434
|
+
|
|
435
|
+
expect(Net::HTTP::Get).to receive(:new).with(*request_args).
|
|
436
|
+
and_return(expected_request)
|
|
437
|
+
|
|
438
|
+
VCR.use_cassette 'sso/list_connections/with_after' do
|
|
439
|
+
connections = described_class.list_connections(
|
|
426
440
|
after: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
|
|
427
441
|
)
|
|
428
|
-
|
|
442
|
+
|
|
443
|
+
expect(connections.data.size).to eq(3)
|
|
429
444
|
end
|
|
430
445
|
end
|
|
431
446
|
end
|
|
432
447
|
end
|
|
433
448
|
|
|
434
449
|
describe '.get_connection' do
|
|
435
|
-
before(:all) do
|
|
436
|
-
WorkOS.key = 'key'
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
after(:all) do
|
|
440
|
-
WorkOS.key = nil
|
|
441
|
-
end
|
|
442
|
-
|
|
443
450
|
context 'with a valid id' do
|
|
444
451
|
it 'gets the connection details' do
|
|
445
452
|
VCR.use_cassette('sso/get_connection_with_valid_id') do
|
|
@@ -470,14 +477,6 @@ describe WorkOS::SSO do
|
|
|
470
477
|
end
|
|
471
478
|
|
|
472
479
|
describe '.delete_connection' do
|
|
473
|
-
before(:all) do
|
|
474
|
-
WorkOS.key = 'key'
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
after(:all) do
|
|
478
|
-
WorkOS.key = nil
|
|
479
|
-
end
|
|
480
|
-
|
|
481
480
|
context 'with a valid id' do
|
|
482
481
|
it 'returns true' do
|
|
483
482
|
VCR.use_cassette('sso/delete_connection_with_valid_id') do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: false
|
|
3
3
|
|
|
4
4
|
require 'simplecov'
|
|
5
5
|
SimpleCov.start
|
|
@@ -48,5 +48,6 @@ RSpec.configure do |config|
|
|
|
48
48
|
end
|
|
49
49
|
end)
|
|
50
50
|
|
|
51
|
+
config.before(:all) { WorkOS.key ||= '' }
|
|
51
52
|
config.before(:each) { VCR.turn_on! }
|
|
52
53
|
end
|