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.
- package/AGENTS.md +2 -357
- package/CHANGELOG.md +185 -10
- package/CLAUDE.md +138 -2
- 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/actionModules.js +1 -4
- package/lib/context/directory/handlers/actions.js +1 -4
- package/lib/context/directory/handlers/attackProtection.js +11 -1
- package/lib/context/directory/handlers/branding.js +4 -1
- package/lib/context/directory/handlers/clientAuthCredentials.d.ts +5 -0
- package/lib/context/directory/handlers/clientAuthCredentials.js +13 -0
- package/lib/context/directory/handlers/clientGrants.js +78 -24
- package/lib/context/directory/handlers/clients.js +20 -3
- package/lib/context/directory/handlers/connections.js +19 -5
- package/lib/context/directory/handlers/databases.js +1 -4
- package/lib/context/directory/handlers/emailTemplates.js +5 -0
- package/lib/context/directory/handlers/guardianEmailFactorSettings.d.ts +5 -0
- package/lib/context/directory/handlers/guardianEmailFactorSettings.js +38 -0
- package/lib/context/directory/handlers/guardianPhoneFactorSettings.d.ts +5 -0
- package/lib/context/directory/handlers/guardianPhoneFactorSettings.js +38 -0
- package/lib/context/directory/handlers/guardianSettings.d.ts +5 -0
- package/lib/context/directory/handlers/guardianSettings.js +38 -0
- package/lib/context/directory/handlers/hooks.js +1 -4
- package/lib/context/directory/handlers/index.js +12 -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 +7 -3
- package/lib/context/directory/handlers/rateLimitPolicies.d.ts +6 -0
- package/lib/context/directory/handlers/rateLimitPolicies.js +53 -0
- package/lib/context/directory/handlers/rules.js +1 -4
- package/lib/context/directory/index.js +1 -4
- package/lib/context/index.js +32 -31
- package/lib/context/yaml/handlers/attackProtection.js +5 -2
- package/lib/context/yaml/handlers/branding.js +4 -1
- package/lib/context/yaml/handlers/clientAuthCredentials.d.ts +5 -0
- package/lib/context/yaml/handlers/clientAuthCredentials.js +13 -0
- package/lib/context/yaml/handlers/clients.js +19 -1
- package/lib/context/yaml/handlers/connections.js +8 -1
- package/lib/context/yaml/handlers/flows.js +3 -0
- package/lib/context/yaml/handlers/forms.js +3 -0
- package/lib/context/yaml/handlers/guardianEmailFactorSettings.d.ts +5 -0
- package/lib/context/yaml/handlers/guardianEmailFactorSettings.js +15 -0
- package/lib/context/yaml/handlers/guardianPhoneFactorSettings.d.ts +5 -0
- package/lib/context/yaml/handlers/guardianPhoneFactorSettings.js +15 -0
- package/lib/context/yaml/handlers/guardianSettings.d.ts +5 -0
- package/lib/context/yaml/handlers/guardianSettings.js +15 -0
- package/lib/context/yaml/handlers/index.js +12 -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 +3 -1
- package/lib/context/yaml/handlers/rateLimitPolicies.d.ts +6 -0
- package/lib/context/yaml/handlers/rateLimitPolicies.js +27 -0
- package/lib/context/yaml/index.js +85 -7
- 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.d.ts +12 -0
- package/lib/tools/auth0/handlers/attackProtection.js +66 -6
- package/lib/tools/auth0/handlers/clientAuthCredentials.d.ts +27 -0
- package/lib/tools/auth0/handlers/clientAuthCredentials.js +234 -0
- package/lib/tools/auth0/handlers/clientAuthCredentialsPre.d.ts +38 -0
- package/lib/tools/auth0/handlers/clientAuthCredentialsPre.js +123 -0
- package/lib/tools/auth0/handlers/clientGrants.d.ts +1 -1
- package/lib/tools/auth0/handlers/clients.d.ts +106 -0
- package/lib/tools/auth0/handlers/clients.js +207 -3
- 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.d.ts +34 -6
- package/lib/tools/auth0/handlers/connections.js +75 -11
- package/lib/tools/auth0/handlers/databases.d.ts +28 -0
- package/lib/tools/auth0/handlers/databases.js +58 -24
- package/lib/tools/auth0/handlers/default.d.ts +23 -0
- package/lib/tools/auth0/handlers/default.js +47 -29
- package/lib/tools/auth0/handlers/eventStreams.js +10 -2
- package/lib/tools/auth0/handlers/guardianEmailFactorSettings.d.ts +22 -0
- package/lib/tools/auth0/handlers/guardianEmailFactorSettings.js +77 -0
- package/lib/tools/auth0/handlers/guardianFactorTemplates.js +13 -4
- package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +11 -9
- package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +11 -9
- package/lib/tools/auth0/handlers/guardianPhoneFactorSettings.d.ts +22 -0
- package/lib/tools/auth0/handlers/guardianPhoneFactorSettings.js +77 -0
- package/lib/tools/auth0/handlers/guardianPolicies.js +11 -1
- package/lib/tools/auth0/handlers/guardianSettings.d.ts +30 -0
- package/lib/tools/auth0/handlers/guardianSettings.js +85 -0
- package/lib/tools/auth0/handlers/hooks.js +1 -1
- package/lib/tools/auth0/handlers/index.js +16 -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 +132 -2
- package/lib/tools/auth0/handlers/networkACLs.js +100 -16
- package/lib/tools/auth0/handlers/organizations.d.ts +33 -1
- package/lib/tools/auth0/handlers/organizations.js +177 -19
- package/lib/tools/auth0/handlers/phoneProvider.js +10 -2
- package/lib/tools/auth0/handlers/phoneTemplates.d.ts +4 -1
- package/lib/tools/auth0/handlers/phoneTemplates.js +67 -10
- package/lib/tools/auth0/handlers/prompts.d.ts +17 -0
- package/lib/tools/auth0/handlers/prompts.js +47 -14
- package/lib/tools/auth0/handlers/rateLimitPolicies.d.ts +81 -0
- package/lib/tools/auth0/handlers/rateLimitPolicies.js +203 -0
- package/lib/tools/auth0/handlers/resourceServers.d.ts +48 -0
- package/lib/tools/auth0/handlers/resourceServers.js +56 -2
- package/lib/tools/auth0/handlers/riskAssessment.d.ts +1 -1
- package/lib/tools/auth0/handlers/riskAssessment.js +19 -1
- package/lib/tools/auth0/handlers/roles.d.ts +4 -0
- package/lib/tools/auth0/handlers/roles.js +27 -9
- package/lib/tools/auth0/handlers/rules.js +19 -7
- package/lib/tools/auth0/handlers/scimHandler.js +8 -3
- package/lib/tools/auth0/handlers/tenant.d.ts +45 -0
- package/lib/tools/auth0/handlers/tenant.js +48 -0
- package/lib/tools/auth0/handlers/themes.d.ts +37 -1
- package/lib/tools/auth0/handlers/themes.js +64 -0
- package/lib/tools/auth0/handlers/tokenExchangeProfiles.js +3 -1
- package/lib/tools/auth0/index.js +12 -6
- package/lib/tools/calculateDryRunChanges.js +12 -8
- package/lib/tools/constants.d.ts +3 -0
- package/lib/tools/constants.js +8 -0
- package/lib/tools/utils.d.ts +3 -0
- package/lib/tools/utils.js +41 -2
- package/lib/types.d.ts +10 -1
- package/lib/utils.d.ts +6 -0
- package/lib/utils.js +17 -2
- package/package.json +2 -2
- package/references/code-style.md +133 -0
- package/references/commands.md +98 -0
- package/references/docs-update.md +34 -0
- package/references/git-workflow.md +135 -0
- package/references/pitfalls.md +62 -0
- 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
|
-
|
|
125
|
-
|
|
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 (
|
|
128
|
-
await this.updatePhoneTemplates(
|
|
144
|
+
if (hasId.length > 0) {
|
|
145
|
+
await this.updatePhoneTemplates(hasId);
|
|
129
146
|
}
|
|
130
147
|
}
|
|
131
148
|
async createPhoneTemplate(template) {
|
|
132
|
-
|
|
133
|
-
|
|
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((
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
[language]: {
|
|
210
|
+
definitions: {
|
|
211
|
+
promptType: {
|
|
207
212
|
type: 'object',
|
|
208
|
-
properties:
|
|
209
|
-
...
|
|
210
|
-
[
|
|
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
|
|
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
|
|
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
|
|
168
|
-
|
|
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
|
}
|