workos 0.9.0 → 1.0.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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +5 -0
  3. data/.rubocop.yml +5 -1
  4. data/.ruby-version +1 -1
  5. data/.semaphore/semaphore.yml +8 -2
  6. data/Gemfile.lock +49 -36
  7. data/LICENSE +1 -1
  8. data/README.md +13 -167
  9. data/docs/WorkOS/SSO.html +235 -235
  10. data/docs/file.README.html +20 -20
  11. data/lib/workos/audit_trail.rb +1 -0
  12. data/lib/workos/client.rb +42 -4
  13. data/lib/workos/connection.rb +12 -3
  14. data/lib/workos/directory.rb +53 -0
  15. data/lib/workos/directory_group.rb +44 -0
  16. data/lib/workos/directory_sync.rb +63 -7
  17. data/lib/workos/directory_user.rb +63 -0
  18. data/lib/workos/organization.rb +0 -2
  19. data/lib/workos/organizations.rb +150 -0
  20. data/lib/workos/passwordless.rb +7 -2
  21. data/lib/workos/portal.rb +1 -87
  22. data/lib/workos/profile.rb +3 -6
  23. data/lib/workos/profile_and_token.rb +28 -0
  24. data/lib/workos/sso.rb +106 -65
  25. data/lib/workos/types/connection_struct.rb +3 -0
  26. data/lib/workos/types/directory_group_struct.rb +13 -0
  27. data/lib/workos/types/directory_struct.rb +16 -0
  28. data/lib/workos/types/directory_user_struct.rb +19 -0
  29. data/lib/workos/types/intent_enum.rb +1 -0
  30. data/lib/workos/types.rb +3 -0
  31. data/lib/workos/version.rb +1 -1
  32. data/lib/workos.rb +6 -0
  33. data/sorbet/rbi/gems/addressable.rbi +199 -0
  34. data/sorbet/rbi/gems/ast.rbi +49 -0
  35. data/sorbet/rbi/gems/codecov.rbi +37 -0
  36. data/sorbet/rbi/gems/crack.rbi +62 -0
  37. data/sorbet/rbi/gems/docile.rbi +36 -0
  38. data/sorbet/rbi/gems/hashdiff.rbi +66 -0
  39. data/sorbet/rbi/gems/parallel.rbi +83 -0
  40. data/sorbet/rbi/gems/parser.rbi +1429 -0
  41. data/sorbet/rbi/gems/public_suffix.rbi +104 -0
  42. data/sorbet/rbi/gems/rainbow.rbi +118 -0
  43. data/sorbet/rbi/gems/rake.rbi +644 -0
  44. data/sorbet/rbi/gems/regexp_parser.rbi +926 -0
  45. data/sorbet/rbi/gems/rexml.rbi +628 -0
  46. data/sorbet/rbi/gems/rspec-core.rbi +1898 -0
  47. data/sorbet/rbi/gems/rspec-expectations.rbi +1127 -0
  48. data/sorbet/rbi/gems/rspec-mocks.rbi +1099 -0
  49. data/sorbet/rbi/gems/rspec-support.rbi +280 -0
  50. data/sorbet/rbi/gems/rspec.rbi +15 -0
  51. data/sorbet/rbi/gems/rubocop-ast.rbi +1355 -0
  52. data/sorbet/rbi/gems/rubocop.rbi +7253 -0
  53. data/sorbet/rbi/gems/ruby-progressbar.rbi +304 -0
  54. data/sorbet/rbi/gems/simplecov-html.rbi +35 -0
  55. data/sorbet/rbi/gems/simplecov.rbi +406 -0
  56. data/sorbet/rbi/gems/unicode-display_width.rbi +17 -0
  57. data/sorbet/rbi/gems/vcr.rbi +572 -0
  58. data/sorbet/rbi/gems/webmock.rbi +556 -0
  59. data/sorbet/rbi/gems/yard.rbi +1165 -0
  60. data/sorbet/rbi/sorbet-typed/lib/rake/all/rake.rbi +645 -0
  61. data/sorbet/rbi/sorbet-typed/lib/rspec-core/all/rspec-core.rbi +1891 -0
  62. data/sorbet/rbi/sorbet-typed/lib/rubocop/~>0.85/rubocop.rbi +2072 -0
  63. data/sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi +1214 -0
  64. data/sorbet/rbi/todo.rbi +1 -3
  65. data/spec/lib/workos/audit_trail_spec.rb +0 -8
  66. data/spec/lib/workos/directory_sync_spec.rb +347 -40
  67. data/spec/lib/workos/organizations_spec.rb +164 -0
  68. data/spec/lib/workos/passwordless_spec.rb +1 -8
  69. data/spec/lib/workos/portal_spec.rb +17 -123
  70. data/spec/lib/workos/sso_spec.rb +230 -71
  71. data/spec/spec_helper.rb +2 -1
  72. data/spec/support/fixtures/vcr_cassettes/audit_trail/get_events.yml +2 -2
  73. data/spec/support/fixtures/vcr_cassettes/directory_sync/delete_directory.yml +72 -0
  74. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_after.yml +72 -0
  75. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_before.yml +72 -0
  76. data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_directories_with_domain_param.yml → list_directories/with_domain.yml} +19 -9
  77. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_limit.yml +74 -0
  78. data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_directories.yml → list_directories/with_no_options.yml} +1 -1
  79. data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_users_with_directory_param.yml → list_directories/with_search.yml} +22 -11
  80. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_after.yml +76 -0
  81. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_before.yml +74 -0
  82. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_directory.yml +78 -0
  83. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_limit.yml +74 -0
  84. data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_groups.yml → list_groups/with_no_options.yml} +16 -6
  85. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_groups/with_user.yml +72 -0
  86. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_after.yml +86 -0
  87. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_before.yml +75 -0
  88. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_directory.yml +93 -0
  89. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_group.yml +76 -0
  90. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_users/with_limit.yml +75 -0
  91. data/spec/support/fixtures/vcr_cassettes/directory_sync/{list_users.yml → list_users/with_no_options.yml} +16 -6
  92. data/spec/support/fixtures/vcr_cassettes/organization/get.yml +73 -0
  93. data/spec/support/fixtures/vcr_cassettes/{directory_sync/list_groups_with_directory_param.yml → organization/get_invalid.yml} +21 -11
  94. data/spec/support/fixtures/vcr_cassettes/organization/update.yml +73 -0
  95. data/spec/support/fixtures/vcr_cassettes/organization/update_invalid.yml +73 -0
  96. data/spec/support/fixtures/vcr_cassettes/portal/generate_link_dsync.yml +72 -0
  97. data/spec/support/fixtures/vcr_cassettes/portal/{generate_link.yml → generate_link_sso.yml} +1 -1
  98. data/spec/support/fixtures/vcr_cassettes/sso/delete_connection_with_invalid_id.yml +72 -0
  99. data/spec/support/fixtures/vcr_cassettes/sso/delete_connection_with_valid_id.yml +70 -0
  100. data/spec/support/fixtures/vcr_cassettes/sso/{create_connection_with_invalid_source.yml → get_connection_with_invalid_id.yml} +26 -12
  101. data/spec/support/fixtures/vcr_cassettes/sso/get_connection_with_valid_id.yml +74 -0
  102. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_after.yml +73 -0
  103. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_before.yml +73 -0
  104. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_connection_type.yml +73 -0
  105. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_domain.yml +72 -0
  106. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_limit.yml +74 -0
  107. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_no_options.yml +73 -0
  108. data/spec/support/fixtures/vcr_cassettes/sso/list_connections/with_organization_id.yml +72 -0
  109. data/workos.gemspec +2 -0
  110. metadata +122 -33
  111. data/CODEOWNERS +0 -1
  112. data/sorbet/rbi/hidden-definitions/errors.txt +0 -24896
  113. data/sorbet/rbi/hidden-definitions/hidden.rbi +0 -38411
  114. data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +0 -8684
  115. data/sorbet/rbi/sorbet-typed/lib/ruby/all/gem.rbi +0 -4222
  116. data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +0 -111
  117. data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +0 -543
  118. data/spec/support/fixtures/vcr_cassettes/sso/create_connection_with_valid_source.yml +0 -63
@@ -2,56 +2,30 @@
2
2
  # typed: false
3
3
 
4
4
  describe WorkOS::Portal do
5
- before :all do
6
- WorkOS.key = 'test'
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
- expect(organization.id).to eq('org_01EHT88Z8J8795GZNQ4ZP1J81T')
23
- expect(organization.name).to eq('Test Organization')
24
- expect(organization.domains.first[:domain]).to eq('example.com')
25
- end
26
- end
27
- end
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
- context 'with an invalid payload' do
30
- it 'returns an error' do
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.to raise_error(
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
- describe '.generate_link' do
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/generate_link' do
26
+ VCR.use_cassette 'portal/generate_link_dsync' do
53
27
  portal_link = described_class.generate_link(
54
- intent: 'sso',
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
- 'bogus-intent is not a valid value. `intent` must be in ["sso"]',
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
@@ -9,7 +9,7 @@ describe WorkOS::SSO do
9
9
  let(:args) do
10
10
  {
11
11
  domain: 'foo.com',
12
- project_id: 'workos-proj-123',
12
+ client_id: 'workos-proj-123',
13
13
  redirect_uri: 'foo.com/auth/callback',
14
14
  state: {
15
15
  next_page: '/dashboard/edit',
@@ -43,7 +43,7 @@ describe WorkOS::SSO do
43
43
  let(:args) do
44
44
  {
45
45
  provider: 'GoogleOAuth',
46
- project_id: 'workos-proj-123',
46
+ client_id: 'workos-proj-123',
47
47
  redirect_uri: 'foo.com/auth/callback',
48
48
  state: {
49
49
  next_page: '/dashboard/edit',
@@ -73,10 +73,44 @@ describe WorkOS::SSO do
73
73
  end
74
74
  end
75
75
 
76
- context 'with neither domain or provider' do
76
+ context 'with a connection' do
77
77
  let(:args) do
78
78
  {
79
- project_id: 'workos-proj-123',
79
+ connection: 'connection_123',
80
+ client_id: 'workos-proj-123',
81
+ redirect_uri: 'foo.com/auth/callback',
82
+ state: {
83
+ next_page: '/dashboard/edit',
84
+ }.to_s,
85
+ }
86
+ end
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',
106
+ )
107
+ end
108
+ end
109
+
110
+ context 'with neither connection, domain, or provider' do
111
+ let(:args) do
112
+ {
113
+ client_id: 'workos-proj-123',
80
114
  redirect_uri: 'foo.com/auth/callback',
81
115
  state: {
82
116
  next_page: '/dashboard/edit',
@@ -88,7 +122,7 @@ describe WorkOS::SSO do
88
122
  described_class.authorization_url(**args)
89
123
  end.to raise_error(
90
124
  ArgumentError,
91
- 'Either domain or provider is required.',
125
+ 'Either connection, domain, or provider is required.',
92
126
  )
93
127
  end
94
128
  end
@@ -97,7 +131,7 @@ describe WorkOS::SSO do
97
131
  let(:args) do
98
132
  {
99
133
  provider: 'Okta',
100
- project_id: 'workos-proj-123',
134
+ client_id: 'workos-proj-123',
101
135
  redirect_uri: 'foo.com/auth/callback',
102
136
  state: {
103
137
  next_page: '/dashboard/edit',
@@ -115,21 +149,17 @@ describe WorkOS::SSO do
115
149
  end
116
150
  end
117
151
 
118
- describe '.profile' do
119
- before do
120
- WorkOS.key = 'api-key'
121
- end
122
-
152
+ describe '.profile_and_token' do
123
153
  let(:args) do
124
154
  {
125
155
  code: SecureRandom.hex(10),
126
- project_id: 'workos-proj-123',
156
+ client_id: 'workos-proj-123',
127
157
  }
128
158
  end
129
159
 
130
160
  let(:request_body) do
131
161
  {
132
- client_id: args[:project_id],
162
+ client_id: args[:client_id],
133
163
  client_secret: WorkOS.key,
134
164
  code: args[:code],
135
165
  grant_type: 'authorization_code',
@@ -152,15 +182,15 @@ describe WorkOS::SSO do
152
182
  end
153
183
 
154
184
  it 'includes the SDK Version header' do
155
- described_class.profile(**args)
185
+ described_class.profile_and_token(**args)
156
186
 
157
187
  expect(a_request(:post, 'https://api.workos.com/sso/token').
158
188
  with(headers: headers, body: request_body)).to have_been_made
159
189
  end
160
190
 
161
- it 'returns a WorkOS::Profile' do
162
- profile = described_class.profile(**args)
163
- expect(profile).to be_a(WorkOS::Profile)
191
+ it 'returns a WorkOS::ProfileAndToken' do
192
+ profile_and_token = described_class.profile_and_token(**args)
193
+ expect(profile_and_token).to be_a(WorkOS::ProfileAndToken)
164
194
 
165
195
  expectation = {
166
196
  connection_id: 'conn_01EMH8WAK20T42N2NBMNBCYHAG',
@@ -179,7 +209,8 @@ describe WorkOS::SSO do
179
209
  },
180
210
  }
181
211
 
182
- expect(profile.to_json).to eq(expectation)
212
+ expect(profile_and_token.access_token).to eq('01DVX6QBS3EG6FHY2ESAA5Q65X')
213
+ expect(profile_and_token.profile.to_json).to eq(expectation)
183
214
  end
184
215
  end
185
216
 
@@ -196,7 +227,7 @@ describe WorkOS::SSO do
196
227
 
197
228
  it 'raises an exception with request ID' do
198
229
  expect do
199
- described_class.profile(**args)
230
+ described_class.profile_and_token(**args)
200
231
  end.to raise_error(
201
232
  WorkOS::APIError,
202
233
  'some error message - request ID: request-id',
@@ -220,7 +251,7 @@ describe WorkOS::SSO do
220
251
 
221
252
  it 'raises an exception' do
222
253
  expect do
223
- described_class.profile(**args)
254
+ described_class.profile_and_token(**args)
224
255
  end.to raise_error(
225
256
  WorkOS::APIError,
226
257
  "The code '01DVX3C5Z367SFHR8QNDMK7V24'" \
@@ -230,85 +261,213 @@ describe WorkOS::SSO do
230
261
  end
231
262
  end
232
263
 
233
- describe '.create_connection' do
234
- before(:all) do
235
- WorkOS.key = 'key'
264
+ describe '.list_connections' do
265
+ context 'with no options' do
266
+ it 'returns connections and metadata' do
267
+ expected_metadata = {
268
+ 'after' => nil,
269
+ 'before' => 'before_id',
270
+ }
271
+
272
+ VCR.use_cassette 'sso/list_connections/with_no_options' do
273
+ connections = described_class.list_connections
274
+
275
+ expect(connections.data.size).to eq(3)
276
+ expect(connections.list_metadata).to eq(expected_metadata)
277
+ end
278
+ end
236
279
  end
237
280
 
238
- after(:all) do
239
- WorkOS.key = nil
281
+ context 'with connection_type option' do
282
+ it 'forms the proper request to the API' do
283
+ request_args = [
284
+ '/connections?connection_type=OktaSAML',
285
+ 'Content-Type' => 'application/json'
286
+ ]
287
+
288
+ expected_request = Net::HTTP::Get.new(*request_args)
289
+
290
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
291
+ and_return(expected_request)
292
+
293
+ VCR.use_cassette 'sso/list_connections/with_connection_type' do
294
+ connections = described_class.list_connections(
295
+ connection_type: 'OktaSAML',
296
+ )
297
+
298
+ expect(connections.data.size).to eq(3)
299
+ expect(connections.data.first.connection_type).to eq('OktaSAML')
300
+ end
301
+ end
240
302
  end
241
303
 
242
- context 'with a valid source' do
243
- it 'creates a connection' do
244
- VCR.use_cassette('sso/create_connection_with_valid_source') do
245
- connection = WorkOS::SSO.create_connection(
246
- source: 'draft_conn_01E6PK87QP6NQ29RRX0G100YGV',
304
+ context 'with domain option' do
305
+ it 'forms the proper request to the API' do
306
+ request_args = [
307
+ '/connections?domain=foo-corp.com',
308
+ 'Content-Type' => 'application/json'
309
+ ]
310
+
311
+ expected_request = Net::HTTP::Get.new(*request_args)
312
+
313
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
314
+ and_return(expected_request)
315
+
316
+ VCR.use_cassette 'sso/list_connections/with_domain' do
317
+ connections = described_class.list_connections(
318
+ domain: 'foo-corp.com',
247
319
  )
248
320
 
249
- expect(connection.id).to eq('conn_01E4F9T2YWZFD218DN04KVFDSY')
250
- expect(connection.connection_type).to eq('GoogleOAuth')
251
- expect(connection.name).to eq('Foo Corp')
252
- expect(connection.domains.first[:domain]).to eq('example.com')
321
+ expect(connections.data.size).to eq(1)
253
322
  end
254
323
  end
255
324
  end
256
325
 
257
- context 'with an invalid source' do
258
- it 'raises an error' do
259
- VCR.use_cassette('sso/create_connection_with_invalid_source') do
260
- expect do
261
- WorkOS::SSO.create_connection(source: 'invalid')
262
- end.to raise_error(
263
- WorkOS::APIError,
264
- 'Status 404, Not Found - request ID: ',
326
+ context 'with organization_id option' do
327
+ it 'forms the proper request to the API' do
328
+ request_args = [
329
+ '/connections?organization_id=org_01EGS4P7QR31EZ4YWD1Z1XA176',
330
+ 'Content-Type' => 'application/json'
331
+ ]
332
+
333
+ expected_request = Net::HTTP::Get.new(*request_args)
334
+
335
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
336
+ and_return(expected_request)
337
+
338
+ VCR.use_cassette 'sso/list_connections/with_organization_id' do
339
+ connections = described_class.list_connections(
340
+ organization_id: 'org_01EGS4P7QR31EZ4YWD1Z1XA176',
341
+ )
342
+
343
+ expect(connections.data.size).to eq(1)
344
+ expect(connections.data.first.organization_id).to eq(
345
+ 'org_01EGS4P7QR31EZ4YWD1Z1XA176',
265
346
  )
266
347
  end
267
348
  end
268
349
  end
269
- end
270
350
 
271
- describe '.promote_draft_connection' do
272
- before(:all) do
273
- WorkOS.key = 'key'
351
+ context 'with limit option' do
352
+ it 'forms the proper request to the API' do
353
+ request_args = [
354
+ '/connections?limit=2',
355
+ 'Content-Type' => 'application/json'
356
+ ]
357
+
358
+ expected_request = Net::HTTP::Get.new(*request_args)
359
+
360
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
361
+ and_return(expected_request)
362
+
363
+ VCR.use_cassette 'sso/list_connections/with_limit' do
364
+ connections = described_class.list_connections(
365
+ limit: 2,
366
+ )
367
+
368
+ expect(connections.data.size).to eq(2)
369
+ end
370
+ end
274
371
  end
275
372
 
276
- after(:all) do
277
- WorkOS.key = nil
373
+ context 'with before option' do
374
+ it 'forms the proper request to the API' do
375
+ request_args = [
376
+ '/connections?before=conn_01EQKPMQAPV02H270HKVNS4CTA',
377
+ 'Content-Type' => 'application/json'
378
+ ]
379
+
380
+ expected_request = Net::HTTP::Get.new(*request_args)
381
+
382
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
383
+ and_return(expected_request)
384
+
385
+ VCR.use_cassette 'sso/list_connections/with_before' do
386
+ connections = described_class.list_connections(
387
+ before: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
388
+ )
389
+
390
+ expect(connections.data.size).to eq(3)
391
+ end
392
+ end
278
393
  end
279
394
 
280
- let(:token) { 'draft_conn_id' }
281
- let(:project_id) { 'proj_0239u590h' }
395
+ context 'with after option' do
396
+ it 'forms the proper request to the API' do
397
+ request_args = [
398
+ '/connections?after=conn_01EQKPMQAPV02H270HKVNS4CTA',
399
+ 'Content-Type' => 'application/json'
400
+ ]
282
401
 
283
- context 'with a valid request' do
284
- before do
285
- stub_request(
286
- :post,
287
- "https://api.workos.com/draft_connections/#{token}/activate",
288
- ).to_return(status: 200)
402
+ expected_request = Net::HTTP::Get.new(*request_args)
403
+
404
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
405
+ and_return(expected_request)
406
+
407
+ VCR.use_cassette 'sso/list_connections/with_after' do
408
+ connections = described_class.list_connections(
409
+ after: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
410
+ )
411
+
412
+ expect(connections.data.size).to eq(3)
413
+ end
289
414
  end
290
- it 'returns true' do
291
- response = described_class.promote_draft_connection(
292
- token: token,
293
- )
415
+ end
416
+ end
294
417
 
295
- expect(response).to be(true)
418
+ describe '.get_connection' do
419
+ context 'with a valid id' do
420
+ it 'gets the connection details' do
421
+ VCR.use_cassette('sso/get_connection_with_valid_id') do
422
+ connection = WorkOS::SSO.get_connection(
423
+ id: 'conn_01EX00NB050H354WKGC7990AR2',
424
+ )
425
+
426
+ expect(connection.id).to eq('conn_01EX00NB050H354WKGC7990AR2')
427
+ expect(connection.connection_type).to eq('OktaSAML')
428
+ expect(connection.name).to eq('Foo Corp')
429
+ expect(connection.domains.first[:domain]).to eq('foo-corp.com')
430
+ end
296
431
  end
297
432
  end
298
433
 
299
- context 'with an invalid request' do
300
- before do
301
- stub_request(
302
- :post,
303
- "https://api.workos.com/draft_connections/#{token}/activate",
304
- ).to_return(status: 403)
434
+ context 'with an invalid id' do
435
+ it 'raises an error' do
436
+ VCR.use_cassette('sso/get_connection_with_invalid_id') do
437
+ expect do
438
+ WorkOS::SSO.get_connection(id: 'invalid')
439
+ end.to raise_error(
440
+ WorkOS::APIError,
441
+ 'Status 404, Not Found - request ID: ',
442
+ )
443
+ end
305
444
  end
445
+ end
446
+ end
447
+
448
+ describe '.delete_connection' do
449
+ context 'with a valid id' do
306
450
  it 'returns true' do
307
- response = described_class.promote_draft_connection(
308
- token: token,
309
- )
451
+ VCR.use_cassette('sso/delete_connection_with_valid_id') do
452
+ response = WorkOS::SSO.delete_connection(
453
+ id: 'conn_01EX55FRVN1V2PCA9YWTMZQMMQ',
454
+ )
455
+
456
+ expect(response).to be(true)
457
+ end
458
+ end
459
+ end
310
460
 
311
- expect(response).to be(false)
461
+ context 'with an invalid id' do
462
+ it 'returns false' do
463
+ VCR.use_cassette('sso/delete_connection_with_invalid_id') do
464
+ expect do
465
+ WorkOS::SSO.delete_connection(id: 'invalid')
466
+ end.to raise_error(
467
+ WorkOS::APIError,
468
+ 'Status 404, Not Found - request ID: ',
469
+ )
470
+ end
312
471
  end
313
472
  end
314
473
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: true
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
@@ -54,8 +54,8 @@ http_interactions:
54
54
  encoding: ASCII-8BIT
55
55
  string:
56
56
  '{"data":[{"object":"event","id":"evt_01EEJM9Q9SMC3W2SZDKA5VJ8XQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPHAYX46BBZKGK3BGQXJ","metadata":{"description":"User
57
- viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.384Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","project_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}},{"object":"event","id":"evt_01EEJM9Q7GMR1VGT6VXN2N2JJQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPGM8KFT9VBQHJMV8YZB","metadata":{"description":"User
58
- viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.360Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","project_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}}],"listMetadata":{"before":"evt_01EEJKZDAR6G4JHFQT4R3KSZDQ","after":null}}'
57
+ viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.384Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","client_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}},{"object":"event","id":"evt_01EEJM9Q7GMR1VGT6VXN2N2JJQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPGM8KFT9VBQHJMV8YZB","metadata":{"description":"User
58
+ viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.360Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","client_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}}],"listMetadata":{"before":"evt_01EEJKZDAR6G4JHFQT4R3KSZDQ","after":null}}'
59
59
  http_version:
60
60
  recorded_at: Fri, 31 Jul 2020 14:41:12 GMT
61
61
  recorded_with: VCR 5.0.0
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: https://api.workos.com/directories/directory_01F2T098SKN5PCTVSJ7CWP70N5
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ User-Agent:
17
+ - WorkOS; ruby/2.7.1; x86_64-darwin20; v0.10.3
18
+ Authorization:
19
+ - Bearer <API_KEY>
20
+ response:
21
+ status:
22
+ code: 202
23
+ message: Accepted
24
+ headers:
25
+ Server:
26
+ - Cowboy
27
+ Connection:
28
+ - keep-alive
29
+ Vary:
30
+ - Origin, Accept-Encoding
31
+ Access-Control-Allow-Credentials:
32
+ - 'true'
33
+ Content-Security-Policy:
34
+ - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self''
35
+ https: data:;frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src
36
+ ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests'
37
+ X-Dns-Prefetch-Control:
38
+ - 'off'
39
+ Expect-Ct:
40
+ - max-age=0
41
+ X-Frame-Options:
42
+ - SAMEORIGIN
43
+ Strict-Transport-Security:
44
+ - max-age=15552000; includeSubDomains
45
+ X-Download-Options:
46
+ - noopen
47
+ X-Content-Type-Options:
48
+ - nosniff
49
+ X-Permitted-Cross-Domain-Policies:
50
+ - none
51
+ Referrer-Policy:
52
+ - no-referrer
53
+ X-Xss-Protection:
54
+ - '0'
55
+ X-Request-Id:
56
+ - 834c3434-80dd-4e5e-bda7-95cd1412ad29
57
+ Content-Type:
58
+ - text/plain; charset=utf-8
59
+ Content-Length:
60
+ - '8'
61
+ Etag:
62
+ - W/"8-YaBXLEiT7zQxEyDYTILfiL6oPhE"
63
+ Date:
64
+ - Wed, 21 Apr 2021 22:26:51 GMT
65
+ Via:
66
+ - 1.1 vegur
67
+ body:
68
+ encoding: UTF-8
69
+ string: Accepted
70
+ http_version:
71
+ recorded_at: Wed, 21 Apr 2021 22:26:51 GMT
72
+ recorded_with: VCR 5.0.0