auth0-deploy-cli 9.0.0-beta.2 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/AGENTS.md +2 -357
  2. package/CHANGELOG.md +185 -10
  3. package/CLAUDE.md +138 -2
  4. package/README.md +1 -1
  5. package/lib/context/defaults.d.ts +7 -0
  6. package/lib/context/defaults.js +74 -30
  7. package/lib/context/directory/handlers/actionModules.js +1 -4
  8. package/lib/context/directory/handlers/actions.js +1 -4
  9. package/lib/context/directory/handlers/attackProtection.js +11 -1
  10. package/lib/context/directory/handlers/branding.js +4 -1
  11. package/lib/context/directory/handlers/clientAuthCredentials.d.ts +5 -0
  12. package/lib/context/directory/handlers/clientAuthCredentials.js +13 -0
  13. package/lib/context/directory/handlers/clientGrants.js +78 -24
  14. package/lib/context/directory/handlers/clients.js +20 -3
  15. package/lib/context/directory/handlers/connections.js +19 -5
  16. package/lib/context/directory/handlers/databases.js +1 -4
  17. package/lib/context/directory/handlers/emailTemplates.js +5 -0
  18. package/lib/context/directory/handlers/guardianEmailFactorSettings.d.ts +5 -0
  19. package/lib/context/directory/handlers/guardianEmailFactorSettings.js +38 -0
  20. package/lib/context/directory/handlers/guardianPhoneFactorSettings.d.ts +5 -0
  21. package/lib/context/directory/handlers/guardianPhoneFactorSettings.js +38 -0
  22. package/lib/context/directory/handlers/guardianSettings.d.ts +5 -0
  23. package/lib/context/directory/handlers/guardianSettings.js +38 -0
  24. package/lib/context/directory/handlers/hooks.js +1 -4
  25. package/lib/context/directory/handlers/index.js +12 -0
  26. package/lib/context/directory/handlers/networkACLKeys.d.ts +6 -0
  27. package/lib/context/directory/handlers/networkACLKeys.js +54 -0
  28. package/lib/context/directory/handlers/prompts.js +7 -3
  29. package/lib/context/directory/handlers/rateLimitPolicies.d.ts +6 -0
  30. package/lib/context/directory/handlers/rateLimitPolicies.js +53 -0
  31. package/lib/context/directory/handlers/rules.js +1 -4
  32. package/lib/context/directory/index.js +1 -4
  33. package/lib/context/index.js +32 -31
  34. package/lib/context/yaml/handlers/attackProtection.js +5 -2
  35. package/lib/context/yaml/handlers/branding.js +4 -1
  36. package/lib/context/yaml/handlers/clientAuthCredentials.d.ts +5 -0
  37. package/lib/context/yaml/handlers/clientAuthCredentials.js +13 -0
  38. package/lib/context/yaml/handlers/clients.js +19 -1
  39. package/lib/context/yaml/handlers/connections.js +8 -1
  40. package/lib/context/yaml/handlers/flows.js +3 -0
  41. package/lib/context/yaml/handlers/forms.js +3 -0
  42. package/lib/context/yaml/handlers/guardianEmailFactorSettings.d.ts +5 -0
  43. package/lib/context/yaml/handlers/guardianEmailFactorSettings.js +15 -0
  44. package/lib/context/yaml/handlers/guardianPhoneFactorSettings.d.ts +5 -0
  45. package/lib/context/yaml/handlers/guardianPhoneFactorSettings.js +15 -0
  46. package/lib/context/yaml/handlers/guardianSettings.d.ts +5 -0
  47. package/lib/context/yaml/handlers/guardianSettings.js +15 -0
  48. package/lib/context/yaml/handlers/index.js +12 -0
  49. package/lib/context/yaml/handlers/networkACLKeys.d.ts +6 -0
  50. package/lib/context/yaml/handlers/networkACLKeys.js +42 -0
  51. package/lib/context/yaml/handlers/prompts.js +3 -1
  52. package/lib/context/yaml/handlers/rateLimitPolicies.d.ts +6 -0
  53. package/lib/context/yaml/handlers/rateLimitPolicies.js +27 -0
  54. package/lib/context/yaml/index.js +85 -7
  55. package/lib/keywordPreservation.d.ts +1 -1
  56. package/lib/keywordPreservation.js +2 -1
  57. package/lib/readonly.js +5 -0
  58. package/lib/tools/auth0/handlers/attackProtection.d.ts +12 -0
  59. package/lib/tools/auth0/handlers/attackProtection.js +66 -6
  60. package/lib/tools/auth0/handlers/clientAuthCredentials.d.ts +27 -0
  61. package/lib/tools/auth0/handlers/clientAuthCredentials.js +234 -0
  62. package/lib/tools/auth0/handlers/clientAuthCredentialsPre.d.ts +38 -0
  63. package/lib/tools/auth0/handlers/clientAuthCredentialsPre.js +123 -0
  64. package/lib/tools/auth0/handlers/clientGrants.d.ts +1 -1
  65. package/lib/tools/auth0/handlers/clients.d.ts +106 -0
  66. package/lib/tools/auth0/handlers/clients.js +207 -3
  67. package/lib/tools/auth0/handlers/connectionProfiles.d.ts +27 -0
  68. package/lib/tools/auth0/handlers/connectionProfiles.js +30 -0
  69. package/lib/tools/auth0/handlers/connections.d.ts +34 -6
  70. package/lib/tools/auth0/handlers/connections.js +75 -11
  71. package/lib/tools/auth0/handlers/databases.d.ts +28 -0
  72. package/lib/tools/auth0/handlers/databases.js +58 -24
  73. package/lib/tools/auth0/handlers/default.d.ts +23 -0
  74. package/lib/tools/auth0/handlers/default.js +47 -29
  75. package/lib/tools/auth0/handlers/eventStreams.js +10 -2
  76. package/lib/tools/auth0/handlers/guardianEmailFactorSettings.d.ts +22 -0
  77. package/lib/tools/auth0/handlers/guardianEmailFactorSettings.js +77 -0
  78. package/lib/tools/auth0/handlers/guardianFactorTemplates.js +13 -4
  79. package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +11 -9
  80. package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +11 -9
  81. package/lib/tools/auth0/handlers/guardianPhoneFactorSettings.d.ts +22 -0
  82. package/lib/tools/auth0/handlers/guardianPhoneFactorSettings.js +77 -0
  83. package/lib/tools/auth0/handlers/guardianPolicies.js +11 -1
  84. package/lib/tools/auth0/handlers/guardianSettings.d.ts +30 -0
  85. package/lib/tools/auth0/handlers/guardianSettings.js +85 -0
  86. package/lib/tools/auth0/handlers/hooks.js +1 -1
  87. package/lib/tools/auth0/handlers/index.js +16 -0
  88. package/lib/tools/auth0/handlers/networkACLKeys.d.ts +45 -0
  89. package/lib/tools/auth0/handlers/networkACLKeys.js +177 -0
  90. package/lib/tools/auth0/handlers/networkACLs.d.ts +132 -2
  91. package/lib/tools/auth0/handlers/networkACLs.js +100 -16
  92. package/lib/tools/auth0/handlers/organizations.d.ts +33 -1
  93. package/lib/tools/auth0/handlers/organizations.js +177 -19
  94. package/lib/tools/auth0/handlers/phoneProvider.js +10 -2
  95. package/lib/tools/auth0/handlers/phoneTemplates.d.ts +4 -1
  96. package/lib/tools/auth0/handlers/phoneTemplates.js +67 -10
  97. package/lib/tools/auth0/handlers/prompts.d.ts +17 -0
  98. package/lib/tools/auth0/handlers/prompts.js +47 -14
  99. package/lib/tools/auth0/handlers/rateLimitPolicies.d.ts +81 -0
  100. package/lib/tools/auth0/handlers/rateLimitPolicies.js +203 -0
  101. package/lib/tools/auth0/handlers/resourceServers.d.ts +48 -0
  102. package/lib/tools/auth0/handlers/resourceServers.js +56 -2
  103. package/lib/tools/auth0/handlers/riskAssessment.d.ts +1 -1
  104. package/lib/tools/auth0/handlers/riskAssessment.js +19 -1
  105. package/lib/tools/auth0/handlers/roles.d.ts +4 -0
  106. package/lib/tools/auth0/handlers/roles.js +27 -9
  107. package/lib/tools/auth0/handlers/rules.js +19 -7
  108. package/lib/tools/auth0/handlers/scimHandler.js +8 -3
  109. package/lib/tools/auth0/handlers/tenant.d.ts +45 -0
  110. package/lib/tools/auth0/handlers/tenant.js +48 -0
  111. package/lib/tools/auth0/handlers/themes.d.ts +37 -1
  112. package/lib/tools/auth0/handlers/themes.js +64 -0
  113. package/lib/tools/auth0/handlers/tokenExchangeProfiles.js +3 -1
  114. package/lib/tools/auth0/index.js +12 -6
  115. package/lib/tools/calculateDryRunChanges.js +12 -8
  116. package/lib/tools/constants.d.ts +3 -0
  117. package/lib/tools/constants.js +8 -0
  118. package/lib/tools/utils.d.ts +3 -0
  119. package/lib/tools/utils.js +41 -2
  120. package/lib/types.d.ts +10 -1
  121. package/lib/utils.d.ts +6 -0
  122. package/lib/utils.js +17 -2
  123. package/package.json +2 -2
  124. package/references/code-style.md +133 -0
  125. package/references/commands.md +98 -0
  126. package/references/docs-update.md +34 -0
  127. package/references/git-workflow.md +135 -0
  128. package/references/pitfalls.md +62 -0
  129. package/references/testing.md +118 -0
@@ -44,6 +44,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.schema = void 0;
46
46
  const default_1 = __importStar(require("./default"));
47
+ const utils_1 = require("../../utils");
47
48
  const logger_1 = __importDefault(require("../../../logger"));
48
49
  exports.schema = {
49
50
  type: 'array',
@@ -121,25 +122,77 @@ class PhoneTemplatesHandler extends default_1.default {
121
122
  if (del.length > 0) {
122
123
  await this.deletePhoneTemplates(del);
123
124
  }
124
- if (create.length > 0) {
125
- await this.createPhoneTemplates(create);
125
+ // On newly created tenants the phone templates returned by the API have no
126
+ // ID until they are explicitly created. calcChanges matches assets by `type`
127
+ // and routes them all to `update`, but PATCH requires an ID. Split out the
128
+ // templates whose existing counterpart has no ID yet and create them instead.
129
+ const missingId = [];
130
+ const hasId = [];
131
+ update.forEach((template) => {
132
+ const existing = this.existing?.find((t) => t.type === template.type);
133
+ if (existing?.id) {
134
+ hasId.push(template);
135
+ }
136
+ else {
137
+ missingId.push(template);
138
+ }
139
+ });
140
+ const toCreate = [...create, ...missingId];
141
+ if (toCreate.length > 0) {
142
+ await this.createPhoneTemplates(toCreate);
126
143
  }
127
- if (update.length > 0) {
128
- await this.updatePhoneTemplates(update);
144
+ if (hasId.length > 0) {
145
+ await this.updatePhoneTemplates(hasId);
129
146
  }
130
147
  }
131
148
  async createPhoneTemplate(template) {
132
- const created = await this.client.branding.phone.templates.create(template);
133
- return created;
149
+ // The create endpoint only accepts type/disabled/content; strip read-only
150
+ // fields (channel, customizable, tenant) that the API would reject.
151
+ const createPayload = (0, utils_1.stripFields)(template, this.stripCreateFields);
152
+ // The API rejects an empty `content.from`, which is what fresh tenants
153
+ // export. Drop it when blank (cloning `content`, which stripFields only
154
+ // shallow-copied, so the caller's original asset isn't mutated).
155
+ if (createPayload.content && !createPayload.content.from) {
156
+ createPayload.content = { ...createPayload.content };
157
+ delete createPayload.content.from;
158
+ }
159
+ try {
160
+ const created = await this.client.branding.phone.templates.create(createPayload);
161
+ return { asset: created, action: 'create' };
162
+ }
163
+ catch (err) {
164
+ // A 409 means the template already exists on the tenant (it was created
165
+ // between our list call and this create, or the list endpoint didn't
166
+ // surface its ID). Re-fetch to pick up the ID and fall back to an update.
167
+ if (err.statusCode === 409) {
168
+ logger_1.default.debug(`Phone template type '${template.type}' already exists, falling back to update`);
169
+ // Reassigns the shared `this.existing`; safe under concurrency since
170
+ // every re-fetch returns the same consistent list. If it still lacks an
171
+ // ID, updatePhoneTemplate warns and skips.
172
+ const response = await this.client.branding.phone.templates.list();
173
+ this.existing = response.templates ?? [];
174
+ const updated = await this.updatePhoneTemplate(template);
175
+ return { asset: updated, action: 'update' };
176
+ }
177
+ throw err;
178
+ }
134
179
  }
135
180
  async createPhoneTemplates(creates) {
136
181
  await this.client.pool
137
182
  .addEachTask({
138
183
  data: creates || [],
139
184
  generator: (item) => this.createPhoneTemplate(item)
140
- .then((data) => {
141
- this.didCreate(data);
142
- this.created += 1;
185
+ .then(({ asset, action }) => {
186
+ // A 409 fallback actually performed an update; count it as such so
187
+ // the import summary doesn't report a phantom "create".
188
+ if (action === 'update') {
189
+ this.didUpdate(asset);
190
+ this.updated += 1;
191
+ }
192
+ else {
193
+ this.didCreate(asset);
194
+ this.created += 1;
195
+ }
143
196
  })
144
197
  .catch((err) => {
145
198
  throw new Error(`Problem creating ${this.type} ${this.objString(item)}\n${err}`);
@@ -160,7 +213,6 @@ class PhoneTemplatesHandler extends default_1.default {
160
213
  logger_1.default.debug(`Stripping ${this.type} create-only fields ${JSON.stringify(stripUpdateFields)}`);
161
214
  const updatePayload = {
162
215
  content: {
163
- from: template.content?.from,
164
216
  body: {
165
217
  text: template.content?.body?.text,
166
218
  voice: template.content?.body?.voice,
@@ -168,6 +220,11 @@ class PhoneTemplatesHandler extends default_1.default {
168
220
  },
169
221
  disabled: template.disabled,
170
222
  };
223
+ // `content.from` is optional but the API rejects an empty string, which is
224
+ // what fresh tenants export. Only include it when it has a value.
225
+ if (template.content?.from) {
226
+ updatePayload.content.from = template.content.from;
227
+ }
171
228
  const updated = await this.client.branding.phone.templates.update(existing.id, updatePayload);
172
229
  return updated;
173
230
  }
@@ -47,7 +47,18 @@ export declare const schema: {
47
47
  type: string;
48
48
  };
49
49
  customText: {
50
+ $id: string;
50
51
  type: string;
52
+ definitions: {
53
+ promptType: {
54
+ type: string;
55
+ properties: {};
56
+ };
57
+ language: {
58
+ type: string;
59
+ properties: {};
60
+ };
61
+ };
51
62
  properties: {};
52
63
  };
53
64
  partials: {
@@ -87,6 +98,12 @@ export default class PromptsHandler extends DefaultHandler {
87
98
  constructor(options: DefaultHandler);
88
99
  objString({ customText, screenRenderers }: Prompts): string;
89
100
  getType(): Promise<Prompts | null>;
101
+ /**
102
+ * Narrows the tenant's enabled languages to those listed in AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES.
103
+ * Custom text is fetched with one rate-limited request per language and prompt type, so
104
+ * limiting languages is the only way to shorten this step on tenants with many languages.
105
+ */
106
+ getCustomTextLanguages<T extends string>(enabledLanguages: T[]): T[];
90
107
  getCustomTextSettings(): Promise<AllPromptsByLanguage>;
91
108
  /**
92
109
  * Error handler wrapper.
@@ -199,25 +199,35 @@ exports.schema = {
199
199
  identifier_first: {
200
200
  type: 'boolean',
201
201
  },
202
+ // Every language/prompt shares the same shape, so the per-prompt and per-language schemas are
203
+ // defined once and referenced. Inlining them multiplies the schema by
204
+ // languages x promptTypes x screenTypes (~184k subschemas), which costs ~1 GB and ~2.5s of
205
+ // Ajv compile time on every `deploy`. The `$id` scopes the `#/definitions/...` refs to this
206
+ // subschema so they resolve wherever it is embedded.
202
207
  customText: {
208
+ $id: 'prompts-custom-text',
203
209
  type: 'object',
204
- properties: types_1.languages.reduce((acc, language) => ({
205
- ...acc,
206
- [language]: {
210
+ definitions: {
211
+ promptType: {
207
212
  type: 'object',
208
- properties: promptTypes.reduce((promptAcc, promptType) => ({
209
- ...promptAcc,
210
- [promptType]: {
213
+ properties: screenTypes.reduce((screenAcc, screenType) => ({
214
+ ...screenAcc,
215
+ [screenType]: {
211
216
  type: 'object',
212
- properties: screenTypes.reduce((screenAcc, screenType) => ({
213
- ...screenAcc,
214
- [screenType]: {
215
- type: 'object',
216
- },
217
- }), {}),
218
217
  },
219
218
  }), {}),
220
219
  },
220
+ language: {
221
+ type: 'object',
222
+ properties: promptTypes.reduce((promptAcc, promptType) => ({
223
+ ...promptAcc,
224
+ [promptType]: { $ref: '#/definitions/promptType' },
225
+ }), {}),
226
+ },
227
+ },
228
+ properties: types_1.languages.reduce((acc, language) => ({
229
+ ...acc,
230
+ [language]: { $ref: '#/definitions/language' },
221
231
  }), {}),
222
232
  },
223
233
  partials: {
@@ -306,12 +316,35 @@ class PromptsHandler extends default_1.default {
306
316
  }
307
317
  return prompts;
308
318
  }
319
+ /**
320
+ * Narrows the tenant's enabled languages to those listed in AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES.
321
+ * Custom text is fetched with one rate-limited request per language and prompt type, so
322
+ * limiting languages is the only way to shorten this step on tenants with many languages.
323
+ */
324
+ getCustomTextLanguages(enabledLanguages) {
325
+ const configuredLanguages = this.config('AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES');
326
+ if (configuredLanguages === undefined)
327
+ return enabledLanguages;
328
+ if (!Array.isArray(configuredLanguages) ||
329
+ !configuredLanguages.every((language) => typeof language === 'string')) {
330
+ throw new Error('AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES must be an array of language codes, e.g. ["en", "fr"].');
331
+ }
332
+ const notEnabledLanguages = configuredLanguages.filter((language) => !enabledLanguages.includes(language));
333
+ if (notEnabledLanguages.length > 0) {
334
+ logger_1.default.warn(`Skipping custom text for languages listed in AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES that are not enabled on the tenant: ${notEnabledLanguages.join(', ')}`);
335
+ }
336
+ const languages = enabledLanguages.filter((language) => configuredLanguages.includes(language));
337
+ logger_1.default.info(`Retrieving prompts custom text only for languages in AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES: ${languages.join(', ') || '(none)'}`);
338
+ return languages;
339
+ }
309
340
  async getCustomTextSettings() {
310
- const supportedLanguages = await this.client.tenants.settings.get().then((res) => {
341
+ const enabledLanguages = await this.client.tenants.settings.get().then((res) => {
311
342
  if (res.enabled_locales === undefined)
312
343
  return []; // In rare cases, private cloud tenants may not have `enabled_locales` defined
313
344
  return res.enabled_locales;
314
345
  });
346
+ const supportedLanguages = this.getCustomTextLanguages(enabledLanguages);
347
+ logger_1.default.debug(`Fetching prompts custom text for ${supportedLanguages.length} language(s) x ${promptTypes.length} prompt type(s) (${supportedLanguages.length * promptTypes.length} requests). This endpoint is rate-limited by Auth0, so this may take a while on tenants with many languages enabled; set AUTH0_EXPORT_CUSTOM_TEXT_LANGUAGES to limit which languages are fetched.`);
315
348
  return this.client.pool
316
349
  .addEachTask({
317
350
  data: supportedLanguages
@@ -496,7 +529,7 @@ class PromptsHandler extends default_1.default {
496
529
  updatePayload = {
497
530
  ...updatePrams,
498
531
  rendering_mode: auth0_1.Management.AculRenderingModeEnum.Advanced,
499
- default_head_tags_disabled: screenRenderer.default_head_tags_disabled || undefined,
532
+ default_head_tags_disabled: screenRenderer.default_head_tags_disabled ?? undefined,
500
533
  head_tags: screenRenderer.head_tags,
501
534
  };
502
535
  }
@@ -0,0 +1,81 @@
1
+ import { Management } from 'auth0';
2
+ import DefaultAPIHandler from './default';
3
+ import { Asset, Assets, CalculatedChanges } from '../../../types';
4
+ export type RateLimitPolicyConfiguration = Management.RateLimitPolicyConfiguration;
5
+ export type RateLimitPolicy = Management.RateLimitPolicy;
6
+ export declare const schema: {
7
+ type: string;
8
+ items: {
9
+ type: string;
10
+ properties: {
11
+ resource: {
12
+ type: string;
13
+ enum: "oauth_authentication_api"[];
14
+ };
15
+ consumer: {
16
+ type: string;
17
+ enum: "client"[];
18
+ };
19
+ consumer_selector: {
20
+ type: string;
21
+ };
22
+ configuration: {
23
+ type: string;
24
+ oneOf: ({
25
+ required: string[];
26
+ properties: {
27
+ action: {
28
+ type: string;
29
+ enum: string[];
30
+ };
31
+ limit?: undefined;
32
+ redirect_uri?: undefined;
33
+ };
34
+ additionalProperties: boolean;
35
+ } | {
36
+ required: string[];
37
+ properties: {
38
+ action: {
39
+ type: string;
40
+ enum: string[];
41
+ };
42
+ limit: {
43
+ type: string;
44
+ };
45
+ redirect_uri?: undefined;
46
+ };
47
+ additionalProperties: boolean;
48
+ } | {
49
+ required: string[];
50
+ properties: {
51
+ action: {
52
+ type: string;
53
+ enum: string[];
54
+ };
55
+ limit: {
56
+ type: string;
57
+ };
58
+ redirect_uri: {
59
+ type: string;
60
+ };
61
+ };
62
+ additionalProperties: boolean;
63
+ })[];
64
+ };
65
+ };
66
+ required: string[];
67
+ };
68
+ };
69
+ export default class RateLimitPoliciesHandler extends DefaultAPIHandler {
70
+ existing: RateLimitPolicy[] | null;
71
+ constructor(config: DefaultAPIHandler);
72
+ objString(policy: RateLimitPolicy): string;
73
+ getType(): Promise<Asset | null>;
74
+ processChanges(assets: Assets): Promise<void>;
75
+ createRateLimitPolicy(policy: RateLimitPolicy): Promise<RateLimitPolicy>;
76
+ createRateLimitPolicies(creates: CalculatedChanges['create']): Promise<void>;
77
+ updateRateLimitPolicy(policy: RateLimitPolicy): Promise<void>;
78
+ updateRateLimitPolicies(updates: CalculatedChanges['update']): Promise<void>;
79
+ deleteRateLimitPolicy(policy: RateLimitPolicy): Promise<void>;
80
+ deleteRateLimitPolicies(data: Asset[]): Promise<void>;
81
+ }
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.schema = void 0;
7
+ const auth0_1 = require("auth0");
8
+ const default_1 = __importDefault(require("./default"));
9
+ const client_1 = require("../client");
10
+ const utils_1 = require("../../utils");
11
+ const logger_1 = __importDefault(require("../../../logger"));
12
+ exports.schema = {
13
+ type: 'array',
14
+ items: {
15
+ type: 'object',
16
+ properties: {
17
+ resource: {
18
+ type: 'string',
19
+ enum: Object.values(auth0_1.Management.RateLimitPolicyResourceEnum),
20
+ },
21
+ consumer: {
22
+ type: 'string',
23
+ enum: Object.values(auth0_1.Management.RateLimitPolicyConsumerEnum),
24
+ },
25
+ consumer_selector: {
26
+ type: 'string',
27
+ },
28
+ configuration: {
29
+ type: 'object',
30
+ oneOf: [
31
+ {
32
+ required: ['action'],
33
+ properties: {
34
+ action: { type: 'string', enum: ['allow'] },
35
+ },
36
+ additionalProperties: false,
37
+ },
38
+ {
39
+ required: ['action', 'limit'],
40
+ properties: {
41
+ action: { type: 'string', enum: ['block', 'log'] },
42
+ limit: { type: 'number' },
43
+ },
44
+ additionalProperties: false,
45
+ },
46
+ {
47
+ required: ['action', 'limit', 'redirect_uri'],
48
+ properties: {
49
+ action: { type: 'string', enum: ['redirect'] },
50
+ limit: { type: 'number' },
51
+ redirect_uri: { type: 'string' },
52
+ },
53
+ additionalProperties: false,
54
+ },
55
+ ],
56
+ },
57
+ },
58
+ required: ['resource', 'consumer', 'consumer_selector', 'configuration'],
59
+ },
60
+ };
61
+ class RateLimitPoliciesHandler extends default_1.default {
62
+ constructor(config) {
63
+ super({
64
+ ...config,
65
+ type: 'rateLimitPolicies',
66
+ id: 'id',
67
+ identifiers: ['id', 'consumer_selector'],
68
+ stripCreateFields: ['id', 'created_at', 'updated_at'],
69
+ stripUpdateFields: [
70
+ 'id',
71
+ 'resource',
72
+ 'consumer',
73
+ 'consumer_selector',
74
+ 'created_at',
75
+ 'updated_at',
76
+ ],
77
+ });
78
+ }
79
+ objString(policy) {
80
+ return super.objString({
81
+ consumer_selector: policy.consumer_selector,
82
+ resource: policy.resource,
83
+ });
84
+ }
85
+ async getType() {
86
+ if (this.existing)
87
+ return this.existing;
88
+ try {
89
+ const rateLimitPolicies = await (0, client_1.paginate)(this.client.rateLimitPolicies.list, { checkpoint: true });
90
+ this.existing = rateLimitPolicies;
91
+ return this.existing;
92
+ }
93
+ catch (err) {
94
+ if (err.statusCode === 404 || err.statusCode === 501) {
95
+ return null;
96
+ }
97
+ if (err.statusCode === 403) {
98
+ logger_1.default.debug('Rate Limit Policies feature is not enabled for this tenant. Please contact Auth0 support to enable this feature.');
99
+ return null;
100
+ }
101
+ throw err;
102
+ }
103
+ }
104
+ async processChanges(assets) {
105
+ const { rateLimitPolicies } = assets;
106
+ if (!rateLimitPolicies)
107
+ return;
108
+ const { del, update, create } = await this.calcChanges(assets);
109
+ if ((0, utils_1.isDryRun)(this.config)) {
110
+ if (create.length === 0 && update.length === 0 && del.length === 0) {
111
+ return;
112
+ }
113
+ }
114
+ logger_1.default.debug(`Start processChanges for rateLimitPolicies [delete:${del.length}] [update:${update.length}], [create:${create.length}]`);
115
+ const changes = [{ del }, { create }, { update }];
116
+ await Promise.all(changes.map(async (change) => {
117
+ switch (true) {
118
+ case change.del && change.del.length > 0:
119
+ await this.deleteRateLimitPolicies(change.del);
120
+ break;
121
+ case change.create && change.create.length > 0:
122
+ await this.createRateLimitPolicies(change.create);
123
+ break;
124
+ case change.update && change.update.length > 0:
125
+ await this.updateRateLimitPolicies(change.update);
126
+ break;
127
+ default:
128
+ break;
129
+ }
130
+ }));
131
+ }
132
+ async createRateLimitPolicy(policy) {
133
+ const created = await this.client.rateLimitPolicies.create(policy);
134
+ return created;
135
+ }
136
+ async createRateLimitPolicies(creates) {
137
+ await this.client.pool
138
+ .addEachTask({
139
+ data: creates || [],
140
+ generator: (item) => this.createRateLimitPolicy(item)
141
+ .then((data) => {
142
+ this.didCreate(data);
143
+ this.created += 1;
144
+ })
145
+ .catch((err) => {
146
+ throw new Error(`Problem creating ${this.type} ${this.objString(item)}\n${err}`);
147
+ }),
148
+ })
149
+ .promise();
150
+ }
151
+ async updateRateLimitPolicy(policy) {
152
+ const { id, configuration } = policy;
153
+ if (!id) {
154
+ throw new Error(`Missing id for ${this.type} ${this.objString(policy)}`);
155
+ }
156
+ await this.client.rateLimitPolicies.update(id, { configuration });
157
+ }
158
+ async updateRateLimitPolicies(updates) {
159
+ await this.client.pool
160
+ .addEachTask({
161
+ data: updates || [],
162
+ generator: (item) => this.updateRateLimitPolicy(item)
163
+ .then(() => {
164
+ this.didUpdate(item);
165
+ this.updated += 1;
166
+ })
167
+ .catch((err) => {
168
+ throw new Error(`Problem updating ${this.type} ${this.objString(item)}\n${err}`);
169
+ }),
170
+ })
171
+ .promise();
172
+ }
173
+ async deleteRateLimitPolicy(policy) {
174
+ if (!policy.id) {
175
+ throw new Error(`Missing id for ${this.type} ${this.objString(policy)}`);
176
+ }
177
+ await this.client.rateLimitPolicies.delete(policy.id);
178
+ }
179
+ async deleteRateLimitPolicies(data) {
180
+ if (this.config('AUTH0_ALLOW_DELETE') === 'true' ||
181
+ this.config('AUTH0_ALLOW_DELETE') === true) {
182
+ await this.client.pool
183
+ .addEachTask({
184
+ data: data || [],
185
+ generator: (item) => this.deleteRateLimitPolicy(item)
186
+ .then(() => {
187
+ this.didDelete(item);
188
+ this.deleted += 1;
189
+ })
190
+ .catch((err) => {
191
+ throw new Error(`Problem deleting ${this.type} ${this.objString(item)}\n${err}`);
192
+ }),
193
+ })
194
+ .promise();
195
+ }
196
+ else {
197
+ logger_1.default.warn(`Detected the following ${this.type} should be deleted. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${data
198
+ .map((i) => this.objString(i))
199
+ .join('\n')}`);
200
+ }
201
+ }
202
+ }
203
+ exports.default = RateLimitPoliciesHandler;
@@ -85,14 +85,62 @@ export declare const schema: {
85
85
  };
86
86
  };
87
87
  };
88
+ anonymous_user: {
89
+ type: string;
90
+ description: string;
91
+ properties: {
92
+ policy: {
93
+ type: string;
94
+ enum: ("deny_all" | "require_client_grant")[];
95
+ };
96
+ };
97
+ };
88
98
  };
89
99
  additionalProperties: boolean;
90
100
  };
101
+ token_lifetime_for_anonymous_access_tokens: {
102
+ type: string;
103
+ description: string;
104
+ };
105
+ access_token: {
106
+ type: string[];
107
+ description: string;
108
+ properties: {
109
+ claims_mapping: {
110
+ type: string;
111
+ description: string;
112
+ properties: {
113
+ custom_claims: {
114
+ type: string;
115
+ description: string;
116
+ items: {
117
+ type: string;
118
+ properties: {
119
+ name: {
120
+ type: string;
121
+ description: string;
122
+ };
123
+ expression: {
124
+ type: string;
125
+ description: string;
126
+ };
127
+ };
128
+ required: string[];
129
+ };
130
+ };
131
+ };
132
+ };
133
+ };
134
+ };
91
135
  client_id: {
92
136
  type: string;
93
137
  description: string;
94
138
  readOnly: boolean;
95
139
  };
140
+ require_consent_non_repudiation: {
141
+ type: string;
142
+ description: string;
143
+ };
96
144
  };
97
145
  required: string[];
98
146
  };
@@ -72,14 +72,62 @@ exports.schema = {
72
72
  },
73
73
  },
74
74
  },
75
+ anonymous_user: {
76
+ type: 'object',
77
+ description: 'Access Permissions for anonymous user flows',
78
+ properties: {
79
+ policy: {
80
+ type: 'string',
81
+ enum: Object.values(auth0_1.Management.ResourceServerSubjectTypeAuthorizationAnonymousUserPolicyEnum),
82
+ },
83
+ },
84
+ },
75
85
  },
76
86
  additionalProperties: false,
77
87
  },
88
+ token_lifetime_for_anonymous_access_tokens: {
89
+ type: 'number',
90
+ description: 'Expiration value (in seconds) for anonymous-session access tokens issued for this API.',
91
+ },
92
+ access_token: {
93
+ type: ['object', 'null'],
94
+ description: 'Custom configuration for access tokens.',
95
+ properties: {
96
+ claims_mapping: {
97
+ type: 'object',
98
+ description: 'Custom configuration for claims in access tokens.',
99
+ properties: {
100
+ custom_claims: {
101
+ type: 'array',
102
+ description: 'Custom claims to emit in anonymous-session access tokens. Each rule maps a value from the anonymous-session context onto a named access-token claim.',
103
+ items: {
104
+ type: 'object',
105
+ properties: {
106
+ name: {
107
+ type: 'string',
108
+ description: 'The access-token claim name to emit.',
109
+ },
110
+ expression: {
111
+ type: 'string',
112
+ description: 'Restricted dot-path expression read from the anonymous-session context.',
113
+ },
114
+ },
115
+ required: ['name', 'expression'],
116
+ },
117
+ },
118
+ },
119
+ },
120
+ },
121
+ },
78
122
  client_id: {
79
123
  type: 'string',
80
124
  description: 'The client ID of the client that this resource server is linked to (readonly)',
81
125
  readOnly: true,
82
126
  },
127
+ require_consent_non_repudiation: {
128
+ type: 'boolean',
129
+ description: 'When true, the authorization server rejects consent decisions that do not include a valid signature and kid. Requires the my_account_consents entitlement.',
130
+ },
83
131
  },
84
132
  required: ['name', 'identifier'],
85
133
  },
@@ -120,6 +168,7 @@ class ResourceServersHandler extends default_1.default {
120
168
  'id',
121
169
  'is_system',
122
170
  'authorization_policy',
171
+ 'require_consent_non_repudiation',
123
172
  ];
124
173
  const sanitized = {};
125
174
  allowedKeys.forEach((key) => {
@@ -164,14 +213,19 @@ class ResourceServersHandler extends default_1.default {
164
213
  });
165
214
  }
166
215
  async updateResourceServer(id, update) {
167
- // Exclude name from update as it cannot be modified for system resource servers like Auth0 My Account API
168
- if (update.is_system === true || update.name === 'Auth0 My Account API') {
216
+ // Exclude name from update as it cannot be modified for system resource servers like the
217
+ // Auth0 My Account API or the Auth0 My Organization API. `is_system` is listed in
218
+ // `stripUpdateFields`, so it has already been removed from `update` by the time this runs -
219
+ // read it off the existing resource server instead, which `getType()` retains it on.
220
+ const existing = this.existing?.find((resourceServer) => resourceServer.id === id);
221
+ if (existing?.is_system === true) {
169
222
  const updateFields = {
170
223
  token_lifetime: update.token_lifetime,
171
224
  proof_of_possession: update.proof_of_possession,
172
225
  skip_consent_for_verifiable_first_party_clients: update.skip_consent_for_verifiable_first_party_clients,
173
226
  subject_type_authorization: update.subject_type_authorization,
174
227
  authorization_policy: update.authorization_policy,
228
+ require_consent_non_repudiation: update.require_consent_non_repudiation,
175
229
  };
176
230
  return this.client.resourceServers.update(id, updateFields);
177
231
  }