auth0-deploy-cli 8.43.0 → 8.45.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.
- package/CHANGELOG.md +53 -1
- package/README.md +1 -1
- package/lib/context/defaults.d.ts +7 -0
- package/lib/context/defaults.js +74 -30
- package/lib/context/directory/handlers/attackProtection.js +1 -1
- package/lib/context/directory/handlers/branding.js +9 -1
- package/lib/context/directory/handlers/clients.js +9 -3
- package/lib/context/directory/handlers/connections.js +10 -4
- package/lib/context/directory/handlers/emailTemplates.js +9 -0
- package/lib/context/directory/handlers/index.js +2 -0
- package/lib/context/directory/handlers/networkACLKeys.d.ts +6 -0
- package/lib/context/directory/handlers/networkACLKeys.js +54 -0
- package/lib/context/directory/handlers/prompts.js +11 -3
- package/lib/context/yaml/handlers/attackProtection.js +1 -1
- package/lib/context/yaml/handlers/branding.js +8 -1
- package/lib/context/yaml/handlers/clients.js +4 -1
- package/lib/context/yaml/handlers/connections.js +3 -1
- package/lib/context/yaml/handlers/flows.js +7 -0
- package/lib/context/yaml/handlers/forms.js +7 -0
- package/lib/context/yaml/handlers/index.js +2 -0
- package/lib/context/yaml/handlers/networkACLKeys.d.ts +6 -0
- package/lib/context/yaml/handlers/networkACLKeys.js +42 -0
- package/lib/context/yaml/handlers/prompts.js +7 -1
- package/lib/keywordPreservation.d.ts +1 -1
- package/lib/keywordPreservation.js +2 -1
- package/lib/readonly.js +5 -0
- package/lib/tools/auth0/handlers/attackProtection.js +3 -1
- package/lib/tools/auth0/handlers/clients.d.ts +40 -0
- package/lib/tools/auth0/handlers/clients.js +58 -1
- package/lib/tools/auth0/handlers/connectionProfiles.d.ts +27 -0
- package/lib/tools/auth0/handlers/connectionProfiles.js +30 -0
- package/lib/tools/auth0/handlers/connections.js +10 -3
- package/lib/tools/auth0/handlers/databases.d.ts +28 -0
- package/lib/tools/auth0/handlers/databases.js +47 -22
- package/lib/tools/auth0/handlers/default.d.ts +23 -0
- package/lib/tools/auth0/handlers/default.js +21 -10
- package/lib/tools/auth0/handlers/index.js +2 -0
- package/lib/tools/auth0/handlers/networkACLKeys.d.ts +45 -0
- package/lib/tools/auth0/handlers/networkACLKeys.js +177 -0
- package/lib/tools/auth0/handlers/networkACLs.d.ts +114 -2
- package/lib/tools/auth0/handlers/networkACLs.js +91 -16
- package/lib/tools/auth0/handlers/organizations.d.ts +1 -1
- package/lib/tools/auth0/handlers/organizations.js +49 -20
- package/lib/tools/auth0/handlers/phoneProvider.js +10 -2
- package/lib/tools/calculateDryRunChanges.js +12 -8
- package/lib/tools/constants.d.ts +1 -0
- package/lib/tools/constants.js +1 -0
- package/lib/types.d.ts +3 -1
- package/lib/utils.js +5 -2
- package/package.json +2 -2
package/lib/readonly.js
CHANGED
|
@@ -28,6 +28,11 @@ const readOnlyFields = {
|
|
|
28
28
|
'config_route',
|
|
29
29
|
'owners',
|
|
30
30
|
],
|
|
31
|
+
attackProtection: [
|
|
32
|
+
// Returned by GET but rejected by PATCH with "Additional properties not allowed"
|
|
33
|
+
'bruteForceProtection.form_submission_mode',
|
|
34
|
+
'bruteForceProtection.form_submission_behavior',
|
|
35
|
+
],
|
|
31
36
|
};
|
|
32
37
|
function getExcludedFields(config) {
|
|
33
38
|
const strippedFields = { ...readOnlyFields };
|
|
@@ -314,7 +314,9 @@ class AttackProtectionHandler extends default_1.default {
|
|
|
314
314
|
updates.push(this.client.attackProtection.captcha.update(attackProtection.captcha));
|
|
315
315
|
}
|
|
316
316
|
if (attackProtection.bruteForceProtection) {
|
|
317
|
-
|
|
317
|
+
// Strip fields returned by GET but rejected by PATCH
|
|
318
|
+
const { form_submission_mode, form_submission_behavior, ...bruteForcePayload } = attackProtection.bruteForceProtection;
|
|
319
|
+
updates.push(this.client.attackProtection.bruteForceProtection.update(bruteForcePayload));
|
|
318
320
|
}
|
|
319
321
|
if (attackProtection.suspiciousIpThrottling) {
|
|
320
322
|
updates.push(this.client.attackProtection.suspiciousIpThrottling.update(attackProtection.suspiciousIpThrottling));
|
|
@@ -209,6 +209,25 @@ export declare const schema: {
|
|
|
209
209
|
type: string;
|
|
210
210
|
description: string;
|
|
211
211
|
};
|
|
212
|
+
b2b_integration_configuration: {
|
|
213
|
+
type: string[];
|
|
214
|
+
description: string;
|
|
215
|
+
properties: {
|
|
216
|
+
integration_type: {
|
|
217
|
+
type: string;
|
|
218
|
+
enum: string[];
|
|
219
|
+
description: string;
|
|
220
|
+
};
|
|
221
|
+
sso_profiles: {
|
|
222
|
+
type: string;
|
|
223
|
+
description: string;
|
|
224
|
+
items: {
|
|
225
|
+
type: string;
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
additionalProperties: boolean;
|
|
230
|
+
};
|
|
212
231
|
resource_server_identifier: {
|
|
213
232
|
type: string;
|
|
214
233
|
description: string;
|
|
@@ -254,6 +273,27 @@ export declare const schema: {
|
|
|
254
273
|
enum: ("allow" | "allow_if_empty")[];
|
|
255
274
|
description: string;
|
|
256
275
|
};
|
|
276
|
+
third_party_client_access: {
|
|
277
|
+
type: string;
|
|
278
|
+
description: string;
|
|
279
|
+
properties: {
|
|
280
|
+
default_value: {
|
|
281
|
+
type: string;
|
|
282
|
+
enum: "block"[];
|
|
283
|
+
description: string;
|
|
284
|
+
};
|
|
285
|
+
allowed_values: {
|
|
286
|
+
type: string;
|
|
287
|
+
items: {
|
|
288
|
+
type: string;
|
|
289
|
+
enum: ("allow" | "block")[];
|
|
290
|
+
};
|
|
291
|
+
uniqueItems: boolean;
|
|
292
|
+
description: string;
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
required: string[];
|
|
296
|
+
};
|
|
257
297
|
invitation_landing_client_id: {
|
|
258
298
|
type: string;
|
|
259
299
|
description: string;
|
|
@@ -59,6 +59,27 @@ const myOrganizationConfigurationSchema = {
|
|
|
59
59
|
enum: Object.values(auth0_1.Management.ClientMyOrganizationDeletionBehaviorEnum),
|
|
60
60
|
description: 'The deletion behavior for My Organization connections created by this client',
|
|
61
61
|
},
|
|
62
|
+
third_party_client_access: {
|
|
63
|
+
type: 'object',
|
|
64
|
+
description: 'Controls whether third-party clients can access the organization via the My Organization API.',
|
|
65
|
+
properties: {
|
|
66
|
+
default_value: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
enum: Object.values(auth0_1.Management.ClientMyOrganizationConfigurationThirdPartyClientAccessDefaultValueEnum),
|
|
69
|
+
description: 'The default third-party client access value.',
|
|
70
|
+
},
|
|
71
|
+
allowed_values: {
|
|
72
|
+
type: 'array',
|
|
73
|
+
items: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
enum: Object.values(auth0_1.Management.ClientMyOrganizationConfigurationThirdPartyClientAccessAllowedValuesEnum),
|
|
76
|
+
},
|
|
77
|
+
uniqueItems: true,
|
|
78
|
+
description: 'The allowed third-party client access values.',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
required: ['default_value', 'allowed_values'],
|
|
82
|
+
},
|
|
62
83
|
invitation_landing_client_id: {
|
|
63
84
|
type: 'string',
|
|
64
85
|
description: 'The client ID of the invitation landing client for the My Organization configuration',
|
|
@@ -271,6 +292,23 @@ exports.schema = {
|
|
|
271
292
|
type: 'string',
|
|
272
293
|
description: 'The type of application this client represents',
|
|
273
294
|
},
|
|
295
|
+
b2b_integration_configuration: {
|
|
296
|
+
type: ['object', 'null'],
|
|
297
|
+
description: 'B2B integration configuration. Early Access. Required feature flag: enterprise_connect_entitled.',
|
|
298
|
+
properties: {
|
|
299
|
+
integration_type: {
|
|
300
|
+
type: 'string',
|
|
301
|
+
enum: ['custom_auth_server', 'third_party', 'application'],
|
|
302
|
+
description: 'The type of integration used to connect to this B2B integration client.',
|
|
303
|
+
},
|
|
304
|
+
sso_profiles: {
|
|
305
|
+
type: 'array',
|
|
306
|
+
description: 'List of SSO profile IDs linked to this B2B integration client. Maximum 1 entry.',
|
|
307
|
+
items: { type: 'string' },
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
additionalProperties: false,
|
|
311
|
+
},
|
|
274
312
|
resource_server_identifier: {
|
|
275
313
|
type: 'string',
|
|
276
314
|
description: 'The identifier of a resource server in your tenant. This property links a client to a resource server indicating that the client IS that resource server. Can only be set when app_type=resource_server.',
|
|
@@ -563,6 +601,9 @@ class ClientHandler extends default_1.default {
|
|
|
563
601
|
'jwks_uri',
|
|
564
602
|
// third_party_security_mode is immutable after creation; PATCH returns 400
|
|
565
603
|
'third_party_security_mode',
|
|
604
|
+
// API-generated timestamps; PATCH returns 400 if present
|
|
605
|
+
'created_at',
|
|
606
|
+
'updated_at',
|
|
566
607
|
],
|
|
567
608
|
functions: {
|
|
568
609
|
create: (client) => this.createClient(client),
|
|
@@ -752,7 +793,23 @@ class ClientHandler extends default_1.default {
|
|
|
752
793
|
async updateClient(clientId, client) {
|
|
753
794
|
// For non-CIMD clients
|
|
754
795
|
if (!this.isCimdClient(client)) {
|
|
755
|
-
|
|
796
|
+
const payload = { ...client };
|
|
797
|
+
// b2b_integration_configuration: PATCH only allowed if client already has the object.
|
|
798
|
+
// Sending it to a client that lacks it returns 400 invalid_body.
|
|
799
|
+
// null clears the object — but only for clients that already have it; stripping
|
|
800
|
+
// null for a client without the field is a safe no-op.
|
|
801
|
+
if ('b2b_integration_configuration' in payload) {
|
|
802
|
+
const existing = (this.existing || []).find((c) => c.client_id === (client.client_id || clientId));
|
|
803
|
+
if (!existing?.b2b_integration_configuration) {
|
|
804
|
+
if (payload.b2b_integration_configuration !== null) {
|
|
805
|
+
logger_1.default.warn(`b2b_integration_configuration cannot be added to an existing client via PATCH ` +
|
|
806
|
+
`(client: ${client.name || clientId}). Skipping field. ` +
|
|
807
|
+
`Re-create the client to set this field.`);
|
|
808
|
+
}
|
|
809
|
+
delete payload.b2b_integration_configuration;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return this.client.clients.update(clientId, payload);
|
|
756
813
|
}
|
|
757
814
|
const updatePayload = this.getCIMDEditableFields(client);
|
|
758
815
|
const registrationClientId = client.client_id || clientId;
|
|
@@ -36,6 +36,33 @@ export declare const schema: {
|
|
|
36
36
|
connection_config: {
|
|
37
37
|
type: string[];
|
|
38
38
|
};
|
|
39
|
+
cross_app_access_resource_app: {
|
|
40
|
+
type: string;
|
|
41
|
+
description: string;
|
|
42
|
+
properties: {
|
|
43
|
+
status: {
|
|
44
|
+
type: string;
|
|
45
|
+
properties: {
|
|
46
|
+
default_value: {
|
|
47
|
+
type: string;
|
|
48
|
+
enum: ("enabled" | "disabled")[];
|
|
49
|
+
description: string;
|
|
50
|
+
};
|
|
51
|
+
allowed_values: {
|
|
52
|
+
type: string;
|
|
53
|
+
items: {
|
|
54
|
+
type: string;
|
|
55
|
+
enum: ("enabled" | "disabled")[];
|
|
56
|
+
};
|
|
57
|
+
uniqueItems: boolean;
|
|
58
|
+
description: string;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
required: string[];
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
required: string[];
|
|
65
|
+
};
|
|
39
66
|
strategy_overrides: {
|
|
40
67
|
type: string[];
|
|
41
68
|
properties: {
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getConnectionProfile = exports.schema = void 0;
|
|
7
|
+
const auth0_1 = require("auth0");
|
|
7
8
|
const default_1 = __importDefault(require("./default"));
|
|
8
9
|
const client_1 = require("../client");
|
|
9
10
|
const logger_1 = __importDefault(require("../../../logger"));
|
|
@@ -42,6 +43,35 @@ exports.schema = {
|
|
|
42
43
|
connection_config: {
|
|
43
44
|
type: ['object', 'null'],
|
|
44
45
|
},
|
|
46
|
+
cross_app_access_resource_app: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
description: 'Controls whether organization admins may enable Cross App Access (XAA) on their Identity Providers.',
|
|
49
|
+
properties: {
|
|
50
|
+
status: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
default_value: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
enum: Object.values(auth0_1.Management.ConnectionProfileCrossAppAccessResourceAppStatusDefaultValueEnum),
|
|
56
|
+
description: 'The default Cross App Access resource app status.',
|
|
57
|
+
},
|
|
58
|
+
allowed_values: {
|
|
59
|
+
type: 'array',
|
|
60
|
+
items: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
enum: Object.values(auth0_1.Management.ConnectionProfileCrossAppAccessResourceAppStatusValueEnum),
|
|
63
|
+
},
|
|
64
|
+
uniqueItems: true,
|
|
65
|
+
description: 'The allowed Cross App Access resource app status values.',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
// allowed_values is optional per the SDK type (unlike the client's
|
|
69
|
+
// third_party_client_access, which requires both fields).
|
|
70
|
+
required: ['default_value'],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
required: ['status'],
|
|
74
|
+
},
|
|
45
75
|
strategy_overrides: {
|
|
46
76
|
type: ['object', 'null'],
|
|
47
77
|
properties: {
|
|
@@ -380,12 +380,15 @@ class ConnectionsHandler extends default_1.default {
|
|
|
380
380
|
}
|
|
381
381
|
getFormattedOptions(connection, clients) {
|
|
382
382
|
try {
|
|
383
|
+
const { idpinitiated } = connection.options;
|
|
383
384
|
return {
|
|
384
385
|
options: {
|
|
385
386
|
...connection.options,
|
|
386
387
|
idpinitiated: {
|
|
387
|
-
...
|
|
388
|
-
|
|
388
|
+
...idpinitiated,
|
|
389
|
+
...(idpinitiated.client_id && {
|
|
390
|
+
client_id: (0, utils_1.convertClientNameToId)(idpinitiated.client_id, clients),
|
|
391
|
+
}),
|
|
389
392
|
},
|
|
390
393
|
},
|
|
391
394
|
};
|
|
@@ -744,7 +747,11 @@ class ConnectionsHandler extends default_1.default {
|
|
|
744
747
|
...(enabledClients !== undefined && { enabled_clients: enabledClients }),
|
|
745
748
|
};
|
|
746
749
|
});
|
|
747
|
-
|
|
750
|
+
let proposedChanges = await super.dryRunChanges({ ...assets, connections: formatted });
|
|
751
|
+
const includedConnections = (assets.include && assets.include.connections) || [];
|
|
752
|
+
const excludedConnections = (assets.exclude && assets.exclude.connections) || [];
|
|
753
|
+
proposedChanges = (0, utils_1.filterExcluded)(proposedChanges, excludedConnections);
|
|
754
|
+
proposedChanges = (0, utils_1.filterIncluded)(proposedChanges, includedConnections);
|
|
748
755
|
return (0, exports.addExcludedConnectionPropertiesToChanges)({
|
|
749
756
|
proposedChanges,
|
|
750
757
|
existingConnections,
|
|
@@ -195,6 +195,33 @@ export declare const schema: {
|
|
|
195
195
|
};
|
|
196
196
|
};
|
|
197
197
|
};
|
|
198
|
+
otp_settings: {
|
|
199
|
+
type: string;
|
|
200
|
+
properties: {
|
|
201
|
+
email: {
|
|
202
|
+
type: string;
|
|
203
|
+
properties: {
|
|
204
|
+
otp_length: {
|
|
205
|
+
type: string;
|
|
206
|
+
};
|
|
207
|
+
otp_expiry: {
|
|
208
|
+
type: string;
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
phone: {
|
|
213
|
+
type: string;
|
|
214
|
+
properties: {
|
|
215
|
+
otp_length: {
|
|
216
|
+
type: string;
|
|
217
|
+
};
|
|
218
|
+
otp_expiry: {
|
|
219
|
+
type: string;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
};
|
|
198
225
|
password_options: {
|
|
199
226
|
type: string;
|
|
200
227
|
properties: {
|
|
@@ -295,6 +322,7 @@ export default class DatabaseHandler extends DefaultAPIHandler {
|
|
|
295
322
|
private validatePasswordlessSettings;
|
|
296
323
|
private validateEmailUniqueConstraints;
|
|
297
324
|
getClientFN(fn: 'create' | 'delete' | 'getAll' | 'update'): Function;
|
|
325
|
+
private enrichConnectionsWithEnabledClients;
|
|
298
326
|
getType(): Promise<Connection[]>;
|
|
299
327
|
calcChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
300
328
|
dryRunChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
@@ -181,6 +181,25 @@ exports.schema = {
|
|
|
181
181
|
action_id: { type: 'string' },
|
|
182
182
|
},
|
|
183
183
|
},
|
|
184
|
+
otp_settings: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: {
|
|
187
|
+
email: {
|
|
188
|
+
type: 'object',
|
|
189
|
+
properties: {
|
|
190
|
+
otp_length: { type: 'integer' },
|
|
191
|
+
otp_expiry: { type: 'integer' },
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
phone: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
otp_length: { type: 'integer' },
|
|
198
|
+
otp_expiry: { type: 'integer' },
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
184
203
|
password_options: {
|
|
185
204
|
type: 'object',
|
|
186
205
|
properties: {
|
|
@@ -419,6 +438,22 @@ class DatabaseHandler extends default_1.default {
|
|
|
419
438
|
}
|
|
420
439
|
return this.client.connections[fn].bind(this.client.connections);
|
|
421
440
|
}
|
|
441
|
+
// `enabled_clients` is no longer returned by connections.list; it must be fetched from the
|
|
442
|
+
// dedicated enabled-clients endpoint. Enriching the remote connections keeps the diff and the
|
|
443
|
+
// excluded-client preservation in `getEnabledClients` correct. Without it the dry-run diff
|
|
444
|
+
// reports a false "found in localObj but not in remoteObj" and a real import can silently
|
|
445
|
+
// disable an excluded-but-enabled client.
|
|
446
|
+
async enrichConnectionsWithEnabledClients(connections) {
|
|
447
|
+
return Promise.all(connections.map(async (con) => {
|
|
448
|
+
if (!con?.id)
|
|
449
|
+
return con;
|
|
450
|
+
const enabledClients = await (0, connections_1.getConnectionEnabledClients)(this.client, con.id);
|
|
451
|
+
if (enabledClients?.length) {
|
|
452
|
+
return { ...con, enabled_clients: enabledClients };
|
|
453
|
+
}
|
|
454
|
+
return con;
|
|
455
|
+
}));
|
|
456
|
+
}
|
|
422
457
|
async getType() {
|
|
423
458
|
if (this.existing)
|
|
424
459
|
return this.existing;
|
|
@@ -433,16 +468,7 @@ class DatabaseHandler extends default_1.default {
|
|
|
433
468
|
include_totals: true,
|
|
434
469
|
}),
|
|
435
470
|
]);
|
|
436
|
-
const dbConnectionsWithEnabledClients = await
|
|
437
|
-
if (!con?.id)
|
|
438
|
-
return con;
|
|
439
|
-
const enabledClients = await (0, connections_1.getConnectionEnabledClients)(this.client, con.id);
|
|
440
|
-
const connection = { ...con };
|
|
441
|
-
if (enabledClients && enabledClients?.length) {
|
|
442
|
-
connection.enabled_clients = enabledClients;
|
|
443
|
-
}
|
|
444
|
-
return connection;
|
|
445
|
-
}));
|
|
471
|
+
const dbConnectionsWithEnabledClients = await this.enrichConnectionsWithEnabledClients(connections);
|
|
446
472
|
// Convert action ID back to action name for export
|
|
447
473
|
const dbConnectionsWithActionNames = dbConnectionsWithEnabledClients.map((connection) => {
|
|
448
474
|
if (connection.options && 'custom_password_hash' in connection.options) {
|
|
@@ -489,28 +515,26 @@ class DatabaseHandler extends default_1.default {
|
|
|
489
515
|
update: [],
|
|
490
516
|
conflicts: [],
|
|
491
517
|
};
|
|
492
|
-
// Convert enabled_clients by name to the id
|
|
493
|
-
//
|
|
494
|
-
|
|
518
|
+
// Convert enabled_clients by name to the id. `getType()` fetches and enriches the existing
|
|
519
|
+
// connections with `enabled_clients` and caches the result in `this.existing`, so the
|
|
520
|
+
// `super.calcChanges()` call below reuses it instead of fetching again.
|
|
521
|
+
const [clients, actions, existingWithEnabledClients] = await Promise.all([
|
|
495
522
|
(0, client_1.paginate)(this.client.clients.list, {
|
|
496
523
|
paginate: true,
|
|
497
524
|
}),
|
|
498
|
-
(0, client_1.paginate)(this.client.connections.list, {
|
|
499
|
-
strategy: [auth0_1.Management.ConnectionStrategyEnum.Auth0],
|
|
500
|
-
checkpoint: true,
|
|
501
|
-
include_totals: true,
|
|
502
|
-
}),
|
|
503
525
|
(0, client_1.paginate)(this.client.actions.list, {
|
|
504
526
|
paginate: true,
|
|
505
527
|
include_totals: true,
|
|
506
528
|
}),
|
|
529
|
+
this.getType(),
|
|
507
530
|
]);
|
|
531
|
+
const existingConnections = existingWithEnabledClients || [];
|
|
508
532
|
const formatted = databases.map((db) => {
|
|
509
533
|
const { options, ...rest } = db;
|
|
510
534
|
const formattedOptions = this.getFormattedOptions(options, actions);
|
|
511
535
|
const formattedDb = { ...rest, options: formattedOptions };
|
|
512
536
|
if (db.enabled_clients) {
|
|
513
|
-
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db,
|
|
537
|
+
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db, existingConnections, clients);
|
|
514
538
|
}
|
|
515
539
|
return formattedDb;
|
|
516
540
|
});
|
|
@@ -540,21 +564,22 @@ class DatabaseHandler extends default_1.default {
|
|
|
540
564
|
include_totals: true,
|
|
541
565
|
}),
|
|
542
566
|
]);
|
|
567
|
+
const existingWithEnabledClients = await this.enrichConnectionsWithEnabledClients(existingDatabasesConnections);
|
|
543
568
|
const formatted = databases.map((db) => {
|
|
544
569
|
const { options, ...rest } = db;
|
|
545
570
|
const formattedOptions = this.getFormattedOptions(options, actions);
|
|
546
571
|
const formattedDb = { ...rest, options: formattedOptions };
|
|
547
572
|
if (db.enabled_clients) {
|
|
548
|
-
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db,
|
|
573
|
+
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db, existingWithEnabledClients, clients);
|
|
549
574
|
}
|
|
550
575
|
return formattedDb;
|
|
551
576
|
});
|
|
552
577
|
return (0, calculateDryRunChanges_1.calculateDryRunChanges)({
|
|
553
578
|
type: this.type,
|
|
554
579
|
assets: formatted,
|
|
555
|
-
existing:
|
|
580
|
+
existing: existingWithEnabledClients,
|
|
556
581
|
identifiers: this.identifiers,
|
|
557
|
-
ignoreDryRunFields: this.
|
|
582
|
+
ignoreDryRunFields: this.getEffectiveIgnoreDryRunFields(),
|
|
558
583
|
});
|
|
559
584
|
}
|
|
560
585
|
// Run after clients are updated so we can convert all the enabled_clients names to id's
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { Asset, Assets, Auth0APIClient, CalculatedChanges } from '../../../types';
|
|
2
2
|
import { ConfigFunction } from '../../../configFactory';
|
|
3
3
|
export declare function order(value: any): (t: any, n: any, descriptor: any) => any;
|
|
4
|
+
export interface RetryOptions {
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
initialDelay?: number;
|
|
7
|
+
maxDelay?: number;
|
|
8
|
+
onRetry?: (error: any, attempt: number, delay: number) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Executes a function with exponential backoff retry logic for rate limit errors (429).
|
|
12
|
+
*
|
|
13
|
+
* @param fn - The function to execute with retry logic
|
|
14
|
+
* @param options - Configuration options for retry behavior
|
|
15
|
+
* @returns Promise that resolves with the function result or rejects after max retries
|
|
16
|
+
*/
|
|
17
|
+
export declare function retryWithExponentialBackoff<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
4
18
|
type ApiMethodOverride = string | Function;
|
|
5
19
|
export default class APIHandler {
|
|
6
20
|
config: ConfigFunction;
|
|
@@ -50,6 +64,15 @@ export default class APIHandler {
|
|
|
50
64
|
*/
|
|
51
65
|
getEffectiveIgnoreDryRunFields(): string[];
|
|
52
66
|
getClientFN(fn: ApiMethodOverride): Function;
|
|
67
|
+
/**
|
|
68
|
+
* Builds the exponential-backoff retry configuration for this handler from the
|
|
69
|
+
* shared `AUTH0_MAX_RETRIES` / `AUTH0_RETRY_INITIAL_DELAY_MS` /
|
|
70
|
+
* `AUTH0_RETRY_MAX_DELAY_MS` config keys. Exposed so that handlers which issue
|
|
71
|
+
* writes outside the default `processChanges` flow (e.g. organizations, which
|
|
72
|
+
* writes nested connections/grants directly) can wrap those calls in the same
|
|
73
|
+
* 429 backoff behaviour as the base handler.
|
|
74
|
+
*/
|
|
75
|
+
getRetryConfig(): RetryOptions;
|
|
53
76
|
didDelete(item: Asset): void;
|
|
54
77
|
didCreate(item: Asset): void;
|
|
55
78
|
didUpdate(item: Asset): void;
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.order = order;
|
|
7
|
+
exports.retryWithExponentialBackoff = retryWithExponentialBackoff;
|
|
7
8
|
const auth0_1 = require("auth0");
|
|
8
9
|
const validationError_1 = __importDefault(require("../../validationError"));
|
|
9
10
|
const utils_1 = require("../../utils");
|
|
@@ -114,6 +115,25 @@ class APIHandler {
|
|
|
114
115
|
}
|
|
115
116
|
return fn;
|
|
116
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Builds the exponential-backoff retry configuration for this handler from the
|
|
120
|
+
* shared `AUTH0_MAX_RETRIES` / `AUTH0_RETRY_INITIAL_DELAY_MS` /
|
|
121
|
+
* `AUTH0_RETRY_MAX_DELAY_MS` config keys. Exposed so that handlers which issue
|
|
122
|
+
* writes outside the default `processChanges` flow (e.g. organizations, which
|
|
123
|
+
* writes nested connections/grants directly) can wrap those calls in the same
|
|
124
|
+
* 429 backoff behaviour as the base handler.
|
|
125
|
+
*/
|
|
126
|
+
getRetryConfig() {
|
|
127
|
+
const retryConfig = {
|
|
128
|
+
maxRetries: this.config('AUTH0_MAX_RETRIES') || DEFAULT_MAX_RETRIES,
|
|
129
|
+
initialDelay: this.config('AUTH0_RETRY_INITIAL_DELAY_MS') || DEFAULT_INITIAL_DELAY_MS,
|
|
130
|
+
maxDelay: this.config('AUTH0_RETRY_MAX_DELAY_MS') || DEFAULT_MAX_DELAY_MS,
|
|
131
|
+
onRetry: (error, attempt, delay) => {
|
|
132
|
+
logger_1.default.warn(`Rate limit hit for [${this.type}]. Retrying attempt ${attempt}/${retryConfig.maxRetries} after ${Math.round(delay / 1000)}s...`);
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
return retryConfig;
|
|
136
|
+
}
|
|
117
137
|
didDelete(item) {
|
|
118
138
|
logger_1.default.info(`Deleted [${this.type}]: ${this.objString(item)}`);
|
|
119
139
|
}
|
|
@@ -210,7 +230,6 @@ class APIHandler {
|
|
|
210
230
|
return (0, calculateDryRunChanges_1.calculateDryRunChanges)({
|
|
211
231
|
type: this.type,
|
|
212
232
|
assets: typeAssets,
|
|
213
|
-
// @ts-ignore TODO: investigate what happens when `existing` is null
|
|
214
233
|
existing,
|
|
215
234
|
identifiers: this.identifiers,
|
|
216
235
|
ignoreDryRunFields: this.getEffectiveIgnoreDryRunFields(),
|
|
@@ -243,7 +262,6 @@ class APIHandler {
|
|
|
243
262
|
return (0, calculateDryRunChanges_1.calculateDryRunChanges)({
|
|
244
263
|
type: this.type,
|
|
245
264
|
assets: typeAssets,
|
|
246
|
-
// @ts-ignore TODO: investigate what happens when `existing` is null
|
|
247
265
|
existing,
|
|
248
266
|
identifiers: this.identifiers,
|
|
249
267
|
ignoreDryRunFields: this.getEffectiveIgnoreDryRunFields(),
|
|
@@ -282,14 +300,7 @@ class APIHandler {
|
|
|
282
300
|
const conflicts = changes.conflicts || [];
|
|
283
301
|
logger_1.default.debug(`Start processChanges for ${this.type} [delete:${del.length}] [update:${update.length}], [create:${create.length}], [conflicts:${conflicts.length}]`);
|
|
284
302
|
// Set retry configuration from config
|
|
285
|
-
const retryConfig =
|
|
286
|
-
maxRetries: this.config('AUTH0_MAX_RETRIES') || DEFAULT_MAX_RETRIES,
|
|
287
|
-
initialDelay: this.config('AUTH0_RETRY_INITIAL_DELAY_MS') || DEFAULT_INITIAL_DELAY_MS,
|
|
288
|
-
maxDelay: this.config('AUTH0_RETRY_MAX_DELAY_MS') || DEFAULT_MAX_DELAY_MS,
|
|
289
|
-
onRetry: (error, attempt, delay) => {
|
|
290
|
-
logger_1.default.warn(`Rate limit hit for [${this.type}]. Retrying attempt ${attempt}/${retryConfig.maxRetries} after ${Math.round(delay / 1000)}s...`);
|
|
291
|
-
},
|
|
292
|
-
};
|
|
303
|
+
const retryConfig = this.getRetryConfig();
|
|
293
304
|
// Process Deleted
|
|
294
305
|
if (del.length > 0) {
|
|
295
306
|
const allowDelete = this.config('AUTH0_ALLOW_DELETE') === 'true' || this.config('AUTH0_ALLOW_DELETE') === true;
|
|
@@ -69,6 +69,7 @@ const forms = __importStar(require("./forms"));
|
|
|
69
69
|
const flows = __importStar(require("./flows"));
|
|
70
70
|
const flowVaultConnections = __importStar(require("./flowVaultConnections"));
|
|
71
71
|
const selfServiceProfiles = __importStar(require("./selfServiceProfiles"));
|
|
72
|
+
const networkACLKeys = __importStar(require("./networkACLKeys"));
|
|
72
73
|
const networkACLs = __importStar(require("./networkACLs"));
|
|
73
74
|
const userAttributeProfiles = __importStar(require("./userAttributeProfiles"));
|
|
74
75
|
const connectionProfiles = __importStar(require("./connectionProfiles"));
|
|
@@ -116,6 +117,7 @@ const auth0ApiHandlers = {
|
|
|
116
117
|
flows,
|
|
117
118
|
flowVaultConnections,
|
|
118
119
|
selfServiceProfiles,
|
|
120
|
+
networkACLKeys,
|
|
119
121
|
networkACLs,
|
|
120
122
|
userAttributeProfiles,
|
|
121
123
|
connectionProfiles,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Management } from 'auth0';
|
|
2
|
+
import DefaultAPIHandler from './default';
|
|
3
|
+
import { Asset, Assets, CalculatedChanges } from '../../../types';
|
|
4
|
+
export type NetworkAclKey = Management.NetworkAclKey & {
|
|
5
|
+
value?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const schema: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
items: {
|
|
11
|
+
type: string;
|
|
12
|
+
required: string[];
|
|
13
|
+
properties: {
|
|
14
|
+
id: {
|
|
15
|
+
type: string;
|
|
16
|
+
};
|
|
17
|
+
name: {
|
|
18
|
+
type: string;
|
|
19
|
+
maxLength: number;
|
|
20
|
+
};
|
|
21
|
+
alg: {
|
|
22
|
+
type: string;
|
|
23
|
+
enum: string[];
|
|
24
|
+
};
|
|
25
|
+
value: {
|
|
26
|
+
type: string;
|
|
27
|
+
};
|
|
28
|
+
fingerprint: {
|
|
29
|
+
type: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
additionalProperties: boolean;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export default class NetworkACLKeysHandler extends DefaultAPIHandler {
|
|
36
|
+
existing: NetworkAclKey[] | null;
|
|
37
|
+
constructor(config: DefaultAPIHandler);
|
|
38
|
+
objString(key: NetworkAclKey): string;
|
|
39
|
+
getType(): Promise<Asset | null>;
|
|
40
|
+
processChanges(assets: Assets): Promise<void>;
|
|
41
|
+
createNetworkACLKey(key: NetworkAclKey): Promise<void>;
|
|
42
|
+
createNetworkACLKeys(creates: CalculatedChanges['create']): Promise<void>;
|
|
43
|
+
deleteNetworkACLKey(key: NetworkAclKey): Promise<void>;
|
|
44
|
+
deleteNetworkACLKeys(data: Asset[]): Promise<void>;
|
|
45
|
+
}
|