descope 1.0.7 → 1.2.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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +51 -12
  3. data/.github/workflows/publish-gem.yaml +6 -33
  4. data/.github/workflows/release-please.yaml +36 -0
  5. data/.gitignore +3 -2
  6. data/.release-please-manifest.json +1 -1
  7. data/.rubocop.yml +1 -1
  8. data/.rubocop_todo.yml +1 -1
  9. data/.ruby-version +1 -1
  10. data/CHANGELOG.md +31 -0
  11. data/Gemfile +7 -6
  12. data/Gemfile.lock +46 -45
  13. data/README.md +244 -1
  14. data/examples/ruby-on-rails-api/descope/package-lock.json +16 -10
  15. data/examples/ruby-on-rails-api/descope/yarn.lock +3 -3
  16. data/lib/descope/api/v1/auth/enchantedlink.rb +76 -9
  17. data/lib/descope/api/v1/management/access_key.rb +8 -7
  18. data/lib/descope/api/v1/management/analytics.rb +62 -0
  19. data/lib/descope/api/v1/management/audit.rb +2 -2
  20. data/lib/descope/api/v1/management/authz.rb +15 -15
  21. data/lib/descope/api/v1/management/common.rb +76 -0
  22. data/lib/descope/api/v1/management/descoper.rb +45 -0
  23. data/lib/descope/api/v1/management/engine.rb +44 -0
  24. data/lib/descope/api/v1/management/fga.rb +64 -0
  25. data/lib/descope/api/v1/management/flow.rb +5 -5
  26. data/lib/descope/api/v1/management/group.rb +42 -0
  27. data/lib/descope/api/v1/management/jwt_template.rb +49 -0
  28. data/lib/descope/api/v1/management/lists.rb +96 -0
  29. data/lib/descope/api/v1/management/management_key.rb +54 -0
  30. data/lib/descope/api/v1/management/outbound_app.rb +112 -0
  31. data/lib/descope/api/v1/management/password.rb +2 -2
  32. data/lib/descope/api/v1/management/permission.rb +4 -4
  33. data/lib/descope/api/v1/management/project.rb +5 -5
  34. data/lib/descope/api/v1/management/role.rb +5 -5
  35. data/lib/descope/api/v1/management/scim.rb +14 -14
  36. data/lib/descope/api/v1/management/scope_claim_mapping.rb +34 -0
  37. data/lib/descope/api/v1/management/sso_application.rb +7 -7
  38. data/lib/descope/api/v1/management/sso_settings.rb +5 -5
  39. data/lib/descope/api/v1/management/tenant.rb +8 -6
  40. data/lib/descope/api/v1/management/third_party_application.rb +190 -0
  41. data/lib/descope/api/v1/management/user.rb +36 -36
  42. data/lib/descope/api/v1/management.rb +22 -0
  43. data/lib/descope/http_client.rb +30 -0
  44. data/lib/descope/mixins/common.rb +1 -0
  45. data/lib/descope/mixins/http.rb +25 -18
  46. data/lib/descope/mixins/initializer.rb +23 -11
  47. data/lib/descope/mixins/requests.rb +24 -0
  48. data/lib/descope/mixins.rb +2 -1
  49. data/lib/descope/version.rb +1 -1
  50. data/spec/integration/lib.descope/api/v1/auth/enchantedlink_spec.rb +19 -21
  51. data/spec/integration/lib.descope/api/v1/auth/magiclink_spec.rb +5 -1
  52. data/spec/integration/lib.descope/api/v1/auth/otp_spec.rb +5 -1
  53. data/spec/integration/lib.descope/api/v1/auth/session_spec.rb +24 -5
  54. data/spec/integration/lib.descope/api/v1/auth/totp_spec.rb +5 -1
  55. data/spec/integration/lib.descope/api/v1/management/access_key_spec.rb +10 -2
  56. data/spec/integration/lib.descope/api/v1/management/authz_spec.rb +26 -5
  57. data/spec/integration/lib.descope/api/v1/management/permissions_spec.rb +20 -2
  58. data/spec/integration/lib.descope/api/v1/management/project_spec.rb +16 -2
  59. data/spec/integration/lib.descope/api/v1/management/roles_spec.rb +114 -36
  60. data/spec/integration/lib.descope/api/v1/management/user_spec.rb +21 -4
  61. data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +163 -1
  62. data/spec/lib.descope/api/v1/management/access_key_spec.rb +7 -7
  63. data/spec/lib.descope/api/v1/management/analytics_spec.rb +82 -0
  64. data/spec/lib.descope/api/v1/management/audit_spec.rb +2 -2
  65. data/spec/lib.descope/api/v1/management/authz_spec.rb +16 -16
  66. data/spec/lib.descope/api/v1/management/descoper_spec.rb +101 -0
  67. data/spec/lib.descope/api/v1/management/engine_spec.rb +115 -0
  68. data/spec/lib.descope/api/v1/management/fga_spec.rb +169 -0
  69. data/spec/lib.descope/api/v1/management/flow_spec.rb +5 -5
  70. data/spec/lib.descope/api/v1/management/group_spec.rb +72 -0
  71. data/spec/lib.descope/api/v1/management/jwt_template_spec.rb +103 -0
  72. data/spec/lib.descope/api/v1/management/lists_spec.rb +285 -0
  73. data/spec/lib.descope/api/v1/management/management_key_spec.rb +109 -0
  74. data/spec/lib.descope/api/v1/management/outbound_app_spec.rb +236 -0
  75. data/spec/lib.descope/api/v1/management/password_spec.rb +2 -2
  76. data/spec/lib.descope/api/v1/management/permission_spec.rb +4 -4
  77. data/spec/lib.descope/api/v1/management/project_spec.rb +4 -4
  78. data/spec/lib.descope/api/v1/management/role_spec.rb +5 -5
  79. data/spec/lib.descope/api/v1/management/scim_spec.rb +14 -14
  80. data/spec/lib.descope/api/v1/management/scope_claim_mapping_spec.rb +59 -0
  81. data/spec/lib.descope/api/v1/management/sso_application_spec.rb +6 -6
  82. data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +5 -5
  83. data/spec/lib.descope/api/v1/management/tenant_spec.rb +6 -6
  84. data/spec/lib.descope/api/v1/management/third_party_application_spec.rb +171 -0
  85. data/spec/lib.descope/api/v1/management/user_spec.rb +36 -36
  86. data/spec/lib.descope/auth_management_key_spec.rb +151 -0
  87. data/spec/lib.descope/mixins/http_spec.rb +17 -6
  88. data/spec/support/client_config.rb +1 -0
  89. data/spec/support/dummy_class.rb +12 -9
  90. data/spec/support/utils.rb +15 -0
  91. metadata +29 -3
data/README.md CHANGED
@@ -31,12 +31,63 @@ descope_client = Descope::Client.new(
31
31
  )
32
32
  ```
33
33
 
34
+ ### Auth Management Key
35
+
36
+ Authentication methods whose public access has been disabled can still be used by providing an
37
+ auth management key. When set, it is sent along with every authentication request.
38
+
39
+ Create one in the [Descope Console](https://app.descope.com/settings/company/managementkeys) with
40
+ either the `Authentication` or `Full Access` scope on the project or company.
41
+
42
+ ```ruby
43
+ # Initialized after setting the DESCOPE_PROJECT_ID and DESCOPE_AUTH_MANAGEMENT_KEY env vars
44
+ descope_client = Descope::Client.new({})
45
+
46
+ # ** Or directly **
47
+ descope_client = Descope::Client.new(
48
+ {
49
+ project_id: '<project_id>',
50
+ auth_management_key: ENV['AUTH_MGMT_KEY']
51
+ }
52
+ )
53
+ ```
54
+
55
+ **Note**: the auth management key can, and probably should, be a different management key than the
56
+ one provided for [management API usage](#setup-1). The auth management key is never sent on
57
+ management requests, and the management key is never sent on authentication requests.
58
+
59
+ ### Request timeout
60
+
61
+ Every request is bounded by a 60 second timeout, matching the other Descope server SDKs. Raise it
62
+ for calls that legitimately take longer, such as `export_project` on a large project:
63
+
64
+ ```ruby
65
+ descope_client = Descope::Client.new(
66
+ {
67
+ project_id: '<project_id>',
68
+ timeout_seconds: 180
69
+ }
70
+ )
71
+ ```
72
+
34
73
  ### Important Logging note
35
74
  You may pass `log_level: 'debug'` to the client config or use `DESCOPE_LOG_LEVEL` env var.
36
- Be aware that only the management key is truncated, and the JWT responses are printed on debug
75
+ Be aware that everything after the project ID in the `Authorization` header is masked, but the JWT
76
+ responses are printed on debug
37
77
 
38
78
  Do not run with log level debug on Production!
39
79
 
80
+ ### Logging
81
+
82
+ You can customize logging behavior:
83
+
84
+ ```ruby
85
+ # Use your application's logger
86
+ descope_client = Descope::Client.new(
87
+ project_id: '<project_id>',
88
+ logger: Rails.logger # or any Logger-compatible object
89
+ )
90
+ ```
40
91
 
41
92
  ## Authentication Methods
42
93
  These sections show how to use the SDK to perform various authentication/authorization functions:
@@ -161,6 +212,33 @@ pending_ref = res['pendingRef'] # Used to poll for a valid session
161
212
  masked_email = res['maskedEmail'] # The email that the message was sent to in a masked format
162
213
  ```
163
214
 
215
+ The same three calls are available over SMS, as `enchanted_link_sign_up_with_phone`,
216
+ `enchanted_link_sign_in_with_phone` and `enchanted_link_sign_up_or_in_with_phone`. The `login_id` is
217
+ a phone number, and the response carries `maskedPhone` instead of `maskedEmail`.
218
+
219
+ ```ruby
220
+ res = descope_client.enchanted_link_sign_up_or_in_with_phone(
221
+ login_id: '+11111111111',
222
+ uri: 'https://myapp.com/verify-enchanted-link', # Set redirect URI here or via console
223
+ template_id: 'my-text-template-id' # Optional, selects a specific text template
224
+ )
225
+ link_identifier = res['linkId'] # Matches the identifier at the start of the SMS, so the user can confirm it
226
+ pending_ref = res['pendingRef'] # Used to poll for a valid session
227
+ masked_phone = res['maskedPhone'] # The phone number that the message was sent to in a masked format
228
+ ```
229
+
230
+ An existing user's phone number can be updated with an enchanted link sent over SMS, using the
231
+ refresh token of their active session:
232
+
233
+ ```ruby
234
+ res = descope_client.enchanted_link_update_user_phone(
235
+ login_id: 'someone@example.com',
236
+ phone: '+11111111111',
237
+ uri: 'https://myapp.com/verify-enchanted-link',
238
+ refresh_token: refresh_token
239
+ )
240
+ ```
241
+
164
242
  After sending the link, you must poll to receive a valid session using the `pending_ref` from
165
243
  the previous step. A valid session will be returned only after the user clicks the right link.
166
244
 
@@ -493,6 +571,8 @@ in nature. Please use responsibly.
493
571
 
494
572
  To use the management API you'll need a `Management Key` along with your `Project ID`.
495
573
  Create one in the [Descope Console](https://app.descope.com/settings/company/managementkeys).
574
+ This key is used only for management functions - to reach authentication methods whose public
575
+ access has been disabled, use the [Auth Management Key](#auth-management-key) instead.
496
576
 
497
577
  ```ruby
498
578
  require 'descope'
@@ -1258,6 +1338,160 @@ resp["apps"].each do |app|
1258
1338
  end
1259
1339
  ```
1260
1340
 
1341
+ ### Manage Third Party Applications
1342
+
1343
+ You can create, update, patch, delete or load third party (OIDC) applications, and manage their secrets and consents:
1344
+
1345
+ ```ruby
1346
+ # Create a third party application (response includes the generated id and secret)
1347
+ resp = descope_client.create_application(
1348
+ name: "My third party app",
1349
+ login_page_url: "https://dummy.com/login"
1350
+ )
1351
+ id = resp["id"]
1352
+
1353
+ # Update (overrides all fields) or patch (only given fields)
1354
+ descope_client.update_application(id: id, name: "Updated name", login_page_url: "https://dummy.com/login")
1355
+ descope_client.patch_application(id: id, name: "Patched name")
1356
+
1357
+ # Load one / all applications
1358
+ descope_client.load_application(id)
1359
+ descope_client.load_all_applications
1360
+
1361
+ # Manage the application secret
1362
+ descope_client.get_application_secret(id)
1363
+ descope_client.rotate_application_secret(id)
1364
+
1365
+ # Delete consents for the application
1366
+ descope_client.delete_consents(app_id: id, user_ids: ["U123"])
1367
+
1368
+ # Application deletion cannot be undone. Use carefully.
1369
+ descope_client.delete_application(id)
1370
+ ```
1371
+
1372
+ ### Manage Management Keys
1373
+
1374
+ Create and manage management keys for a project:
1375
+
1376
+ ```ruby
1377
+ # Response includes the key metadata and the one-time cleartext value
1378
+ resp = descope_client.create_management_key(
1379
+ name: "CI key",
1380
+ description: "used by CI",
1381
+ expires_in: 0, # 0 = no expiration (seconds)
1382
+ permitted_ips: ["1.2.3.4/32"]
1383
+ )
1384
+
1385
+ descope_client.update_management_key(id: "key-id", name: "renamed CI key")
1386
+ descope_client.get_management_key(id: "key-id")
1387
+ descope_client.search_management_keys(status: "active")
1388
+ descope_client.delete_management_key(id: "key-id")
1389
+ ```
1390
+
1391
+ ### Manage Engines
1392
+
1393
+ ```ruby
1394
+ resp = descope_client.create_engine(name: "my-engine") # secret returned only here and on rotate
1395
+ descope_client.update_engine(id: resp["id"], name: "renamed-engine")
1396
+ descope_client.load_engine(id: resp["id"])
1397
+ descope_client.load_all_engines
1398
+ descope_client.rotate_engine_secret(id: resp["id"])
1399
+ descope_client.delete_engine(id: resp["id"])
1400
+ ```
1401
+
1402
+ ### Manage Descopers
1403
+
1404
+ ```ruby
1405
+ descope_client.create_descoper([{ loginId: "admin@descope.com", roleNames: ["Descoper"] }])
1406
+ descope_client.update_descoper(id: "U123", attributes: { name: "Admin" })
1407
+ descope_client.get_descoper(id: "U123")
1408
+ descope_client.search_descopers
1409
+ descope_client.delete_descoper(id: "U123")
1410
+ ```
1411
+
1412
+ ### Manage Lists
1413
+
1414
+ Manage allow/deny lists of IPs and text values:
1415
+
1416
+ ```ruby
1417
+ list = descope_client.create_list(name: "blocklist", type: "ip")
1418
+ descope_client.update_list(id: list["id"], name: "blocklist", type: "ip")
1419
+ descope_client.load_list(list["id"])
1420
+ descope_client.load_list_by_name("blocklist")
1421
+ descope_client.load_all_lists
1422
+ descope_client.import_lists(lists: [{ name: "blocklist", type: "ip", data: ["1.2.3.4"] }])
1423
+
1424
+ # IP entries
1425
+ descope_client.list_add_ips(id: list["id"], ips: ["1.2.3.4"])
1426
+ descope_client.list_remove_ips(id: list["id"], ips: ["1.2.3.4"])
1427
+ descope_client.list_check_ip(id: list["id"], ip: "1.2.3.4")
1428
+
1429
+ # Text entries
1430
+ descope_client.list_add_texts(id: list["id"], texts: ["blocked"])
1431
+ descope_client.list_remove_texts(id: list["id"], texts: ["blocked"])
1432
+ descope_client.list_check_text(id: list["id"], text: "blocked")
1433
+ # Check up to 100 texts in one call: exists if any of them is in the list, or only if all are with match_all: true
1434
+ descope_client.list_check_texts(id: list["id"], texts: ["blocked", "other"])
1435
+ descope_client.list_check_texts(id: list["id"], texts: ["blocked", "other"], match_all: true)
1436
+
1437
+ descope_client.clear_list(id: list["id"])
1438
+ descope_client.delete_list(id: list["id"])
1439
+ ```
1440
+
1441
+ ### Manage JWT Templates
1442
+
1443
+ ```ruby
1444
+ descope_client.create_jwt_template(template: { name: "my-template", authSchema: "default" })
1445
+ descope_client.update_jwt_template(template: { id: "T123", name: "my-template" })
1446
+ descope_client.list_jwt_templates
1447
+ descope_client.load_jwt_template(id: "T123")
1448
+ descope_client.delete_jwt_template(id: "T123")
1449
+ ```
1450
+
1451
+ ### Manage Scope Claim Mapping
1452
+
1453
+ Manage the project-wide OIDC scope-to-claim mapping:
1454
+
1455
+ ```ruby
1456
+ descope_client.set_scope_claim_mapping(mappings: [{ scope: "email", claims: ["email"] }])
1457
+ descope_client.get_scope_claim_mapping
1458
+ descope_client.delete_scope_claim_mapping
1459
+ ```
1460
+
1461
+ ### Query SSO Groups
1462
+
1463
+ Query the SSO groups synced to a project's tenant:
1464
+
1465
+ ```ruby
1466
+ descope_client.load_all_groups(tenant_id: "T123")
1467
+ descope_client.load_all_groups_for_members(tenant_id: "T123", user_ids: ["U123"], login_ids: ["a@b.com"])
1468
+ descope_client.load_all_group_members(tenant_id: "T123", group_id: "G123")
1469
+ ```
1470
+
1471
+ ### Manage FGA (Fine-Grained Authorization)
1472
+
1473
+ Manage a fine-grained authorization schema and relations:
1474
+
1475
+ ```ruby
1476
+ # Save/load the schema (schema is a DSL string)
1477
+ descope_client.fga_save_schema(schema: "model\n schema 1.1\ntype user")
1478
+ descope_client.fga_load_schema
1479
+
1480
+ # Create, delete and check relations
1481
+ tuples = [{ resource: "doc1", resourceType: "document", relation: "owner", target: "u1", targetType: "user" }]
1482
+ descope_client.fga_create_relations(tuples: tuples)
1483
+ descope_client.fga_check(tuples: tuples)
1484
+ descope_client.fga_delete_relations(tuples: tuples)
1485
+ ```
1486
+
1487
+ ### Analytics
1488
+
1489
+ Search project analytics:
1490
+
1491
+ ```ruby
1492
+ descope_client.analytics_search(from_ts: 1700000000000, to_ts: 1700086400000, group_by_action: true)
1493
+ ```
1494
+
1261
1495
 
1262
1496
  ## API Rate Limits
1263
1497
 
@@ -1295,6 +1529,15 @@ You can find various usage examples in the [examples folder](https://github.com/
1295
1529
  bundle install
1296
1530
  ```
1297
1531
 
1532
+ ### Environment variables
1533
+
1534
+ ```bash
1535
+ export DESCOPE_PROJECT_ID=<ProjectID>
1536
+ export DESCOPE_MANAGEMENT_KEY=<ManagementKey>
1537
+ # Optional, only needed for authentication methods with disabled public access
1538
+ export DESCOPE_AUTH_MANAGEMENT_KEY=<AuthManagementKey>
1539
+ ```
1540
+
1298
1541
  ### Run tests
1299
1542
 
1300
1543
  Running all tests:
@@ -73,6 +73,7 @@
73
73
  "version": "10.0.4",
74
74
  "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.4.tgz",
75
75
  "integrity": "sha512-cuBuGK40P/sk5IzWa9QPUaAdvPHjkk1c+xYsd9oZw+YQQEV+10G0P5uMpGctZZKnyQ+ibRO08bD25nWLmYi2pw==",
76
+ "peer": true,
76
77
  "funding": {
77
78
  "type": "opencollective",
78
79
  "url": "https://opencollective.com/immer"
@@ -152,6 +153,7 @@
152
153
  "version": "10.0.4",
153
154
  "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.4.tgz",
154
155
  "integrity": "sha512-cuBuGK40P/sk5IzWa9QPUaAdvPHjkk1c+xYsd9oZw+YQQEV+10G0P5uMpGctZZKnyQ+ibRO08bD25nWLmYi2pw==",
156
+ "peer": true,
155
157
  "funding": {
156
158
  "type": "opencollective",
157
159
  "url": "https://opencollective.com/immer"
@@ -223,6 +225,7 @@
223
225
  "version": "10.0.4",
224
226
  "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.4.tgz",
225
227
  "integrity": "sha512-cuBuGK40P/sk5IzWa9QPUaAdvPHjkk1c+xYsd9oZw+YQQEV+10G0P5uMpGctZZKnyQ+ibRO08bD25nWLmYi2pw==",
228
+ "peer": true,
226
229
  "funding": {
227
230
  "type": "opencollective",
228
231
  "url": "https://opencollective.com/immer"
@@ -721,6 +724,7 @@
721
724
  "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
722
725
  "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
723
726
  "license": "MIT",
727
+ "peer": true,
724
728
  "funding": {
725
729
  "type": "opencollective",
726
730
  "url": "https://opencollective.com/popperjs"
@@ -736,6 +740,7 @@
736
740
  "version": "2.2.3",
737
741
  "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.3.tgz",
738
742
  "integrity": "sha512-76dll9EnJXg4EVcI5YNxZA/9hSAmZsFqzMmNRHvIlzw2WS/twfcVX3ysYrWGJMClwEmChQFC4yRq74tn6fdzRA==",
743
+ "peer": true,
739
744
  "dependencies": {
740
745
  "immer": "^10.0.3",
741
746
  "redux": "^5.0.1",
@@ -775,8 +780,7 @@
775
780
  "node_modules/@types/prop-types": {
776
781
  "version": "15.7.11",
777
782
  "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
778
- "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
779
- "peer": true
783
+ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
780
784
  },
781
785
  "node_modules/@types/react": {
782
786
  "version": "18.2.48",
@@ -792,8 +796,7 @@
792
796
  "node_modules/@types/scheduler": {
793
797
  "version": "0.16.8",
794
798
  "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
795
- "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
796
- "peer": true
799
+ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
797
800
  },
798
801
  "node_modules/abbrev": {
799
802
  "version": "1.1.1",
@@ -864,9 +867,9 @@
864
867
  "license": "MIT"
865
868
  },
866
869
  "node_modules/brace-expansion": {
867
- "version": "1.1.11",
868
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
869
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
870
+ "version": "1.1.12",
871
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
872
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
870
873
  "license": "MIT",
871
874
  "dependencies": {
872
875
  "balanced-match": "^1.0.0",
@@ -916,8 +919,7 @@
916
919
  "node_modules/csstype": {
917
920
  "version": "3.1.3",
918
921
  "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
919
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
920
- "peer": true
922
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
921
923
  },
922
924
  "node_modules/debug": {
923
925
  "version": "4.3.4",
@@ -1241,6 +1243,7 @@
1241
1243
  "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
1242
1244
  "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
1243
1245
  "license": "MIT",
1246
+ "peer": true,
1244
1247
  "dependencies": {
1245
1248
  "loose-envify": "^1.1.0"
1246
1249
  },
@@ -1253,6 +1256,7 @@
1253
1256
  "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
1254
1257
  "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
1255
1258
  "license": "MIT",
1259
+ "peer": true,
1256
1260
  "dependencies": {
1257
1261
  "loose-envify": "^1.1.0",
1258
1262
  "scheduler": "^0.23.0"
@@ -1306,12 +1310,14 @@
1306
1310
  "node_modules/redux": {
1307
1311
  "version": "5.0.1",
1308
1312
  "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
1309
- "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
1313
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
1314
+ "peer": true
1310
1315
  },
1311
1316
  "node_modules/redux-thunk": {
1312
1317
  "version": "3.1.0",
1313
1318
  "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
1314
1319
  "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
1320
+ "peer": true,
1315
1321
  "peerDependencies": {
1316
1322
  "redux": "^5.0.0"
1317
1323
  }
@@ -331,9 +331,9 @@ bootstrap@^5.3.3:
331
331
  integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==
332
332
 
333
333
  brace-expansion@^1.1.7:
334
- version "1.1.11"
335
- resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
336
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
334
+ version "1.1.12"
335
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843"
336
+ integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==
337
337
  dependencies:
338
338
  balanced-match "^1.0.0"
339
339
  concat-map "0.0.1"
@@ -17,7 +17,17 @@ module Descope
17
17
  validate_refresh_token_provided(login_options, refresh_token)
18
18
  body = enchanted_link_compose_signin_body(login_id, uri, login_options)
19
19
  uri = enchanted_link_compose_signin_url
20
- post(uri, body, nil, refresh_token)
20
+ post(uri, body, {}, refresh_token)
21
+ end
22
+
23
+ def enchanted_link_sign_in_with_phone(login_id: nil, uri: nil, login_options: nil, provider_id: nil, template_id: nil, refresh_token: nil)
24
+ validate_login_id(login_id)
25
+ validate_refresh_token_provided(login_options, refresh_token)
26
+ body = enchanted_link_compose_signin_body(login_id, uri, login_options)
27
+ body[:providerId] = provider_id if provider_id
28
+ body[:templateId] = template_id if template_id
29
+ uri = enchanted_link_compose_signin_url(Descope::Mixins::Common::DeliveryMethod::SMS)
30
+ post(uri, body, {}, refresh_token)
21
31
  end
22
32
 
23
33
  def enchanted_link_sign_up(login_id: nil, uri: nil, user: {})
@@ -36,6 +46,23 @@ module Descope
36
46
  post(uri, body)
37
47
  end
38
48
 
49
+ def enchanted_link_sign_up_with_phone(login_id: nil, uri: nil, user: {}, provider_id: nil, template_id: nil)
50
+ method = Descope::Mixins::Common::DeliveryMethod::SMS
51
+
52
+ unless adjust_and_verify_delivery_method(method, login_id, user)
53
+ raise Descope::ArgumentException.new(
54
+ 'Invalid delivery method',
55
+ code: 400
56
+ )
57
+ end
58
+
59
+ body = enchanted_link_compose_signup_body(login_id, uri, user, method)
60
+ body[:providerId] = provider_id if provider_id
61
+ body[:templateId] = template_id if template_id
62
+ uri = enchanted_link_compose_signup_url(method)
63
+ post(uri, body)
64
+ end
65
+
39
66
  def enchanted_link_sign_up_or_in(login_id: nil, uri: nil, login_options: nil)
40
67
  # @see https://docs.descope.com/api/openapi/enchantedlink/operation/SignUpOrInEnchantedLinkEmail/
41
68
  body = enchanted_link_compose_signin_body(login_id, uri, login_options)
@@ -43,6 +70,14 @@ module Descope
43
70
  post(uri, body)
44
71
  end
45
72
 
73
+ def enchanted_link_sign_up_or_in_with_phone(login_id: nil, uri: nil, login_options: nil, provider_id: nil, template_id: nil)
74
+ body = enchanted_link_compose_signin_body(login_id, uri, login_options)
75
+ body[:providerId] = provider_id if provider_id
76
+ body[:templateId] = template_id if template_id
77
+ uri = enchanted_link_compose_sign_up_or_in_url(Descope::Mixins::Common::DeliveryMethod::SMS)
78
+ post(uri, body)
79
+ end
80
+
46
81
  def enchanted_link_update_user_email(login_id: nil, email: nil, uri: nil, add_to_login_ids: nil, on_merge_use_existing: nil, provider_id: nil, template_id: nil, template_options: nil, refresh_token: nil)
47
82
  validate_login_id(login_id)
48
83
  validate_token_not_empty(refresh_token)
@@ -59,6 +94,22 @@ module Descope
59
94
  post(uri, body, {}, refresh_token)
60
95
  end
61
96
 
97
+ def enchanted_link_update_user_phone(login_id: nil, phone: nil, uri: nil, add_to_login_ids: nil, on_merge_use_existing: nil, provider_id: nil, template_id: nil, template_options: nil, refresh_token: nil)
98
+ validate_login_id(login_id)
99
+ validate_token_not_empty(refresh_token)
100
+ validate_phone(Descope::Mixins::Common::DeliveryMethod::SMS, phone)
101
+
102
+ body = enchanted_link_compose_update_user_phone_body(
103
+ login_id, phone, add_to_login_ids, on_merge_use_existing
104
+ )
105
+ body[:redirectUrl] = uri
106
+ body[:providerId] = provider_id if provider_id
107
+ body[:templateId] = template_id if template_id
108
+ body[:templateOptions] = template_options if template_options
109
+ uri = compose_url(UPDATE_USER_PHONE_ENCHANTEDLINK_PATH, Descope::Mixins::Common::DeliveryMethod::SMS)
110
+ post(uri, body, {}, refresh_token)
111
+ end
112
+
62
113
  def enchanted_link_verify_token(token = nil)
63
114
  validate_token_not_empty(token)
64
115
  post(VERIFY_ENCHANTEDLINK_AUTH_PATH, { token: })
@@ -97,19 +148,23 @@ module Descope
97
148
  body
98
149
  end
99
150
 
100
- def enchanted_link_compose_signin_url
101
- compose_url(SIGN_IN_AUTH_ENCHANTEDLINK_PATH, Descope::Mixins::Common::DeliveryMethod::EMAIL)
151
+ def enchanted_link_compose_signin_url(method = nil)
152
+ method = Descope::Mixins::Common::DeliveryMethod::EMAIL if method.nil?
153
+ compose_url(SIGN_IN_AUTH_ENCHANTEDLINK_PATH, method)
102
154
  end
103
155
 
104
- def enchanted_link_compose_signup_url
105
- compose_url(SIGN_UP_AUTH_ENCHANTEDLINK_PATH, Descope::Mixins::Common::DeliveryMethod::EMAIL)
156
+ def enchanted_link_compose_signup_url(method = nil)
157
+ method = Descope::Mixins::Common::DeliveryMethod::EMAIL if method.nil?
158
+ compose_url(SIGN_UP_AUTH_ENCHANTEDLINK_PATH, method)
106
159
  end
107
160
 
108
- def enchanted_link_compose_sign_up_or_in_url
109
- compose_url(SIGN_UP_OR_IN_AUTH_ENCHANTEDLINK_PATH, Descope::Mixins::Common::DeliveryMethod::EMAIL)
161
+ def enchanted_link_compose_sign_up_or_in_url(method = nil)
162
+ method = Descope::Mixins::Common::DeliveryMethod::EMAIL if method.nil?
163
+ compose_url(SIGN_UP_OR_IN_AUTH_ENCHANTEDLINK_PATH, method)
110
164
  end
111
165
 
112
- def enchanted_link_compose_signup_body(login_id, uri, user)
166
+ def enchanted_link_compose_signup_body(login_id, uri, user, method = nil)
167
+ method = Descope::Mixins::Common::DeliveryMethod::EMAIL if method.nil?
113
168
  body = {
114
169
  loginId: login_id,
115
170
  redirectUrl: uri
@@ -118,7 +173,7 @@ module Descope
118
173
  unless user.nil? || user.empty?
119
174
  body[:user] = enchantedlink_user_compose_update_body(**user) unless user.empty?
120
175
 
121
- method_str, val = get_login_id_by_method(method: Descope::Mixins::Common::DeliveryMethod::EMAIL, user:)
176
+ method_str, val = get_login_id_by_method(method:, user:)
122
177
  body[method_str.to_sym] = val
123
178
  end
124
179
 
@@ -137,6 +192,18 @@ module Descope
137
192
  body
138
193
  end
139
194
 
195
+ def enchanted_link_compose_update_user_phone_body(login_id, phone, add_to_login_ids, on_merge_use_existing)
196
+ body = {
197
+ loginId: login_id,
198
+ phone:
199
+ }
200
+
201
+ body[:addToLoginIDs] = add_to_login_ids if add_to_login_ids
202
+ body[:onMergeUseExisting] = on_merge_use_existing if on_merge_use_existing
203
+
204
+ body
205
+ end
206
+
140
207
 
141
208
  private
142
209
  def enchantedlink_user_compose_update_body(login_id: nil, name: nil, phone: nil, email: nil, given_name: nil, middle_name: nil, family_name: nil)
@@ -16,7 +16,8 @@ module Descope
16
16
  role_names ||= []
17
17
  key_tenants ||= []
18
18
  validate_tenants(key_tenants)
19
- post(ACCESS_KEY_CREATE_PATH, access_key_compose_create_body(name, expire_time, role_names, key_tenants, custom_claims))
19
+ mgmt_post(ACCESS_KEY_CREATE_PATH,
20
+ access_key_compose_create_body(name, expire_time, role_names, key_tenants, custom_claims))
20
21
  end
21
22
 
22
23
  def access_key_compose_create_body(name, expire_time, role_names, key_tenants, custom_claims)
@@ -34,7 +35,7 @@ module Descope
34
35
  # @param id [string] The access key id.
35
36
  # @see https://docs.descope.com/api/openapi/accesskeymanagement/operation/LoadAccessKey/
36
37
 
37
- get(ACCESS_KEY_LOAD_PATH, { id: })
38
+ mgmt_get(ACCESS_KEY_LOAD_PATH, { id: })
38
39
  end
39
40
 
40
41
  def search_all_access_keys(tenant_ids = nil)
@@ -43,7 +44,7 @@ module Descope
43
44
  request_params = {
44
45
  tenantIds: tenant_ids
45
46
  }
46
- post(ACCESS_KEYS_SEARCH_PATH, request_params)
47
+ mgmt_post(ACCESS_KEYS_SEARCH_PATH, request_params)
47
48
  end
48
49
 
49
50
  def update_access_key(id: nil, name: nil)
@@ -53,27 +54,27 @@ module Descope
53
54
  id:,
54
55
  name:
55
56
  }
56
- post(ACCESS_KEY_UPDATE_PATH, request_params)
57
+ mgmt_post(ACCESS_KEY_UPDATE_PATH, request_params)
57
58
  end
58
59
 
59
60
  def deactivate_access_key(id)
60
61
  # Deactivate an existing access key. IMPORTANT: This deactivated key will not be usable from this stage.
61
62
  # It will, however, persist, and can be activated again if needed.
62
63
  # @see https://docs.descope.com/api/openapi/accesskeymanagement/operation/DeactivateAccessKey/
63
- post(ACCESS_KEY_DEACTIVATE_PATH, { id: })
64
+ mgmt_post(ACCESS_KEY_DEACTIVATE_PATH, { id: })
64
65
  end
65
66
 
66
67
  def activate_access_key(id)
67
68
  # Activate an existing access key. IMPORTANT: Only deactivated keys can be activated again,
68
69
  # and become usable once more. New access keys are active by default.
69
70
  # @see https://docs.descope.com/api/openapi/accesskeymanagement/operation/ActivateAccessKey/
70
- post(ACCESS_KEY_ACTIVATE_PATH, { id: })
71
+ mgmt_post(ACCESS_KEY_ACTIVATE_PATH, { id: })
71
72
  end
72
73
 
73
74
  def delete_access_key(id)
74
75
  # Delete an existing access key. IMPORTANT: This action is irreversible. Use carefully.
75
76
  # @see https://docs.descope.com/api/openapi/accesskeymanagement/operation/DeleteAccessKey/
76
- post(ACCESS_KEY_DELETE_PATH, { id: })
77
+ mgmt_post(ACCESS_KEY_DELETE_PATH, { id: })
77
78
  end
78
79
  end
79
80
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Descope
4
+ module Api
5
+ module V1
6
+ module Management
7
+ # Management API calls for analytics
8
+ module Analytics
9
+ include Descope::Api::V1::Management::Common
10
+
11
+ def analytics_search(
12
+ from_ts:,
13
+ to_ts:,
14
+ actions: nil,
15
+ excluded_actions: nil,
16
+ devices: nil,
17
+ methods: nil,
18
+ geos: nil,
19
+ tenants: nil,
20
+ group_by_action: false,
21
+ group_by_device: false,
22
+ group_by_method: false,
23
+ group_by_geo: false,
24
+ group_by_tenant: false,
25
+ group_by_referrer: false,
26
+ group_by_created: false
27
+ )
28
+ # Search project analytics based on given parameters
29
+ # from_ts (int): Retrieve records newer than given time in epoch milliseconds
30
+ # to_ts (int): Retrieve records older than given time in epoch milliseconds
31
+ # actions (Array): Optional list of actions to filter by
32
+ # excluded_actions (Array): Optional list of actions to exclude
33
+ # devices (Array): Optional list of devices to filter by
34
+ # methods (Array): Optional list of methods to filter by
35
+ # geos (Array): Optional list of geos to filter by. Geo is currently country code like "US", "IL", etc.
36
+ # tenants (Array): Optional list of tenants to filter by
37
+ # group_by_* (bool): Optional grouping flags for the returned analytics
38
+ request_params = {
39
+ from: from_ts,
40
+ to: to_ts,
41
+ groupByAction: group_by_action,
42
+ groupByDevice: group_by_device,
43
+ groupByMethod: group_by_method,
44
+ groupByGeo: group_by_geo,
45
+ groupByTenant: group_by_tenant,
46
+ groupByReferrer: group_by_referrer,
47
+ groupByCreated: group_by_created
48
+ }
49
+ request_params[:actions] = actions unless actions.nil?
50
+ request_params[:excludedActions] = excluded_actions unless excluded_actions.nil?
51
+ request_params[:devices] = devices unless devices.nil?
52
+ request_params[:methods] = methods unless methods.nil?
53
+ request_params[:geos] = geos unless geos.nil?
54
+ request_params[:tenants] = tenants unless tenants.nil?
55
+
56
+ mgmt_post(ANALYTICS_SEARCH_PATH, request_params)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end