workos 5.3.0 → 6.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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/workflows/ci.yml +2 -4
  4. data/.github/workflows/lint-pr-title.yml +20 -0
  5. data/.github/workflows/release-please.yml +25 -0
  6. data/.github/workflows/release.yml +22 -25
  7. data/.gitignore +1 -0
  8. data/.release-please-manifest.json +3 -0
  9. data/.rubocop.yml +11 -8
  10. data/.rubocop_todo.yml +94 -0
  11. data/.ruby-version +1 -1
  12. data/CHANGELOG.md +15 -0
  13. data/Gemfile.lock +32 -18
  14. data/Rakefile +8 -0
  15. data/context7.json +4 -0
  16. data/lib/workos/authentication_response.rb +32 -4
  17. data/lib/workos/cache.rb +94 -0
  18. data/lib/workos/client.rb +9 -1
  19. data/lib/workos/directory_sync.rb +1 -1
  20. data/lib/workos/directory_user.rb +31 -3
  21. data/lib/workos/encryptors/aes_gcm.rb +49 -0
  22. data/lib/workos/encryptors.rb +9 -0
  23. data/lib/workos/errors.rb +4 -0
  24. data/lib/workos/feature_flag.rb +34 -0
  25. data/lib/workos/mfa.rb +0 -1
  26. data/lib/workos/oauth_tokens.rb +29 -0
  27. data/lib/workos/organization.rb +14 -1
  28. data/lib/workos/organization_membership.rb +5 -1
  29. data/lib/workos/organizations.rb +87 -3
  30. data/lib/workos/profile.rb +10 -2
  31. data/lib/workos/refresh_authentication_response.rb +29 -2
  32. data/lib/workos/role.rb +38 -0
  33. data/lib/workos/session.rb +187 -0
  34. data/lib/workos/sso.rb +3 -24
  35. data/lib/workos/types/intent.rb +3 -1
  36. data/lib/workos/types/provider.rb +1 -1
  37. data/lib/workos/types/widget_scope.rb +15 -0
  38. data/lib/workos/types.rb +1 -0
  39. data/lib/workos/user.rb +7 -1
  40. data/lib/workos/user_management/session.rb +57 -0
  41. data/lib/workos/user_management.rb +213 -45
  42. data/lib/workos/version.rb +1 -1
  43. data/lib/workos/widgets.rb +46 -0
  44. data/lib/workos.rb +8 -0
  45. data/release-please-config.json +12 -0
  46. data/spec/lib/workos/cache_spec.rb +94 -0
  47. data/spec/lib/workos/directory_user_spec.rb +13 -3
  48. data/spec/lib/workos/encryptors/aes_gcm_spec.rb +41 -0
  49. data/spec/lib/workos/organizations_spec.rb +258 -1
  50. data/spec/lib/workos/portal_spec.rb +30 -0
  51. data/spec/lib/workos/role_spec.rb +142 -0
  52. data/spec/lib/workos/session_spec.rb +475 -0
  53. data/spec/lib/workos/sso_spec.rb +106 -5
  54. data/spec/lib/workos/user_management_spec.rb +496 -1
  55. data/spec/lib/workos/widgets_spec.rb +73 -0
  56. data/spec/support/fixtures/vcr_cassettes/directory_sync/get_user.yml +1 -1
  57. data/spec/support/fixtures/vcr_cassettes/organization/create_with_external_id.yml +83 -0
  58. data/spec/support/fixtures/vcr_cassettes/organization/list_organization_feature_flags.yml +78 -0
  59. data/spec/support/fixtures/vcr_cassettes/organization/list_organization_roles.yml +82 -0
  60. data/spec/support/fixtures/vcr_cassettes/organization/update_with_external_id.yml +78 -0
  61. data/spec/support/fixtures/vcr_cassettes/organization/update_with_external_id_null.yml +78 -0
  62. data/spec/support/fixtures/vcr_cassettes/organization/update_with_stripe_customer_id.yml +78 -0
  63. data/spec/support/fixtures/vcr_cassettes/organization/update_without_name.yml +85 -0
  64. data/spec/support/fixtures/vcr_cassettes/portal/generate_link_certificate_renewal.yml +72 -0
  65. data/spec/support/fixtures/vcr_cassettes/portal/generate_link_domain_verification.yml +72 -0
  66. data/spec/support/fixtures/vcr_cassettes/sso/profile.yml +1 -1
  67. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_oauth_tokens.yml +82 -0
  68. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_password/unverified.yml +82 -0
  69. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_refresh_token/valid.yml +79 -78
  70. data/spec/support/fixtures/vcr_cassettes/user_management/create_organization_membership/valid_multiple_roles.yml +76 -0
  71. data/spec/support/fixtures/vcr_cassettes/user_management/create_user_with_external_id.yml +77 -0
  72. data/spec/support/fixtures/vcr_cassettes/user_management/get_user.yml +1 -1
  73. data/spec/support/fixtures/vcr_cassettes/user_management/list_sessions/valid.yml +38 -0
  74. data/spec/support/fixtures/vcr_cassettes/user_management/resend_invitation/accepted.yml +83 -0
  75. data/spec/support/fixtures/vcr_cassettes/user_management/resend_invitation/expired.yml +83 -0
  76. data/spec/support/fixtures/vcr_cassettes/user_management/resend_invitation/invalid.yml +83 -0
  77. data/spec/support/fixtures/vcr_cassettes/user_management/resend_invitation/revoked.yml +83 -0
  78. data/spec/support/fixtures/vcr_cassettes/user_management/resend_invitation/valid.yml +83 -0
  79. data/spec/support/fixtures/vcr_cassettes/user_management/reset_password/valid.yml +1 -1
  80. data/spec/support/fixtures/vcr_cassettes/user_management/update_organization_membership/valid_multiple_roles.yml +76 -0
  81. data/spec/support/fixtures/vcr_cassettes/user_management/update_user/email.yml +82 -0
  82. data/spec/support/fixtures/vcr_cassettes/user_management/update_user/locale.yml +76 -0
  83. data/spec/support/fixtures/vcr_cassettes/user_management/update_user/valid.yml +2 -2
  84. data/spec/support/fixtures/vcr_cassettes/user_management/update_user_external_id_null.yml +77 -0
  85. data/spec/support/fixtures/vcr_cassettes/widgets/get_token.yml +82 -0
  86. data/spec/support/fixtures/vcr_cassettes/widgets/get_token_invalid_organization_id.yml +74 -0
  87. data/spec/support/fixtures/vcr_cassettes/widgets/get_token_invalid_user_id.yml +74 -0
  88. data/spec/support/profile.txt +1 -1
  89. data/workos.gemspec +7 -3
  90. metadata +132 -10
@@ -6,9 +6,9 @@ require 'uri'
6
6
  module WorkOS
7
7
  # The UserManagement module provides convenience methods for working with the
8
8
  # WorkOS User platform. You'll need a valid API key.
9
-
10
- # rubocop:disable Metrics/ModuleLength
11
9
  module UserManagement
10
+ autoload :Session, 'workos/user_management/session'
11
+
12
12
  module Types
13
13
  # The ProviderEnum is a declaration of a
14
14
  # fixed set of values for User Management Providers.
@@ -19,7 +19,7 @@ module WorkOS
19
19
  Microsoft = 'MicrosoftOAuth'
20
20
  AuthKit = 'authkit'
21
21
 
22
- ALL = [GitHub, Google, Microsoft, AuthKit].freeze
22
+ ALL = [Apple, GitHub, Google, Microsoft, AuthKit].freeze
23
23
  end
24
24
 
25
25
  # The AuthFactorType is a declaration of a
@@ -37,6 +37,24 @@ module WorkOS
37
37
  PROVIDERS = WorkOS::UserManagement::Types::Provider::ALL
38
38
  AUTH_FACTOR_TYPES = WorkOS::UserManagement::Types::AuthFactorType::ALL
39
39
 
40
+ # Load a sealed session
41
+ #
42
+ # @param [String] client_id The WorkOS client ID for the environment
43
+ # @param [String] session_data The sealed session data
44
+ # @param [String] cookie_password The password used to seal the session
45
+ # @param [Object] encryptor Optional custom encryptor that responds to #seal and #unseal
46
+ #
47
+ # @return WorkOS::Session
48
+ def load_sealed_session(client_id:, session_data:, cookie_password:, encryptor: nil)
49
+ WorkOS::Session.new(
50
+ user_management: self,
51
+ client_id: client_id,
52
+ session_data: session_data,
53
+ cookie_password: cookie_password,
54
+ encryptor: encryptor,
55
+ )
56
+ end
57
+
40
58
  # Generate an OAuth 2.0 authorization URL that automatically directs a user
41
59
  # to their Identity Provider.
42
60
  #
@@ -55,8 +73,11 @@ module WorkOS
55
73
  # that is preserved and available to the client in the response.
56
74
  # @param [String] login_hint Can be used to pre-fill the username/email address
57
75
  # field of the IdP sign-in page for the user, if you know their username ahead of time.
76
+ # @param [String] screen_hint Specify which AuthKit screen users should land on upon redirection
77
+ # (Only applicable when provider is 'authkit').
58
78
  # @param [String] domain_hint Can be used to pre-fill the domain field when
59
79
  # initiating authentication with Microsoft OAuth, or with a GoogleSAML connection type.
80
+ # @param [Array<String>] provider_scopes An array of additional OAuth scopes to request from the provider.
60
81
  # @example
61
82
  # WorkOS::UserManagement.authorization_url(
62
83
  # connection_id: 'conn_123',
@@ -79,10 +100,12 @@ module WorkOS
79
100
  client_id: nil,
80
101
  domain_hint: nil,
81
102
  login_hint: nil,
103
+ screen_hint: nil,
82
104
  provider: nil,
83
105
  connection_id: nil,
84
106
  organization_id: nil,
85
- state: ''
107
+ state: '',
108
+ provider_scopes: nil
86
109
  )
87
110
 
88
111
  validate_authorization_url_arguments(
@@ -98,9 +121,11 @@ module WorkOS
98
121
  state: state,
99
122
  domain_hint: domain_hint,
100
123
  login_hint: login_hint,
124
+ screen_hint: screen_hint,
101
125
  provider: provider,
102
126
  connection_id: connection_id,
103
127
  organization_id: organization_id,
128
+ provider_scopes: provider_scopes,
104
129
  }.compact)
105
130
 
106
131
  "https://#{WorkOS.config.api_hostname}/user_management/authorize?#{query}"
@@ -165,6 +190,7 @@ module WorkOS
165
190
  # @param [String] first_name The user's first name.
166
191
  # @param [String] last_name The user's last name.
167
192
  # @param [Boolean] email_verified Whether the user's email address was previously verified.
193
+ # @param [String] external_id The user's external ID.
168
194
  # @param [String] password_hash The user's hashed password.
169
195
  # @option [String] password_hash_type The algorithm originally used to hash the password.
170
196
  #
@@ -176,6 +202,7 @@ module WorkOS
176
202
  first_name: nil,
177
203
  last_name: nil,
178
204
  email_verified: nil,
205
+ external_id: nil,
179
206
  password_hash: nil,
180
207
  password_hash_type: nil
181
208
  )
@@ -187,9 +214,10 @@ module WorkOS
187
214
  first_name: first_name,
188
215
  last_name: last_name,
189
216
  email_verified: email_verified,
217
+ external_id: external_id,
190
218
  password_hash: password_hash,
191
219
  password_hash_type: password_hash_type,
192
- },
220
+ }.compact,
193
221
  auth: true,
194
222
  )
195
223
 
@@ -201,9 +229,12 @@ module WorkOS
201
229
  # Update a user
202
230
  #
203
231
  # @param [String] id of the user.
232
+ # @param [String] email of the user.
204
233
  # @param [String] first_name The user's first name.
205
234
  # @param [String] last_name The user's last name.
206
235
  # @param [Boolean] email_verified Whether the user's email address was previously verified.
236
+ # @param [String] external_id The users's external ID
237
+ # @param [String] locale The user's locale.
207
238
  # @param [String] password The user's password.
208
239
  # @param [String] password_hash The user's hashed password.
209
240
  # @option [String] password_hash_type The algorithm originally used to hash the password.
@@ -212,23 +243,29 @@ module WorkOS
212
243
  # @return [WorkOS::User]
213
244
  def update_user(
214
245
  id:,
215
- first_name: nil,
216
- last_name: nil,
217
- email_verified: nil,
218
- password: nil,
219
- password_hash: nil,
220
- password_hash_type: nil
246
+ email: :not_set,
247
+ first_name: :not_set,
248
+ last_name: :not_set,
249
+ email_verified: :not_set,
250
+ external_id: :not_set,
251
+ locale: :not_set,
252
+ password: :not_set,
253
+ password_hash: :not_set,
254
+ password_hash_type: :not_set
221
255
  )
222
256
  request = put_request(
223
257
  path: "/user_management/users/#{id}",
224
258
  body: {
259
+ email: email,
225
260
  first_name: first_name,
226
261
  last_name: last_name,
227
262
  email_verified: email_verified,
263
+ external_id: external_id,
264
+ locale: locale,
228
265
  password: password,
229
266
  password_hash: password_hash,
230
267
  password_hash_type: password_hash_type,
231
- },
268
+ }.reject { |_, v| v == :not_set },
232
269
  auth: true,
233
270
  )
234
271
 
@@ -261,9 +298,23 @@ module WorkOS
261
298
  # @param [String] client_id The WorkOS client ID for the environment
262
299
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
263
300
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
301
+ # @param [String] invitation_token The token of an Invitation, if required.
302
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
303
+ # the optional cookie password.
264
304
  #
265
305
  # @return WorkOS::AuthenticationResponse
266
- def authenticate_with_password(email:, password:, client_id:, ip_address: nil, user_agent: nil)
306
+ # rubocop:disable Metrics/ParameterLists
307
+ def authenticate_with_password(
308
+ email:,
309
+ password:,
310
+ client_id:,
311
+ ip_address: nil,
312
+ user_agent: nil,
313
+ invitation_token: nil,
314
+ session: nil
315
+ )
316
+ validate_session(session)
317
+
267
318
  response = execute_request(
268
319
  request: post_request(
269
320
  path: '/user_management/authenticate',
@@ -274,13 +325,15 @@ module WorkOS
274
325
  password: password,
275
326
  ip_address: ip_address,
276
327
  user_agent: user_agent,
328
+ invitation_token: invitation_token,
277
329
  grant_type: 'password',
278
330
  },
279
331
  ),
280
332
  )
281
333
 
282
- WorkOS::AuthenticationResponse.new(response.body)
334
+ WorkOS::AuthenticationResponse.new(response.body, session)
283
335
  end
336
+ # rubocop:enable Metrics/ParameterLists
284
337
 
285
338
  # Authenticate a user using OAuth or an organization's SSO connection.
286
339
  #
@@ -289,14 +342,21 @@ module WorkOS
289
342
  # @param [String] client_id The WorkOS client ID for the environment
290
343
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
291
344
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
345
+ # @param [String] invitation_token The token of an Invitation, if required.
346
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
347
+ # the optional cookie password.
292
348
  #
293
349
  # @return WorkOS::AuthenticationResponse
294
350
  def authenticate_with_code(
295
351
  code:,
296
352
  client_id:,
297
353
  ip_address: nil,
298
- user_agent: nil
354
+ user_agent: nil,
355
+ invitation_token: nil,
356
+ session: nil
299
357
  )
358
+ validate_session(session)
359
+
300
360
  response = execute_request(
301
361
  request: post_request(
302
362
  path: '/user_management/authenticate',
@@ -306,28 +366,36 @@ module WorkOS
306
366
  client_secret: WorkOS.config.key!,
307
367
  ip_address: ip_address,
308
368
  user_agent: user_agent,
369
+ invitation_token: invitation_token,
309
370
  grant_type: 'authorization_code',
310
371
  },
311
372
  ),
312
373
  )
313
374
 
314
- WorkOS::AuthenticationResponse.new(response.body)
375
+ WorkOS::AuthenticationResponse.new(response.body, session)
315
376
  end
316
377
 
317
378
  # Authenticate a user using a refresh token.
318
379
  #
319
380
  # @param [String] refresh_token The refresh token previously obtained from a successful authentication call
320
381
  # @param [String] client_id The WorkOS client ID for the environment
382
+ # @param [String] organization_id The organization to issue the new access token for. (Optional)
321
383
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
322
384
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
385
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
386
+ # the optional cookie password.
323
387
  #
324
388
  # @return WorkOS::RefreshAuthenticationResponse
325
389
  def authenticate_with_refresh_token(
326
390
  refresh_token:,
327
391
  client_id:,
392
+ organization_id: nil,
328
393
  ip_address: nil,
329
- user_agent: nil
394
+ user_agent: nil,
395
+ session: nil
330
396
  )
397
+ validate_session(session)
398
+
331
399
  response = execute_request(
332
400
  request: post_request(
333
401
  path: '/user_management/authenticate',
@@ -338,11 +406,12 @@ module WorkOS
338
406
  ip_address: ip_address,
339
407
  user_agent: user_agent,
340
408
  grant_type: 'refresh_token',
409
+ organization_id: organization_id,
341
410
  },
342
411
  ),
343
412
  )
344
413
 
345
- WorkOS::RefreshAuthenticationResponse.new(response.body)
414
+ WorkOS::RefreshAuthenticationResponse.new(response.body, session)
346
415
  end
347
416
 
348
417
  # Authenticate user by Magic Auth Code.
@@ -354,16 +423,24 @@ module WorkOS
354
423
  # @param [String] link_authorization_code Used to link an OAuth profile to an existing user,
355
424
  # after having completed a Magic Code challenge.
356
425
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
426
+ # @param [String] invitation_token The token of an Invitation, if required.
427
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
428
+ # the optional cookie password.
357
429
  #
358
430
  # @return WorkOS::AuthenticationResponse
431
+ # rubocop:disable Metrics/ParameterLists
359
432
  def authenticate_with_magic_auth(
360
433
  code:,
361
434
  email:,
362
435
  client_id:,
363
436
  ip_address: nil,
364
437
  user_agent: nil,
365
- link_authorization_code: nil
438
+ link_authorization_code: nil,
439
+ invitation_token: nil,
440
+ session: nil
366
441
  )
442
+ validate_session(session)
443
+
367
444
  response = execute_request(
368
445
  request: post_request(
369
446
  path: '/user_management/authenticate',
@@ -376,12 +453,14 @@ module WorkOS
376
453
  user_agent: user_agent,
377
454
  grant_type: 'urn:workos:oauth:grant-type:magic-auth:code',
378
455
  link_authorization_code: link_authorization_code,
456
+ invitation_token: invitation_token,
379
457
  },
380
458
  ),
381
459
  )
382
460
 
383
- WorkOS::AuthenticationResponse.new(response.body)
461
+ WorkOS::AuthenticationResponse.new(response.body, session)
384
462
  end
463
+ # rubocop:enable Metrics/ParameterLists
385
464
 
386
465
  # Authenticate a user into an organization they are a member of.
387
466
  #
@@ -390,6 +469,8 @@ module WorkOS
390
469
  # @param [String] pending_authentication_token The pending authentication token
391
470
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
392
471
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
472
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
473
+ # the optional cookie password.
393
474
  #
394
475
  # @return WorkOS::AuthenticationResponse
395
476
  def authenticate_with_organization_selection(
@@ -397,8 +478,11 @@ module WorkOS
397
478
  organization_id:,
398
479
  pending_authentication_token:,
399
480
  ip_address: nil,
400
- user_agent: nil
481
+ user_agent: nil,
482
+ session: nil
401
483
  )
484
+ validate_session(session)
485
+
402
486
  response = execute_request(
403
487
  request: post_request(
404
488
  path: '/user_management/authenticate',
@@ -414,7 +498,7 @@ module WorkOS
414
498
  ),
415
499
  )
416
500
 
417
- WorkOS::AuthenticationResponse.new(response.body)
501
+ WorkOS::AuthenticationResponse.new(response.body, session)
418
502
  end
419
503
 
420
504
  # Authenticate a user using TOTP.
@@ -427,16 +511,22 @@ module WorkOS
427
511
  # authentication request.
428
512
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
429
513
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
514
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
515
+ # the optional cookie password.
430
516
  #
431
517
  # @return WorkOS::AuthenticationResponse
518
+ # rubocop:disable Metrics/ParameterLists
432
519
  def authenticate_with_totp(
433
520
  code:,
434
521
  client_id:,
435
522
  pending_authentication_token:,
436
523
  authentication_challenge_id:,
437
524
  ip_address: nil,
438
- user_agent: nil
525
+ user_agent: nil,
526
+ session: nil
439
527
  )
528
+ validate_session(session)
529
+
440
530
  response = execute_request(
441
531
  request: post_request(
442
532
  path: '/user_management/authenticate',
@@ -453,8 +543,9 @@ module WorkOS
453
543
  ),
454
544
  )
455
545
 
456
- WorkOS::AuthenticationResponse.new(response.body)
546
+ WorkOS::AuthenticationResponse.new(response.body, session)
457
547
  end
548
+ # rubocop:enable Metrics/ParameterLists
458
549
 
459
550
  # Authenticate a user using Email Verification Code.
460
551
  #
@@ -464,6 +555,8 @@ module WorkOS
464
555
  # authentication attempt due to an unverified email address.
465
556
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
466
557
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
558
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
559
+ # the optional cookie password.
467
560
  #
468
561
  # @return WorkOS::AuthenticationResponse
469
562
  def authenticate_with_email_verification(
@@ -471,8 +564,11 @@ module WorkOS
471
564
  client_id:,
472
565
  pending_authentication_token:,
473
566
  ip_address: nil,
474
- user_agent: nil
567
+ user_agent: nil,
568
+ session: nil
475
569
  )
570
+ validate_session(session)
571
+
476
572
  response = execute_request(
477
573
  request: post_request(
478
574
  path: '/user_management/authenticate',
@@ -488,7 +584,7 @@ module WorkOS
488
584
  ),
489
585
  )
490
586
 
491
- WorkOS::AuthenticationResponse.new(response.body)
587
+ WorkOS::AuthenticationResponse.new(response.body, session)
492
588
  end
493
589
 
494
590
  # Get the logout URL for a session
@@ -497,13 +593,17 @@ module WorkOS
497
593
  #
498
594
  # @param [String] session_id The session ID can be found in the `sid`
499
595
  # claim of the access token
596
+ # @param [String] return_to The URL to redirect the user to after logging out
500
597
  #
501
598
  # @return String
502
- def get_logout_url(session_id:)
599
+ def get_logout_url(session_id:, return_to: nil)
600
+ params = { session_id: session_id }
601
+ params[:return_to] = return_to if return_to
602
+
503
603
  URI::HTTPS.build(
504
604
  host: WorkOS.config.api_hostname,
505
605
  path: '/user_management/sessions/logout',
506
- query: "session_id=#{session_id}",
606
+ query: URI.encode_www_form(params),
507
607
  ).to_s
508
608
  end
509
609
 
@@ -568,7 +668,7 @@ module WorkOS
568
668
  body: {
569
669
  email: email,
570
670
  invitation_token: invitation_token,
571
- },
671
+ }.compact,
572
672
  auth: true,
573
673
  ),
574
674
  )
@@ -622,7 +722,7 @@ module WorkOS
622
722
  totp_issuer: totp_issuer,
623
723
  totp_user: totp_user,
624
724
  totp_secret: totp_secret,
625
- },
725
+ }.compact,
626
726
  auth: true,
627
727
  ),
628
728
  )
@@ -655,6 +755,40 @@ module WorkOS
655
755
  )
656
756
  end
657
757
 
758
+ # Get all sessions for a user
759
+ #
760
+ # @param [String] user_id The id for the user.
761
+ # @param [Hash] options
762
+ # @option options [String] limit Maximum number of records to return.
763
+ # @option options [String] order The order in which to paginate records
764
+ # @option options [String] before Pagination cursor to receive records
765
+ # before a provided Session ID.
766
+ # @option options [String] after Pagination cursor to receive records
767
+ # after a provided Session ID.
768
+ #
769
+ # @return [WorkOS::Types::ListStruct<WorkOS::UserManagement::Session>]
770
+ def list_sessions(user_id:, options: {})
771
+ options[:order] ||= 'desc'
772
+ response = execute_request(
773
+ request: get_request(
774
+ path: "/user_management/users/#{user_id}/sessions",
775
+ auth: true,
776
+ params: options,
777
+ ),
778
+ )
779
+
780
+ parsed_response = JSON.parse(response.body)
781
+
782
+ sessions = parsed_response['data'].map do |session|
783
+ ::WorkOS::UserManagement::Session.new(session.to_json)
784
+ end
785
+
786
+ WorkOS::Types::ListStruct.new(
787
+ data: sessions,
788
+ list_metadata: parsed_response['list_metadata'],
789
+ )
790
+ end
791
+
658
792
  # Gets an email verification object
659
793
  #
660
794
  # @param [String] id The unique ID of the EmailVerification object.
@@ -784,7 +918,7 @@ module WorkOS
784
918
  ),
785
919
  )
786
920
 
787
- WorkOS::User.new(response.body)
921
+ WorkOS::UserResponse.new(response.body).user
788
922
  end
789
923
 
790
924
  # Get an Organization Membership
@@ -844,16 +978,23 @@ module WorkOS
844
978
  # @param [String] user_id The ID of the User.
845
979
  # @param [String] organization_id The ID of the Organization to which the user belongs to.
846
980
  # @param [String] role_slug The slug of the role to grant to this membership. (Optional)
981
+ # @param [Array<String>] role_slugs Array of role slugs to assign to this membership. (Optional)
847
982
  #
848
983
  # @return [WorkOS::OrganizationMembership]
849
- def create_organization_membership(user_id:, organization_id:, role_slug: nil)
984
+ def create_organization_membership(user_id:, organization_id:, role_slug: nil, role_slugs: nil)
985
+ raise ArgumentError, 'Cannot specify both role_slug and role_slugs' if role_slug && role_slugs
986
+
987
+ body = {
988
+ user_id: user_id,
989
+ organization_id: organization_id,
990
+ }
991
+
992
+ body[:role_slugs] = role_slugs if role_slugs
993
+ body[:role_slug] = role_slug if role_slug
994
+
850
995
  request = post_request(
851
996
  path: '/user_management/organization_memberships',
852
- body: {
853
- user_id: user_id,
854
- organization_id: organization_id,
855
- role_slug: role_slug,
856
- },
997
+ body: body.compact,
857
998
  auth: true,
858
999
  )
859
1000
 
@@ -864,17 +1005,22 @@ module WorkOS
864
1005
 
865
1006
  # Update an Organization Membership
866
1007
  #
867
- # @param [String] organization_membership_id The ID of the Organization Membership.
868
- # @param [String] role_slug The slug of the role to grant to this membership.
1008
+ # @param [String] id The ID of the Organization Membership.
1009
+ # @param [String] role_slug The slug of the role to grant to this membership. (Optional)
1010
+ # @param [Array<String>] role_slugs Array of role slugs to assign to this membership. (Optional)
869
1011
  #
870
1012
  # @return [WorkOS::OrganizationMembership]
871
- def update_organization_membership(id:, role_slug:)
1013
+ def update_organization_membership(id:, role_slug: nil, role_slugs: nil)
1014
+ raise ArgumentError, 'Cannot specify both role_slug and role_slugs' if role_slug && role_slugs
1015
+
1016
+ body = { id: id }
1017
+
1018
+ body[:role_slugs] = role_slugs if role_slugs
1019
+ body[:role_slug] = role_slug if role_slug
1020
+
872
1021
  request = put_request(
873
1022
  path: "/user_management/organization_memberships/#{id}",
874
- body: {
875
- id: id,
876
- role_slug: role_slug,
877
- },
1023
+ body: body.compact,
878
1024
  auth: true,
879
1025
  )
880
1026
 
@@ -1018,7 +1164,7 @@ module WorkOS
1018
1164
  expires_in_days: expires_in_days,
1019
1165
  inviter_user_id: inviter_user_id,
1020
1166
  role_slug: role_slug,
1021
- },
1167
+ }.compact,
1022
1168
  auth: true,
1023
1169
  ),
1024
1170
  )
@@ -1042,8 +1188,30 @@ module WorkOS
1042
1188
  WorkOS::Invitation.new(response.body)
1043
1189
  end
1044
1190
 
1191
+ # Resends an existing Invitation.
1192
+ #
1193
+ # @param [String] id The unique ID of the Invitation.
1194
+ #
1195
+ # @return WorkOS::Invitation
1196
+ def resend_invitation(id:)
1197
+ request = post_request(
1198
+ path: "/user_management/invitations/#{id}/resend",
1199
+ auth: true,
1200
+ )
1201
+
1202
+ response = execute_request(request: request)
1203
+
1204
+ WorkOS::Invitation.new(response.body)
1205
+ end
1206
+
1045
1207
  private
1046
1208
 
1209
+ def validate_session(session)
1210
+ return unless session && (session[:seal_session] == true) && session[:cookie_password].nil?
1211
+
1212
+ raise ArgumentError, 'cookie_password is required when sealing session'
1213
+ end
1214
+
1047
1215
  def validate_authorization_url_arguments(
1048
1216
  provider:,
1049
1217
  connection_id:,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WorkOS
4
- VERSION = '5.3.0'
4
+ VERSION = '6.1.0'
5
5
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+
5
+ module WorkOS
6
+ # The Widgets module provides resource methods for working with the Widgets APIs
7
+ module Widgets
8
+ class << self
9
+ include Client
10
+
11
+ WIDGET_SCOPES = WorkOS::Types::WidgetScope::ALL
12
+
13
+ # Generate a widget token.
14
+ #
15
+ # @param [String] organization_id The ID of the organization to generate the token for.
16
+ # @param [String] user_id The ID of the user to generate the token for.
17
+ # @param [WidgetScope[]] The scopes to generate the token for.
18
+ def get_token(organization_id:, user_id:, scopes:)
19
+ validate_scopes(scopes)
20
+
21
+ request = post_request(
22
+ auth: true,
23
+ body: {
24
+ organization_id: organization_id,
25
+ user_id: user_id,
26
+ scopes: scopes,
27
+ },
28
+ path: '/widgets/token',
29
+ )
30
+
31
+ response = execute_request(request: request)
32
+
33
+ JSON.parse(response.body)['token']
34
+ end
35
+
36
+ private
37
+
38
+ def validate_scopes(scopes)
39
+ return if scopes.all? { |scope| WIDGET_SCOPES.include?(scope) }
40
+
41
+ raise ArgumentError, 'scopes contains an invalid value.' \
42
+ " Every item in `scopes` must be in #{WIDGET_SCOPES}"
43
+ end
44
+ end
45
+ end
46
+ end
data/lib/workos.rb CHANGED
@@ -45,6 +45,7 @@ module WorkOS
45
45
  autoload :AuthenticationFactorAndChallenge, 'workos/authentication_factor_and_challenge'
46
46
  autoload :AuthenticationResponse, 'workos/authentication_response'
47
47
  autoload :AuditLogs, 'workos/audit_logs'
48
+ autoload :Cache, 'workos/cache'
48
49
  autoload :Challenge, 'workos/challenge'
49
50
  autoload :Client, 'workos/client'
50
51
  autoload :Connection, 'workos/connection'
@@ -55,13 +56,16 @@ module WorkOS
55
56
  autoload :DirectorySync, 'workos/directory_sync'
56
57
  autoload :DirectoryUser, 'workos/directory_user'
57
58
  autoload :EmailVerification, 'workos/email_verification'
59
+ autoload :Encryptors, 'workos/encryptors'
58
60
  autoload :Event, 'workos/event'
59
61
  autoload :Events, 'workos/events'
60
62
  autoload :Factor, 'workos/factor'
63
+ autoload :FeatureFlag, 'workos/feature_flag'
61
64
  autoload :Impersonator, 'workos/impersonator'
62
65
  autoload :Invitation, 'workos/invitation'
63
66
  autoload :MagicAuth, 'workos/magic_auth'
64
67
  autoload :MFA, 'workos/mfa'
68
+ autoload :OAuthTokens, 'workos/oauth_tokens'
65
69
  autoload :Organization, 'workos/organization'
66
70
  autoload :Organizations, 'workos/organizations'
67
71
  autoload :OrganizationMembership, 'workos/organization_membership'
@@ -71,6 +75,8 @@ module WorkOS
71
75
  autoload :Profile, 'workos/profile'
72
76
  autoload :ProfileAndToken, 'workos/profile_and_token'
73
77
  autoload :RefreshAuthenticationResponse, 'workos/refresh_authentication_response'
78
+ autoload :Role, 'workos/role'
79
+ autoload :Session, 'workos/session'
74
80
  autoload :SSO, 'workos/sso'
75
81
  autoload :Types, 'workos/types'
76
82
  autoload :User, 'workos/user'
@@ -80,11 +86,13 @@ module WorkOS
80
86
  autoload :VerifyChallenge, 'workos/verify_challenge'
81
87
  autoload :Webhook, 'workos/webhook'
82
88
  autoload :Webhooks, 'workos/webhooks'
89
+ autoload :Widgets, 'workos/widgets'
83
90
 
84
91
  # Errors
85
92
  autoload :APIError, 'workos/errors'
86
93
  autoload :AuthenticationError, 'workos/errors'
87
94
  autoload :InvalidRequestError, 'workos/errors'
95
+ autoload :ForbiddenRequestError, 'workos/errors'
88
96
  autoload :SignatureVerificationError, 'workos/errors'
89
97
  autoload :TimeoutError, 'workos/errors'
90
98
  autoload :NotFoundError, 'workos/errors'