auth0-deploy-cli 8.24.0 → 8.26.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 (45) hide show
  1. package/.github/workflows/claude-code-review.yml +1 -4
  2. package/CHANGELOG.md +44 -1
  3. package/lib/context/directory/handlers/tenant.js +7 -2
  4. package/lib/context/directory/index.js +3 -0
  5. package/lib/context/index.js +10 -0
  6. package/lib/context/yaml/handlers/tenant.js +7 -2
  7. package/lib/context/yaml/index.js +5 -0
  8. package/lib/sessionDurationsToMinutes.d.ts +5 -1
  9. package/lib/sessionDurationsToMinutes.js +5 -1
  10. package/lib/tools/auth0/handlers/actions.js +1 -1
  11. package/lib/tools/auth0/handlers/clientGrants.d.ts +5 -0
  12. package/lib/tools/auth0/handlers/clientGrants.js +18 -3
  13. package/lib/tools/auth0/handlers/clients.d.ts +43 -8
  14. package/lib/tools/auth0/handlers/clients.js +106 -35
  15. package/lib/tools/auth0/handlers/connectionProfiles.js +0 -3
  16. package/lib/tools/auth0/handlers/connections.d.ts +5 -6
  17. package/lib/tools/auth0/handlers/connections.js +41 -53
  18. package/lib/tools/auth0/handlers/customDomains.d.ts +4 -0
  19. package/lib/tools/auth0/handlers/customDomains.js +6 -3
  20. package/lib/tools/auth0/handlers/databases.d.ts +57 -0
  21. package/lib/tools/auth0/handlers/databases.js +52 -2
  22. package/lib/tools/auth0/handlers/default.js +2 -4
  23. package/lib/tools/auth0/handlers/flowVaultConnections.js +6 -3
  24. package/lib/tools/auth0/handlers/flows.js +0 -3
  25. package/lib/tools/auth0/handlers/forms.js +0 -3
  26. package/lib/tools/auth0/handlers/index.d.ts +1 -0
  27. package/lib/tools/auth0/handlers/logStreams.js +0 -3
  28. package/lib/tools/auth0/handlers/organizations.d.ts +4 -1
  29. package/lib/tools/auth0/handlers/organizations.js +61 -32
  30. package/lib/tools/auth0/handlers/prompts.d.ts +2 -2
  31. package/lib/tools/auth0/handlers/prompts.js +1 -0
  32. package/lib/tools/auth0/handlers/resourceServers.d.ts +1 -3
  33. package/lib/tools/auth0/handlers/resourceServers.js +4 -4
  34. package/lib/tools/auth0/handlers/roles.js +6 -3
  35. package/lib/tools/auth0/handlers/scimHandler.d.ts +5 -8
  36. package/lib/tools/auth0/handlers/scimHandler.js +13 -13
  37. package/lib/tools/auth0/handlers/tokenExchangeProfiles.d.ts +0 -14
  38. package/lib/tools/auth0/handlers/tokenExchangeProfiles.js +27 -34
  39. package/lib/tools/auth0/handlers/userAttributeProfiles.js +0 -3
  40. package/lib/tools/auth0/schema.d.ts +7 -0
  41. package/lib/tools/auth0/schema.js +11 -0
  42. package/lib/tools/utils.d.ts +1 -0
  43. package/lib/tools/utils.js +14 -0
  44. package/lib/types.d.ts +4 -0
  45. package/package.json +8 -8
@@ -168,16 +168,21 @@ const getConnectionEnabledClients = async (auth0Client, connectionId) => {
168
168
  try {
169
169
  const enabledClientsFormatted = [];
170
170
  let enabledClients = await auth0Client.connections.clients.get(connectionId);
171
- do {
172
- if (enabledClients && enabledClients.data?.length > 0) {
173
- enabledClients.data.forEach((client) => {
174
- if (client?.client_id) {
175
- enabledClientsFormatted.push(client.client_id);
176
- }
177
- });
171
+ // Process first page
172
+ enabledClients.data?.forEach((client) => {
173
+ if (client?.client_id) {
174
+ enabledClientsFormatted.push(client.client_id);
178
175
  }
176
+ });
177
+ // Fetch remaining pages
178
+ while (enabledClients.hasNextPage()) {
179
179
  enabledClients = await enabledClients.getNextPage();
180
- } while (enabledClients.hasNextPage());
180
+ enabledClients.data?.forEach((client) => {
181
+ if (client?.client_id) {
182
+ enabledClientsFormatted.push(client.client_id);
183
+ }
184
+ });
185
+ }
181
186
  return enabledClientsFormatted;
182
187
  }
183
188
  catch (error) {
@@ -277,7 +282,7 @@ class ConnectionsHandler extends default_1.default {
277
282
  functions: {
278
283
  // When `connections` is updated, it can result in `update`,`create` or `delete` action on SCIM.
279
284
  // Because, `scim_configuration` is inside `connections`.
280
- update: async (requestParams, bodyParams) => this.scimHandler.updateOverride(requestParams, bodyParams),
285
+ update: async (connectionId, bodyParams) => this.scimHandler.updateOverride(connectionId, bodyParams),
281
286
  // When a new `connection` is created. We can perform only `create` option on SCIM.
282
287
  // When a connection is `deleted`. `scim_configuration` is also deleted along with it; no action on SCIM is required.
283
288
  create: async (bodyParams) => this.scimHandler.createOverride(bodyParams),
@@ -306,45 +311,19 @@ class ConnectionsHandler extends default_1.default {
306
311
  }
307
312
  }
308
313
  /**
309
- * Retrieves directory provisioning configuration for a specific Auth0 connection.
310
- * @param connectionId - The unique identifier of the connection
311
- * @returns A promise that resolves to the configuration object, or null if not configured/supported
314
+ * Retrieves all directory provisioning configurations for all connections.
315
+ * @returns A promise that resolves to the configurations object, or null if not configured/supported
312
316
  */
313
- async getConnectionDirectoryProvisioning(connectionId) {
314
- if (!connectionId)
315
- return null;
316
- const creates = [connectionId];
317
- let config = null;
317
+ async getConnectionDirectoryProvisionings() {
318
+ let directoryProvisioningConfigs;
318
319
  try {
319
- await this.client.pool
320
- .addEachTask({
321
- data: creates || [],
322
- generator: async (id) => this.client.connections.directoryProvisioning
323
- .get(id)
324
- .then((resp) => {
325
- config = resp;
326
- })
327
- .catch((err) => {
328
- throw new auth0_1.ManagementError(err);
329
- }),
330
- })
331
- .promise();
332
- const stripKeysFromOutput = [
333
- 'connection_id',
334
- 'connection_name',
335
- 'strategy',
336
- 'created_at',
337
- 'updated_at',
338
- ];
339
- stripKeysFromOutput.forEach((key) => {
340
- if (config && key in config) {
341
- delete config[key];
342
- }
320
+ directoryProvisioningConfigs = await (0, client_1.paginate)(this.client.connections.directoryProvisioning.list, {
321
+ checkpoint: true,
343
322
  });
344
- return config;
323
+ return directoryProvisioningConfigs;
345
324
  }
346
325
  catch (error) {
347
- const errLog = `Unable to fetch directory provisioning for connection '${connectionId}'. `;
326
+ const errLog = `Unable to fetch directory provisioning for connections. `;
348
327
  if (error instanceof auth0_1.ManagementError) {
349
328
  const bodyMessage = error.body?.message;
350
329
  logger_1.default.warn(errLog + bodyMessage);
@@ -471,9 +450,12 @@ class ConnectionsHandler extends default_1.default {
471
450
  async getType() {
472
451
  if (this.existing)
473
452
  return this.existing;
474
- const connections = await (0, client_1.paginate)(this.client.connections.list, {
475
- checkpoint: true,
476
- });
453
+ const [connections, directoryProvisioningConfigs] = await Promise.all([
454
+ (0, client_1.paginate)(this.client.connections.list, {
455
+ checkpoint: true,
456
+ }),
457
+ this.getConnectionDirectoryProvisionings(),
458
+ ]);
477
459
  // Filter out database connections as we have separate handler for it
478
460
  const filteredConnections = connections.filter((c) => c.strategy !== 'auth0');
479
461
  // If options option is empty for all connection, log the missing options scope.
@@ -493,10 +475,13 @@ class ConnectionsHandler extends default_1.default {
493
475
  if (enabledClients && enabledClients?.length) {
494
476
  connection.enabled_clients = enabledClients;
495
477
  }
496
- if (connection.strategy === 'google-apps') {
497
- const dirProvConfig = await this.getConnectionDirectoryProvisioning(con.id);
478
+ if (connection.strategy === 'google-apps' && directoryProvisioningConfigs) {
479
+ const dirProvConfig = directoryProvisioningConfigs.find((congigCon) => congigCon.connection_id === con.id);
498
480
  if (dirProvConfig) {
499
- connection.directory_provisioning_configuration = dirProvConfig;
481
+ connection.directory_provisioning_configuration = {
482
+ mapping: dirProvConfig.mapping,
483
+ synchronize_automatically: dirProvConfig.synchronize_automatically,
484
+ };
500
485
  }
501
486
  }
502
487
  return connection;
@@ -551,13 +536,16 @@ class ConnectionsHandler extends default_1.default {
551
536
  if (!isOptionExists) {
552
537
  logger_1.default.warn(`Insufficient scope the update:connections_options scope is required to update ${this.type} options.`);
553
538
  }
539
+ const includedConnections = (assets.include && assets.include.connections) || [];
554
540
  const excludedConnections = (assets.exclude && assets.exclude.connections) || [];
555
- const changes = await this.calcChanges(assets);
556
- await super.processChanges(assets, (0, utils_1.filterExcluded)(changes, excludedConnections));
541
+ let changes = await this.calcChanges(assets);
542
+ changes = (0, utils_1.filterExcluded)(changes, excludedConnections);
543
+ changes = (0, utils_1.filterIncluded)(changes, includedConnections);
544
+ await super.processChanges(assets, changes);
557
545
  // process enabled clients
558
- await (0, exports.processConnectionEnabledClients)(this.client, this.type, (0, utils_1.filterExcluded)(changes, excludedConnections));
546
+ await (0, exports.processConnectionEnabledClients)(this.client, this.type, changes);
559
547
  // process directory provisioning
560
- await this.processConnectionDirectoryProvisioning((0, utils_1.filterExcluded)(changes, excludedConnections));
548
+ await this.processConnectionDirectoryProvisioning(changes);
561
549
  }
562
550
  }
563
551
  exports.default = ConnectionsHandler;
@@ -46,6 +46,10 @@ export declare const schema: {
46
46
  description: string;
47
47
  defaultValue: string;
48
48
  };
49
+ relying_party_identifier: {
50
+ type: string[];
51
+ description: string;
52
+ };
49
53
  };
50
54
  required: string[];
51
55
  };
@@ -77,6 +77,10 @@ exports.schema = {
77
77
  description: 'Custom domain verification method. Must be `txt`.',
78
78
  defaultValue: 'txt',
79
79
  },
80
+ relying_party_identifier: {
81
+ type: ['string'],
82
+ description: 'Relying Party ID (rpId) to be used for Passkeys on this custom domain. If not provided or set to null, the full domain will be used.',
83
+ },
80
84
  },
81
85
  required: ['domain', 'type'],
82
86
  },
@@ -95,6 +99,7 @@ class CustomDomainsHadnler extends default_1.default {
95
99
  'certificate',
96
100
  'created_at',
97
101
  'updated_at',
102
+ 'is_default',
98
103
  ],
99
104
  stripUpdateFields: [
100
105
  'status',
@@ -106,10 +111,8 @@ class CustomDomainsHadnler extends default_1.default {
106
111
  'certificate',
107
112
  'created_at',
108
113
  'updated_at',
114
+ 'is_default',
109
115
  ],
110
- functions: {
111
- update: (args, data) => this.client.customDomains.update(args.custom_domain_id, data),
112
- },
113
116
  });
114
117
  }
115
118
  objString(item) {
@@ -16,6 +16,50 @@ export declare const schema: {
16
16
  options: {
17
17
  type: string;
18
18
  properties: {
19
+ authentication_methods: {
20
+ type: string;
21
+ properties: {
22
+ passkey: {
23
+ type: string;
24
+ properties: {
25
+ enabled: {
26
+ type: string;
27
+ };
28
+ };
29
+ };
30
+ password: {
31
+ type: string;
32
+ properties: {
33
+ enabled: {
34
+ type: string;
35
+ };
36
+ api_behavior: {
37
+ type: string;
38
+ };
39
+ };
40
+ };
41
+ email_otp: {
42
+ type: string;
43
+ properties: {
44
+ enabled: {
45
+ type: string;
46
+ };
47
+ };
48
+ };
49
+ phone_otp: {
50
+ type: string;
51
+ properties: {
52
+ enabled: {
53
+ type: string;
54
+ };
55
+ };
56
+ };
57
+ };
58
+ };
59
+ disable_self_service_change_password: {
60
+ type: string;
61
+ default: boolean;
62
+ };
19
63
  customScripts: {
20
64
  type: string;
21
65
  properties: {};
@@ -36,6 +80,10 @@ export declare const schema: {
36
80
  active: {
37
81
  type: string;
38
82
  };
83
+ default_method: {
84
+ type: string;
85
+ enum: string[];
86
+ };
39
87
  };
40
88
  };
41
89
  profile_required: {
@@ -73,6 +121,10 @@ export declare const schema: {
73
121
  active: {
74
122
  type: string;
75
123
  };
124
+ default_method: {
125
+ type: string;
126
+ enum: string[];
127
+ };
76
128
  };
77
129
  };
78
130
  profile_required: {
@@ -106,6 +158,10 @@ export declare const schema: {
106
158
  active: {
107
159
  type: string;
108
160
  };
161
+ default_method: {
162
+ type: string;
163
+ enum: string[];
164
+ };
109
165
  };
110
166
  };
111
167
  profile_required: {
@@ -134,6 +190,7 @@ export default class DatabaseHandler extends DefaultAPIHandler {
134
190
  constructor(config: DefaultAPIHandler);
135
191
  objString(db: any): string;
136
192
  validate(assets: Assets): Promise<void>;
193
+ private validatePasswordlessSettings;
137
194
  private validateEmailUniqueConstraints;
138
195
  getClientFN(fn: 'create' | 'delete' | 'getAll' | 'update'): Function;
139
196
  getType(): Promise<Asset | Asset[]>;
@@ -60,6 +60,37 @@ exports.schema = {
60
60
  options: {
61
61
  type: 'object',
62
62
  properties: {
63
+ authentication_methods: {
64
+ type: 'object',
65
+ properties: {
66
+ passkey: {
67
+ type: 'object',
68
+ properties: {
69
+ enabled: { type: 'boolean' },
70
+ },
71
+ },
72
+ password: {
73
+ type: 'object',
74
+ properties: {
75
+ enabled: { type: 'boolean' },
76
+ api_behavior: { type: 'string' },
77
+ },
78
+ },
79
+ email_otp: {
80
+ type: 'object',
81
+ properties: {
82
+ enabled: { type: 'boolean' },
83
+ },
84
+ },
85
+ phone_otp: {
86
+ type: 'object',
87
+ properties: {
88
+ enabled: { type: 'boolean' },
89
+ },
90
+ },
91
+ },
92
+ },
93
+ disable_self_service_change_password: { type: 'boolean', default: false },
63
94
  customScripts: {
64
95
  type: 'object',
65
96
  properties: {
@@ -77,6 +108,7 @@ exports.schema = {
77
108
  type: 'object',
78
109
  properties: {
79
110
  active: { type: 'boolean' },
111
+ default_method: { type: 'string', enum: ['password', 'email_otp'] },
80
112
  },
81
113
  },
82
114
  profile_required: { type: 'boolean' },
@@ -102,6 +134,7 @@ exports.schema = {
102
134
  type: 'object',
103
135
  properties: {
104
136
  active: { type: 'boolean' },
137
+ default_method: { type: 'string', enum: ['password', 'phone_otp'] },
105
138
  },
106
139
  },
107
140
  profile_required: { type: 'boolean' },
@@ -126,6 +159,7 @@ exports.schema = {
126
159
  type: 'object',
127
160
  properties: {
128
161
  active: { type: 'boolean' },
162
+ default_method: { type: 'string', enum: ['password'] },
129
163
  },
130
164
  },
131
165
  profile_required: { type: 'boolean' },
@@ -164,9 +198,25 @@ class DatabaseHandler extends default_1.default {
164
198
  // Validate each database
165
199
  databases.forEach((database) => {
166
200
  this.validateEmailUniqueConstraints(database);
201
+ this.validatePasswordlessSettings(database);
167
202
  });
168
203
  await super.validate(assets);
169
204
  }
205
+ validatePasswordlessSettings(payload) {
206
+ const options = payload?.options;
207
+ if (!options)
208
+ return;
209
+ const passwordEnabled = options?.authentication_methods?.password?.enabled;
210
+ const disableSelfServiceChangePassword = options?.disable_self_service_change_password;
211
+ if (passwordEnabled === undefined || disableSelfServiceChangePassword === undefined)
212
+ return;
213
+ if (passwordEnabled === false && disableSelfServiceChangePassword !== true) {
214
+ throw new Error(`Database "${payload.name}": When password authentication is disabled, disable_self_service_change_password must be true.`);
215
+ }
216
+ if (passwordEnabled === true && disableSelfServiceChangePassword === true) {
217
+ throw new Error(`Database "${payload.name}": disable_self_service_change_password must be false when password authentication is enabled.`);
218
+ }
219
+ }
170
220
  validateEmailUniqueConstraints(payload) {
171
221
  const attributes = payload?.options?.attributes;
172
222
  // Only validate if attributes are present
@@ -196,7 +246,7 @@ class DatabaseHandler extends default_1.default {
196
246
  }
197
247
  // If we going to update database, we need to get current options first
198
248
  if (fn === 'update') {
199
- return (params, payload) => this.client.connections.get(params?.id).then((response) => {
249
+ return (id, payload) => this.client.connections.get(id).then((response) => {
200
250
  const connection = response;
201
251
  const attributes = payload?.options?.attributes;
202
252
  const requiresUsername = payload?.options?.requires_username;
@@ -215,7 +265,7 @@ class DatabaseHandler extends default_1.default {
215
265
  if (payload.options && Object.keys(payload.options).length === 0) {
216
266
  delete payload.options;
217
267
  }
218
- return this.client.connections.update(params.id, payload);
268
+ return this.client.connections.update(id, payload);
219
269
  });
220
270
  }
221
271
  return this.client.connections[fn].bind(this.client.connections);
@@ -232,12 +232,11 @@ class APIHandler {
232
232
  data: conflicts || [],
233
233
  generator: (updateItem) => retryWithExponentialBackoff(() => {
234
234
  const updateFN = this.getClientFN(this.functions.update);
235
- const params = { [this.id]: updateItem[this.id] };
236
235
  const updatePayload = (() => {
237
236
  const data = (0, utils_1.stripFields)({ ...updateItem }, this.stripUpdateFields);
238
237
  return (0, utils_1.stripObfuscatedFieldsFromPayload)(data, this.sensitiveFieldsToObfuscate);
239
238
  })();
240
- return updateFN(params, updatePayload);
239
+ return updateFN(updateItem[this.id], updatePayload);
241
240
  }, retryConfig)
242
241
  .then((data) => this.didUpdate(data))
243
242
  .catch((err) => {
@@ -272,12 +271,11 @@ class APIHandler {
272
271
  data: update || [],
273
272
  generator: (updateItem) => retryWithExponentialBackoff(() => {
274
273
  const updateFN = this.getClientFN(this.functions.update);
275
- const params = { [this.id]: updateItem[this.id] };
276
274
  const updatePayload = (() => {
277
275
  const data = (0, utils_1.stripFields)({ ...updateItem }, this.stripUpdateFields);
278
276
  return (0, utils_1.stripObfuscatedFieldsFromPayload)(data, this.sensitiveFieldsToObfuscate);
279
277
  })();
280
- return updateFN(params, updatePayload);
278
+ return updateFN(updateItem[this.id], updatePayload);
281
279
  }, retryConfig)
282
280
  .then((data) => {
283
281
  this.didUpdate(data);
@@ -66,10 +66,13 @@ exports.schema = {
66
66
  const getAllFlowConnections = async (auth0Client) => {
67
67
  const allFlowConnections = [];
68
68
  let vaultConnections = await auth0Client.flows.vault.connections.list();
69
- do {
70
- allFlowConnections.push(...vaultConnections.data);
69
+ // Process first page
70
+ allFlowConnections.push(...vaultConnections.data);
71
+ // Fetch remaining pages
72
+ while (vaultConnections.hasNextPage()) {
71
73
  vaultConnections = await vaultConnections.getNextPage();
72
- } while (vaultConnections.hasNextPage());
74
+ allFlowConnections.push(...vaultConnections.data);
75
+ }
73
76
  return allFlowConnections;
74
77
  };
75
78
  exports.getAllFlowConnections = getAllFlowConnections;
@@ -70,9 +70,6 @@ class FlowHandler extends default_1.default {
70
70
  id: 'id',
71
71
  stripCreateFields: ['created_at', 'updated_at', 'executed_at'],
72
72
  stripUpdateFields: ['created_at', 'updated_at', 'executed_at'],
73
- functions: {
74
- update: async ({ id }, bodyParams) => this.client.flows.update(id, bodyParams),
75
- },
76
73
  });
77
74
  }
78
75
  objString(item) {
@@ -69,9 +69,6 @@ class FormsHandler extends default_1.default {
69
69
  id: 'id',
70
70
  stripCreateFields: ['created_at', 'updated_at', 'submitted_at', 'embedded_at'],
71
71
  stripUpdateFields: ['created_at', 'updated_at', 'submitted_at', 'embedded_at'],
72
- functions: {
73
- update: async ({ id }, bodyParams) => this.client.forms.update(id, bodyParams),
74
- },
75
72
  });
76
73
  }
77
74
  objString(item) {
@@ -4,5 +4,6 @@ declare const _default: { [key in AssetTypes]: {
4
4
  default: typeof APIHandler;
5
5
  excludeSchema?: any;
6
6
  schema: any;
7
+ includeSchema?: any;
7
8
  }; };
8
9
  export default _default;
@@ -96,9 +96,6 @@ class LogStreamsHandler extends default_1.default {
96
96
  'sink.splunkToken',
97
97
  'sink.datadogApiKey',
98
98
  ],
99
- functions: {
100
- update: async (params, payload) => this.client.logStreams.update(params?.id, payload),
101
- },
102
99
  });
103
100
  }
104
101
  objString(item) {
@@ -87,6 +87,9 @@ export declare const schema: {
87
87
  type: string;
88
88
  enum: string[];
89
89
  };
90
+ use_for_organization_discovery: {
91
+ type: string;
92
+ };
90
93
  };
91
94
  required: string[];
92
95
  };
@@ -122,7 +125,7 @@ export default class OrganizationsHandler extends DefaultHandler {
122
125
  getAllOrganizationDiscoveryDomains(organizationId: string): Promise<Management.OrganizationDiscoveryDomain[] | null>;
123
126
  getOrganizationDiscoveryDomain(organizationId: string, discoveryDomainId: string): Promise<Management.GetOrganizationDiscoveryDomainResponseContent>;
124
127
  createOrganizationDiscoveryDomain(organizationId: string, discoveryDomain: Management.CreateOrganizationDiscoveryDomainRequestContent): Promise<Management.CreateOrganizationDiscoveryDomainResponseContent>;
125
- updateOrganizationDiscoveryDomain(organizationId: string, discoveryDomainId: string, discoveryDomain: string, status: Management.OrganizationDiscoveryDomainStatus): Promise<Management.UpdateOrganizationDiscoveryDomainResponseContent>;
128
+ updateOrganizationDiscoveryDomain(organizationId: string, discoveryDomainId: string, discoveryDomain: string, discoveryDomainUpdate: Management.UpdateOrganizationDiscoveryDomainRequestContent): Promise<Management.UpdateOrganizationDiscoveryDomainResponseContent>;
126
129
  deleteOrganizationDiscoveryDomain(organizationId: string, discoveryDomain: string, discoveryDomainId: string): Promise<void>;
127
130
  }
128
131
  export {};
@@ -112,6 +112,9 @@ exports.schema = {
112
112
  properties: {
113
113
  domain: { type: 'string' },
114
114
  status: { type: 'string', enum: ['pending', 'verified'] },
115
+ use_for_organization_discovery: {
116
+ type: 'boolean',
117
+ },
115
118
  },
116
119
  required: ['domain', 'status'],
117
120
  },
@@ -174,6 +177,7 @@ class OrganizationsHandler extends default_1.default {
174
177
  generator: (discoveryDomain) => this.createOrganizationDiscoveryDomain(created.id, {
175
178
  domain: discoveryDomain?.domain,
176
179
  status: discoveryDomain?.status,
180
+ use_for_organization_discovery: discoveryDomain?.use_for_organization_discovery,
177
181
  }).catch((err) => {
178
182
  throw new Error(`Problem creating discovery domain ${discoveryDomain?.domain} for organization ${created.id}\n${err}`);
179
183
  }),
@@ -256,32 +260,47 @@ class OrganizationsHandler extends default_1.default {
256
260
  const orgDiscoveryDomainsToRemove = existingDiscoveryDomains?.filter((existingDomain) => !organizationDiscoveryDomains?.find((d) => d.domain === existingDomain.domain)) || [];
257
261
  const orgDiscoveryDomainsToAdd = organizationDiscoveryDomains?.filter((domain) => !existingDiscoveryDomains?.find((d) => d.domain === domain.domain)) || [];
258
262
  const orgDiscoveryDomainsToUpdate = existingDiscoveryDomains
259
- ?.filter((existingDomain) => {
263
+ ?.map((existingDomain) => {
260
264
  const updatedDomain = organizationDiscoveryDomains?.find((d) => d.domain === existingDomain.domain);
261
- return updatedDomain && updatedDomain.status !== existingDomain.status;
265
+ if (!updatedDomain)
266
+ return undefined;
267
+ return {
268
+ ...updatedDomain,
269
+ id: existingDomain.id, // setting remote id for update
270
+ };
262
271
  })
263
- .map((existingDomain) => ({
264
- id: existingDomain.id,
265
- domain: existingDomain.domain,
266
- status: organizationDiscoveryDomains.find((d) => d.domain === existingDomain.domain)
267
- .status,
268
- })) || [];
269
- // Handle updates first
270
- await Promise.all(orgDiscoveryDomainsToUpdate.map((domainUpdate) => this.updateOrganizationDiscoveryDomain(params.id, domainUpdate.id, domainUpdate.domain, domainUpdate.status).catch((err) => {
271
- throw new Error(`Problem updating discovery domain ${domainUpdate.domain} for organization ${params.id}\n${err.message}`);
272
- })));
273
- await Promise.all(orgDiscoveryDomainsToAdd.map((domain) => this.createOrganizationDiscoveryDomain(params.id, {
274
- domain: domain.domain,
275
- status: domain.status,
276
- }).catch((err) => {
277
- throw new Error(`Problem adding discovery domain ${domain.domain} for organization ${params.id}\n${err.message}`);
278
- })));
272
+ .filter(Boolean) || [];
273
+ for (const { id, domain, ...updateParams } of orgDiscoveryDomainsToUpdate) {
274
+ try {
275
+ await this.updateOrganizationDiscoveryDomain(params.id, id, domain, updateParams);
276
+ }
277
+ catch (err) {
278
+ throw new Error(`Problem updating discovery domain ${domain} for organization ${params.id}\n${err.message}`);
279
+ }
280
+ }
281
+ for (const domain of orgDiscoveryDomainsToAdd) {
282
+ try {
283
+ await this.createOrganizationDiscoveryDomain(params.id, {
284
+ domain: domain.domain,
285
+ status: domain.status,
286
+ use_for_organization_discovery: domain.use_for_organization_discovery,
287
+ });
288
+ }
289
+ catch (err) {
290
+ throw new Error(`Problem adding discovery domain ${domain.domain} for organization ${params.id}\n${err.message}`);
291
+ }
292
+ }
279
293
  if (orgDiscoveryDomainsToRemove.length > 0) {
280
294
  if (this.config('AUTH0_ALLOW_DELETE') === 'true' ||
281
295
  this.config('AUTH0_ALLOW_DELETE') === true) {
282
- await Promise.all(orgDiscoveryDomainsToRemove.map((domain) => this.deleteOrganizationDiscoveryDomain(params.id, domain.domain, domain.id).catch((err) => {
283
- throw new Error(`Problem removing discovery domain ${domain.domain} for organization ${params.id}\n${err.message}`);
284
- })));
296
+ for (const domain of orgDiscoveryDomainsToRemove) {
297
+ try {
298
+ await this.deleteOrganizationDiscoveryDomain(params.id, domain.domain, domain.id);
299
+ }
300
+ catch (err) {
301
+ throw new Error(`Problem removing discovery domain ${domain.domain} for organization ${params.id}\n${err.message}`);
302
+ }
303
+ }
285
304
  }
286
305
  else {
287
306
  logger_1.default.warn(`Detected the following organization discovery domains should be deleted. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config
@@ -416,19 +435,25 @@ class OrganizationsHandler extends default_1.default {
416
435
  async getOrganizationEnabledConnections(organizationId) {
417
436
  const allOrganizationConnections = [];
418
437
  let organizationConnections = await this.client.organizations.enabledConnections.list(organizationId);
419
- do {
420
- allOrganizationConnections.push(...organizationConnections.data);
438
+ // Process first page
439
+ allOrganizationConnections.push(...organizationConnections.data);
440
+ // Fetch remaining pages
441
+ while (organizationConnections.hasNextPage()) {
421
442
  organizationConnections = await organizationConnections.getNextPage();
422
- } while (organizationConnections.hasNextPage());
443
+ allOrganizationConnections.push(...organizationConnections.data);
444
+ }
423
445
  return allOrganizationConnections;
424
446
  }
425
447
  async getOrganizationClientGrants(organizationId) {
426
448
  const allOrganizationClientGrants = [];
427
449
  let organizationClientGrants = await this.client.organizations.clientGrants.list(organizationId);
428
- do {
429
- allOrganizationClientGrants.push(...organizationClientGrants.data);
450
+ // Process first page
451
+ allOrganizationClientGrants.push(...organizationClientGrants.data);
452
+ // Fetch remaining pages
453
+ while (organizationClientGrants.hasNextPage()) {
430
454
  organizationClientGrants = await organizationClientGrants.getNextPage();
431
- } while (organizationClientGrants.hasNextPage());
455
+ allOrganizationClientGrants.push(...organizationClientGrants.data);
456
+ }
432
457
  return allOrganizationClientGrants;
433
458
  }
434
459
  async createOrganizationClientGrants(organizationId, grantId) {
@@ -447,10 +472,13 @@ class OrganizationsHandler extends default_1.default {
447
472
  const allDiscoveryDomains = [];
448
473
  try {
449
474
  let orgDiscoveryDomain = await this.client.organizations.discoveryDomains.list(organizationId);
450
- do {
451
- allDiscoveryDomains.push(...orgDiscoveryDomain.data);
475
+ // Process first page
476
+ allDiscoveryDomains.push(...orgDiscoveryDomain.data);
477
+ // Fetch remaining pages
478
+ while (orgDiscoveryDomain.hasNextPage()) {
452
479
  orgDiscoveryDomain = await orgDiscoveryDomain.getNextPage();
453
- } while (orgDiscoveryDomain.hasNextPage());
480
+ allDiscoveryDomains.push(...orgDiscoveryDomain.data);
481
+ }
454
482
  return allDiscoveryDomains;
455
483
  }
456
484
  catch (err) {
@@ -480,7 +508,7 @@ class OrganizationsHandler extends default_1.default {
480
508
  .promise();
481
509
  return orgDiscoveryDomain;
482
510
  }
483
- async updateOrganizationDiscoveryDomain(organizationId, discoveryDomainId, discoveryDomain, status) {
511
+ async updateOrganizationDiscoveryDomain(organizationId, discoveryDomainId, discoveryDomain, discoveryDomainUpdate) {
484
512
  logger_1.default.debug(`Updating discovery domain ${discoveryDomain} for organization ${organizationId}`);
485
513
  // stripUpdateFields does not support in sub modules
486
514
  const stripUpdateFields = ['verification_host', 'verification_txt'];
@@ -492,7 +520,8 @@ class OrganizationsHandler extends default_1.default {
492
520
  discoveryDomainId: discoveryDomainId,
493
521
  },
494
522
  generator: (args) => this.client.organizations.discoveryDomains.update(args.id, args.discoveryDomainId, {
495
- status: status,
523
+ status: discoveryDomainUpdate.status,
524
+ use_for_organization_discovery: discoveryDomainUpdate.use_for_organization_discovery,
496
525
  }),
497
526
  })
498
527
  .promise();