auth0-deploy-cli 7.7.1 → 7.8.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 +14 -1
- package/lib/args.d.ts +29 -0
- package/lib/commands/export.d.ts +2 -0
- package/lib/commands/import.d.ts +2 -0
- package/lib/commands/index.d.ts +9 -0
- package/lib/configFactory.d.ts +7 -0
- package/lib/context/defaults.d.ts +1 -0
- package/lib/context/directory/handlers/actions.d.ts +6 -0
- package/lib/context/directory/handlers/attackProtection.d.ts +10 -0
- package/lib/context/directory/handlers/branding.d.ts +6 -0
- package/lib/context/directory/handlers/clientGrants.d.ts +6 -0
- package/lib/context/directory/handlers/clients.d.ts +6 -0
- package/lib/context/directory/handlers/connections.d.ts +6 -0
- package/lib/context/directory/handlers/databases.d.ts +6 -0
- package/lib/context/directory/handlers/emailProvider.d.ts +6 -0
- package/lib/context/directory/handlers/emailTemplates.d.ts +6 -0
- package/lib/context/directory/handlers/guardianFactorProviders.d.ts +6 -0
- package/lib/context/directory/handlers/guardianFactorTemplates.d.ts +6 -0
- package/lib/context/directory/handlers/guardianFactors.d.ts +6 -0
- package/lib/context/directory/handlers/guardianPhoneFactorMessageTypes.d.ts +6 -0
- package/lib/context/directory/handlers/guardianPhoneFactorSelectedProvider.d.ts +6 -0
- package/lib/context/directory/handlers/guardianPolicies.d.ts +6 -0
- package/lib/context/directory/handlers/hooks.d.ts +6 -0
- package/lib/context/directory/handlers/index.d.ts +12 -0
- package/lib/context/directory/handlers/migrations.d.ts +6 -0
- package/lib/context/directory/handlers/organizations.d.ts +6 -0
- package/lib/context/directory/handlers/pages.d.ts +6 -0
- package/lib/context/directory/handlers/resourceServers.d.ts +6 -0
- package/lib/context/directory/handlers/roles.d.ts +6 -0
- package/lib/context/directory/handlers/rules.d.ts +6 -0
- package/lib/context/directory/handlers/rulesConfigs.d.ts +6 -0
- package/lib/context/directory/handlers/tenant.d.ts +10 -0
- package/lib/context/directory/handlers/triggers.d.ts +6 -0
- package/lib/context/directory/index.d.ts +17 -0
- package/lib/context/index.d.ts +4 -0
- package/lib/context/yaml/handlers/actions.d.ts +6 -0
- package/lib/context/yaml/handlers/attackProtection.d.ts +6 -0
- package/lib/context/yaml/handlers/branding.d.ts +6 -0
- package/lib/context/yaml/handlers/clientGrants.d.ts +6 -0
- package/lib/context/yaml/handlers/clients.d.ts +6 -0
- package/lib/context/yaml/handlers/connections.d.ts +6 -0
- package/lib/context/yaml/handlers/databases.d.ts +6 -0
- package/lib/context/yaml/handlers/emailProvider.d.ts +6 -0
- package/lib/context/yaml/handlers/emailTemplates.d.ts +6 -0
- package/lib/context/yaml/handlers/guardianFactorProviders.d.ts +6 -0
- package/lib/context/yaml/handlers/guardianFactorTemplates.d.ts +6 -0
- package/lib/context/yaml/handlers/guardianFactors.d.ts +6 -0
- package/lib/context/yaml/handlers/guardianPhoneFactorMessageTypes.d.ts +6 -0
- package/lib/context/yaml/handlers/guardianPhoneFactorSelectedProvider.d.ts +6 -0
- package/lib/context/yaml/handlers/guardianPolicies.d.ts +6 -0
- package/lib/context/yaml/handlers/hooks.d.ts +6 -0
- package/lib/context/yaml/handlers/index.d.ts +12 -0
- package/lib/context/yaml/handlers/migrations.d.ts +6 -0
- package/lib/context/yaml/handlers/organizations.d.ts +6 -0
- package/lib/context/yaml/handlers/pages.d.ts +6 -0
- package/lib/context/yaml/handlers/resourceServers.d.ts +6 -0
- package/lib/context/yaml/handlers/roles.d.ts +6 -0
- package/lib/context/yaml/handlers/rules.d.ts +6 -0
- package/lib/context/yaml/handlers/rulesConfigs.d.ts +6 -0
- package/lib/context/yaml/handlers/tenant.d.ts +6 -0
- package/lib/context/yaml/handlers/triggers.d.ts +6 -0
- package/lib/context/yaml/index.d.ts +13 -0
- package/lib/index.d.ts +88 -0
- package/lib/index.js +5 -2
- package/lib/logger.d.ts +2 -0
- package/lib/logger.js +7 -17
- package/lib/readonly.d.ts +2 -0
- package/lib/sessionDurationsToMinutes.d.ts +7 -0
- package/lib/tools/auth0/client.d.ts +2 -0
- package/lib/tools/auth0/handlers/actions.d.ts +95 -0
- package/lib/tools/auth0/handlers/actions.js +1 -1
- package/lib/tools/auth0/handlers/attackProtection.d.ts +28 -0
- package/lib/tools/auth0/handlers/branding.d.ts +27 -0
- package/lib/tools/auth0/handlers/clientGrants.d.ts +32 -0
- package/lib/tools/auth0/handlers/clients.d.ts +23 -0
- package/lib/tools/auth0/handlers/connections.d.ts +54 -0
- package/lib/tools/auth0/handlers/databases.d.ts +36 -0
- package/lib/tools/auth0/handlers/default.d.ts +54 -0
- package/lib/tools/auth0/handlers/default.js +22 -8
- package/lib/tools/auth0/handlers/emailProvider.d.ts +11 -0
- package/lib/tools/auth0/handlers/emailTemplates.d.ts +26 -0
- package/lib/tools/auth0/handlers/guardianFactorProviders.d.ts +25 -0
- package/lib/tools/auth0/handlers/guardianFactorTemplates.d.ts +21 -0
- package/lib/tools/auth0/handlers/guardianFactors.d.ts +21 -0
- package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.d.ts +21 -0
- package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.d.ts +18 -0
- package/lib/tools/auth0/handlers/guardianPolicies.d.ts +23 -0
- package/lib/tools/auth0/handlers/hooks.d.ts +58 -0
- package/lib/tools/auth0/handlers/index.d.ts +129 -0
- package/lib/tools/auth0/handlers/migrations.d.ts +15 -0
- package/lib/tools/auth0/handlers/migrations.js +1 -1
- package/lib/tools/auth0/handlers/organizations.d.ts +51 -0
- package/lib/tools/auth0/handlers/organizations.js +1 -1
- package/lib/tools/auth0/handlers/pages.d.ts +42 -0
- package/lib/tools/auth0/handlers/prompts.d.ts +11 -0
- package/lib/tools/auth0/handlers/resourceServers.d.ts +51 -0
- package/lib/tools/auth0/handlers/roles.d.ts +48 -0
- package/lib/tools/auth0/handlers/roles.js +1 -1
- package/lib/tools/auth0/handlers/rules.d.ts +55 -0
- package/lib/tools/auth0/handlers/rules.js +1 -1
- package/lib/tools/auth0/handlers/rulesConfigs.d.ts +25 -0
- package/lib/tools/auth0/handlers/tenant.d.ts +11 -0
- package/lib/tools/auth0/handlers/triggers.d.ts +35 -0
- package/lib/tools/auth0/handlers/triggers.js +1 -1
- package/lib/tools/auth0/index.d.ts +15 -0
- package/lib/tools/auth0/schema.d.ts +15 -0
- package/lib/tools/calculateChanges.d.ts +26 -0
- package/lib/tools/calculateChanges.js +1 -1
- package/lib/tools/constants.d.ts +71 -0
- package/lib/tools/constants.js +3 -1
- package/lib/tools/deploy.d.ts +3 -0
- package/lib/tools/deploy.js +2 -2
- package/lib/tools/index.d.ts +82 -0
- package/lib/tools/utils.d.ts +18 -0
- package/lib/tools/utils.js +35 -2
- package/lib/tools/validationError.d.ts +5 -0
- package/lib/types.d.ts +255 -0
- package/lib/utils.d.ts +66 -0
- package/package.json +7 -7
- package/tsconfig.json +2 -1
- package/lib/tools/logger.js +0 -21
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import DefaultHandler from './default';
|
|
2
|
+
import { Assets } from '../../../types';
|
|
3
|
+
export declare const schema: {
|
|
4
|
+
type: string;
|
|
5
|
+
items: {
|
|
6
|
+
type: string;
|
|
7
|
+
additionalProperties: boolean;
|
|
8
|
+
properties: {
|
|
9
|
+
trigger_id: {
|
|
10
|
+
type: string;
|
|
11
|
+
properties: {
|
|
12
|
+
action_name: {
|
|
13
|
+
type: string;
|
|
14
|
+
enum: string[];
|
|
15
|
+
};
|
|
16
|
+
display_name: {
|
|
17
|
+
type: string;
|
|
18
|
+
default: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export default class TriggersHandler extends DefaultHandler {
|
|
26
|
+
existing: {
|
|
27
|
+
[key: string]: {
|
|
28
|
+
action_name: string;
|
|
29
|
+
display_name: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
constructor(options: DefaultHandler);
|
|
33
|
+
getType(): Promise<DefaultHandler['existing']>;
|
|
34
|
+
processChanges(assets: Assets): Promise<void>;
|
|
35
|
+
}
|
|
@@ -45,7 +45,7 @@ exports.schema = void 0;
|
|
|
45
45
|
const lodash_1 = __importDefault(require("lodash"));
|
|
46
46
|
const default_1 = __importStar(require("./default"));
|
|
47
47
|
const constants_1 = __importDefault(require("../../constants"));
|
|
48
|
-
const logger_1 = __importDefault(require("
|
|
48
|
+
const logger_1 = __importDefault(require("../../../logger"));
|
|
49
49
|
exports.schema = {
|
|
50
50
|
type: 'object',
|
|
51
51
|
items: {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Assets, Auth0APIClient, BaseAuth0APIClient } from '../../types';
|
|
2
|
+
import APIHandler from './handlers/default';
|
|
3
|
+
import { ConfigFunction } from '../../configFactory';
|
|
4
|
+
export declare type Stage = 'load' | 'validate' | 'processChanges';
|
|
5
|
+
export default class Auth0 {
|
|
6
|
+
client: Auth0APIClient;
|
|
7
|
+
config: ConfigFunction;
|
|
8
|
+
assets: Assets;
|
|
9
|
+
handlers: APIHandler[];
|
|
10
|
+
constructor(client: BaseAuth0APIClient, assets: Assets, config: ConfigFunction);
|
|
11
|
+
runStage(stage: Stage): Promise<void>;
|
|
12
|
+
validate(): Promise<void>;
|
|
13
|
+
loadAll(): Promise<void>;
|
|
14
|
+
processChanges(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import APIHandler from '../tools/auth0/handlers/default';
|
|
2
|
+
import { Asset, CalculatedChanges } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {typeof import('./auth0/handlers/default').default} handler
|
|
6
|
+
* @param {T} desiredAssetState
|
|
7
|
+
* @param {T} currentAssetState
|
|
8
|
+
* @param {string[]} [objectFields=[]]
|
|
9
|
+
* @param {boolean} [allowDelete=false]
|
|
10
|
+
* @returns T
|
|
11
|
+
*/
|
|
12
|
+
export declare function processChangedObjectFields({ handler, desiredAssetState, currentAssetState, allowDelete, }: {
|
|
13
|
+
handler: APIHandler;
|
|
14
|
+
desiredAssetState: Asset;
|
|
15
|
+
currentAssetState: Asset;
|
|
16
|
+
allowDelete?: boolean;
|
|
17
|
+
}): {
|
|
18
|
+
[x: string]: any;
|
|
19
|
+
};
|
|
20
|
+
export declare function calculateChanges({ handler, assets, existing, identifiers, allowDelete, }: {
|
|
21
|
+
handler: APIHandler;
|
|
22
|
+
assets: Asset[];
|
|
23
|
+
existing: Asset[];
|
|
24
|
+
identifiers: string[];
|
|
25
|
+
allowDelete: boolean;
|
|
26
|
+
}): CalculatedChanges;
|
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.calculateChanges = exports.processChangedObjectFields = void 0;
|
|
7
|
-
const logger_1 = __importDefault(require("
|
|
7
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
8
8
|
/**
|
|
9
9
|
* @template T
|
|
10
10
|
* @param {typeof import('./auth0/handlers/default').default} handler
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
declare const constants: {
|
|
2
|
+
CONCURRENT_CALLS: number;
|
|
3
|
+
RULES_DIRECTORY: string;
|
|
4
|
+
RULES_STAGES: string[];
|
|
5
|
+
DEFAULT_RULE_STAGE: string;
|
|
6
|
+
HOOKS_HIDDEN_SECRET_VALUE: string;
|
|
7
|
+
OBFUSCATED_SECRET_VALUE: string;
|
|
8
|
+
HOOKS_DIRECTORY: string;
|
|
9
|
+
ACTIONS_DIRECTORY: string;
|
|
10
|
+
TRIGGERS_DIRECTORY: string;
|
|
11
|
+
RULES_CONFIGS_DIRECTORY: string;
|
|
12
|
+
PAGES_DIRECTORY: string;
|
|
13
|
+
PAGE_LOGIN: string;
|
|
14
|
+
PAGE_GUARDIAN_MULTIFACTOR: string;
|
|
15
|
+
PAGE_PASSWORD_RESET: string;
|
|
16
|
+
PAGE_ERROR: string;
|
|
17
|
+
DATABASE_CONNECTIONS_DIRECTORY: string;
|
|
18
|
+
DATABASE_SCRIPTS_CHANGE_EMAIL: string;
|
|
19
|
+
DATABASE_SCRIPTS_GET_USER: string;
|
|
20
|
+
EMAIL_TEMPLATES_TYPES: string[];
|
|
21
|
+
ACTIONS_TRIGGERS: string[];
|
|
22
|
+
EMAIL_TEMPLATES_DIRECTORY: string;
|
|
23
|
+
EMAIL_VERIFY: string;
|
|
24
|
+
EMAIL_VERIFY_BY_CODE: string;
|
|
25
|
+
EMAIL_RESET: string;
|
|
26
|
+
EMAIL_WELCOME: string;
|
|
27
|
+
EMAIL_BLOCKED: string;
|
|
28
|
+
EMAIL_STOLEN_CREDENTIALS: string;
|
|
29
|
+
EMAIL_ENROLLMENT: string;
|
|
30
|
+
EMAIL_CHANGE_PASSWORD: string;
|
|
31
|
+
EMAIL_PASSWORD_RESET: string;
|
|
32
|
+
EMAIL_MFA_OOB_CODE: string;
|
|
33
|
+
EMAIL_USER_INVITATION: string;
|
|
34
|
+
GUARDIAN_DIRECTORY: string;
|
|
35
|
+
GUARDIAN_FACTORS_DIRECTORY: string;
|
|
36
|
+
GUARDIAN_PROVIDERS_DIRECTORY: string;
|
|
37
|
+
GUARDIAN_TEMPLATES_DIRECTORY: string;
|
|
38
|
+
UNIVERSAL_LOGIN_TEMPLATE: string;
|
|
39
|
+
RESOURCE_SERVERS_DIRECTORY: string;
|
|
40
|
+
RESOURCE_SERVERS_CLIENT_NAME: string;
|
|
41
|
+
RESOURCE_SERVERS_MANAGEMENT_API_NAME: string;
|
|
42
|
+
RESOURCE_SERVERS_ID_NAME: string;
|
|
43
|
+
CLIENTS_DIRECTORY: string;
|
|
44
|
+
CLIENTS_GRANTS_DIRECTORY: string;
|
|
45
|
+
BRANDING_DIRECTORY: string;
|
|
46
|
+
BRANDING_TEMPLATES_DIRECTORY: string;
|
|
47
|
+
BRANDING_TEMPLATES_YAML_DIRECTORY: string;
|
|
48
|
+
CLIENTS_CLIENT_NAME: string;
|
|
49
|
+
CLIENTS_CLIENT_ID_NAME: string;
|
|
50
|
+
CONNECTIONS_DIRECTORY: string;
|
|
51
|
+
CONNECTIONS_CLIENT_NAME: string;
|
|
52
|
+
CONNECTIONS_ID_NAME: string;
|
|
53
|
+
ROLES_DIRECTORY: string;
|
|
54
|
+
ATTACK_PROTECTION_DIRECTORY: string;
|
|
55
|
+
GUARDIAN_FACTORS: string[];
|
|
56
|
+
GUARDIAN_POLICIES: string[];
|
|
57
|
+
GUARDIAN_PHONE_PROVIDERS: string[];
|
|
58
|
+
GUARDIAN_PHONE_MESSAGE_TYPES: string[];
|
|
59
|
+
GUARDIAN_FACTOR_TEMPLATES: string[];
|
|
60
|
+
GUARDIAN_FACTOR_PROVIDERS: {
|
|
61
|
+
sms: string[];
|
|
62
|
+
'push-notification': string[];
|
|
63
|
+
};
|
|
64
|
+
PAGE_NAMES: string[];
|
|
65
|
+
DATABASE_SCRIPTS: string[];
|
|
66
|
+
DATABASE_SCRIPTS_NO_IMPORT: string[];
|
|
67
|
+
DATABASE_SCRIPTS_IMPORT: string[];
|
|
68
|
+
EMAIL_TEMPLATES_NAMES: string[];
|
|
69
|
+
SUPPORTED_BRANDING_TEMPLATES: string[];
|
|
70
|
+
};
|
|
71
|
+
export default constants;
|
package/lib/tools/constants.js
CHANGED
|
@@ -19,12 +19,14 @@ const EMAIL_PASSWORD_RESET = 'password_reset';
|
|
|
19
19
|
const EMAIL_MFA_OOB_CODE = 'mfa_oob_code';
|
|
20
20
|
const EMAIL_USER_INVITATION = 'user_invitation';
|
|
21
21
|
const UNIVERSAL_LOGIN_TEMPLATE = 'universal_login';
|
|
22
|
+
const OBFUSCATED_SECRET_VALUE = '_VALUE_NOT_SHOWN_';
|
|
22
23
|
const constants = {
|
|
23
24
|
CONCURRENT_CALLS: 5,
|
|
24
25
|
RULES_DIRECTORY: 'rules',
|
|
25
26
|
RULES_STAGES,
|
|
26
27
|
DEFAULT_RULE_STAGE: RULES_STAGES[0],
|
|
27
|
-
HOOKS_HIDDEN_SECRET_VALUE:
|
|
28
|
+
HOOKS_HIDDEN_SECRET_VALUE: OBFUSCATED_SECRET_VALUE,
|
|
29
|
+
OBFUSCATED_SECRET_VALUE,
|
|
28
30
|
HOOKS_DIRECTORY: 'hooks',
|
|
29
31
|
ACTIONS_DIRECTORY: 'actions',
|
|
30
32
|
TRIGGERS_DIRECTORY: 'triggers',
|
package/lib/tools/deploy.js
CHANGED
|
@@ -13,11 +13,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const auth0_1 = __importDefault(require("./auth0"));
|
|
16
|
-
const logger_1 = __importDefault(require("
|
|
16
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
17
17
|
function deploy(assets, client, config) {
|
|
18
18
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
// Setup log level
|
|
20
|
-
logger_1.default.
|
|
20
|
+
logger_1.default.level = process.env.AUTH0_DEBUG === 'true' ? 'debug' : 'info';
|
|
21
21
|
logger_1.default.info('Getting access token for ' + config('AUTH0_CLIENT_ID') + '/' + config('AUTH0_DOMAIN'));
|
|
22
22
|
const auth0 = new auth0_1.default(client, assets, config);
|
|
23
23
|
// Validate Assets
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import constants from './constants';
|
|
2
|
+
import deploy from './deploy';
|
|
3
|
+
import Auth0 from './auth0';
|
|
4
|
+
import { keywordReplace, loadFileAndReplaceKeywords } from './utils';
|
|
5
|
+
declare const _default: {
|
|
6
|
+
constants: {
|
|
7
|
+
CONCURRENT_CALLS: number;
|
|
8
|
+
RULES_DIRECTORY: string;
|
|
9
|
+
RULES_STAGES: string[];
|
|
10
|
+
DEFAULT_RULE_STAGE: string;
|
|
11
|
+
HOOKS_HIDDEN_SECRET_VALUE: string;
|
|
12
|
+
OBFUSCATED_SECRET_VALUE: string;
|
|
13
|
+
HOOKS_DIRECTORY: string;
|
|
14
|
+
ACTIONS_DIRECTORY: string;
|
|
15
|
+
TRIGGERS_DIRECTORY: string;
|
|
16
|
+
RULES_CONFIGS_DIRECTORY: string;
|
|
17
|
+
PAGES_DIRECTORY: string;
|
|
18
|
+
PAGE_LOGIN: string;
|
|
19
|
+
PAGE_GUARDIAN_MULTIFACTOR: string;
|
|
20
|
+
PAGE_PASSWORD_RESET: string;
|
|
21
|
+
PAGE_ERROR: string;
|
|
22
|
+
DATABASE_CONNECTIONS_DIRECTORY: string;
|
|
23
|
+
DATABASE_SCRIPTS_CHANGE_EMAIL: string;
|
|
24
|
+
DATABASE_SCRIPTS_GET_USER: string;
|
|
25
|
+
EMAIL_TEMPLATES_TYPES: string[];
|
|
26
|
+
ACTIONS_TRIGGERS: string[];
|
|
27
|
+
EMAIL_TEMPLATES_DIRECTORY: string;
|
|
28
|
+
EMAIL_VERIFY: string;
|
|
29
|
+
EMAIL_VERIFY_BY_CODE: string;
|
|
30
|
+
EMAIL_RESET: string;
|
|
31
|
+
EMAIL_WELCOME: string;
|
|
32
|
+
EMAIL_BLOCKED: string;
|
|
33
|
+
EMAIL_STOLEN_CREDENTIALS: string;
|
|
34
|
+
EMAIL_ENROLLMENT: string;
|
|
35
|
+
EMAIL_CHANGE_PASSWORD: string;
|
|
36
|
+
EMAIL_PASSWORD_RESET: string;
|
|
37
|
+
EMAIL_MFA_OOB_CODE: string;
|
|
38
|
+
EMAIL_USER_INVITATION: string;
|
|
39
|
+
GUARDIAN_DIRECTORY: string;
|
|
40
|
+
GUARDIAN_FACTORS_DIRECTORY: string;
|
|
41
|
+
GUARDIAN_PROVIDERS_DIRECTORY: string;
|
|
42
|
+
GUARDIAN_TEMPLATES_DIRECTORY: string;
|
|
43
|
+
UNIVERSAL_LOGIN_TEMPLATE: string;
|
|
44
|
+
RESOURCE_SERVERS_DIRECTORY: string;
|
|
45
|
+
RESOURCE_SERVERS_CLIENT_NAME: string;
|
|
46
|
+
RESOURCE_SERVERS_MANAGEMENT_API_NAME: string;
|
|
47
|
+
RESOURCE_SERVERS_ID_NAME: string;
|
|
48
|
+
CLIENTS_DIRECTORY: string;
|
|
49
|
+
CLIENTS_GRANTS_DIRECTORY: string;
|
|
50
|
+
BRANDING_DIRECTORY: string;
|
|
51
|
+
BRANDING_TEMPLATES_DIRECTORY: string;
|
|
52
|
+
BRANDING_TEMPLATES_YAML_DIRECTORY: string;
|
|
53
|
+
CLIENTS_CLIENT_NAME: string;
|
|
54
|
+
CLIENTS_CLIENT_ID_NAME: string;
|
|
55
|
+
CONNECTIONS_DIRECTORY: string;
|
|
56
|
+
CONNECTIONS_CLIENT_NAME: string;
|
|
57
|
+
CONNECTIONS_ID_NAME: string;
|
|
58
|
+
ROLES_DIRECTORY: string;
|
|
59
|
+
ATTACK_PROTECTION_DIRECTORY: string;
|
|
60
|
+
GUARDIAN_FACTORS: string[];
|
|
61
|
+
GUARDIAN_POLICIES: string[];
|
|
62
|
+
GUARDIAN_PHONE_PROVIDERS: string[];
|
|
63
|
+
GUARDIAN_PHONE_MESSAGE_TYPES: string[];
|
|
64
|
+
GUARDIAN_FACTOR_TEMPLATES: string[];
|
|
65
|
+
GUARDIAN_FACTOR_PROVIDERS: {
|
|
66
|
+
sms: string[];
|
|
67
|
+
'push-notification': string[];
|
|
68
|
+
};
|
|
69
|
+
PAGE_NAMES: string[];
|
|
70
|
+
DATABASE_SCRIPTS: string[];
|
|
71
|
+
DATABASE_SCRIPTS_NO_IMPORT: string[];
|
|
72
|
+
DATABASE_SCRIPTS_IMPORT: string[];
|
|
73
|
+
EMAIL_TEMPLATES_NAMES: string[];
|
|
74
|
+
SUPPORTED_BRANDING_TEMPLATES: string[];
|
|
75
|
+
};
|
|
76
|
+
deploy: typeof deploy;
|
|
77
|
+
keywordReplace: typeof keywordReplace;
|
|
78
|
+
loadFileAndReplaceKeywords: typeof loadFileAndReplaceKeywords;
|
|
79
|
+
Auth0: typeof Auth0;
|
|
80
|
+
};
|
|
81
|
+
export default _default;
|
|
82
|
+
export { constants, deploy, keywordReplace, loadFileAndReplaceKeywords, Auth0 };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Asset, Assets, CalculatedChanges, KeywordMappings } from '../types';
|
|
2
|
+
export declare function keywordArrayReplace(input: string, mappings: KeywordMappings): string;
|
|
3
|
+
export declare function keywordStringReplace(input: string, mappings: KeywordMappings): string;
|
|
4
|
+
export declare function keywordReplace(input: string, mappings: KeywordMappings): string;
|
|
5
|
+
export declare function convertClientNameToId(name: string, clients: Asset[]): string;
|
|
6
|
+
export declare function convertClientNamesToIds(names: string[], clients: Asset[]): string[];
|
|
7
|
+
export declare function loadFileAndReplaceKeywords(file: string, mappings: KeywordMappings): string;
|
|
8
|
+
export declare function flatten(list: any[]): any[];
|
|
9
|
+
export declare function convertJsonToString(obj: {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}, spacing?: number): string;
|
|
12
|
+
export declare function stripFields(obj: Asset, fields: string[]): Asset;
|
|
13
|
+
export declare function getEnabledClients(assets: Assets, connection: Asset, existing: Asset[], clients: Asset[]): string[];
|
|
14
|
+
export declare function duplicateItems(arr: Asset[], key: string): Asset[];
|
|
15
|
+
export declare function filterExcluded(changes: CalculatedChanges, exclude: string[]): CalculatedChanges;
|
|
16
|
+
export declare function areArraysEquals(x: any[], y: any[]): boolean;
|
|
17
|
+
export declare const obfuscateSensitiveValues: (data: Asset | Asset[] | null, sensitiveFieldsToObfuscate: string[]) => Asset | Asset[] | null;
|
|
18
|
+
export declare const stripObfuscatedFieldsFromPayload: (data: Asset | Asset[] | null, obfuscatedFields: string[]) => Asset | Asset[] | null;
|
package/lib/tools/utils.js
CHANGED
|
@@ -26,12 +26,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.areArraysEquals = exports.filterExcluded = exports.duplicateItems = exports.getEnabledClients = exports.stripFields = exports.convertJsonToString = exports.flatten = exports.loadFileAndReplaceKeywords = exports.convertClientNamesToIds = exports.convertClientNameToId = exports.keywordReplace = exports.keywordStringReplace = exports.keywordArrayReplace = void 0;
|
|
29
|
+
exports.stripObfuscatedFieldsFromPayload = exports.obfuscateSensitiveValues = exports.areArraysEquals = exports.filterExcluded = exports.duplicateItems = exports.getEnabledClients = exports.stripFields = exports.convertJsonToString = exports.flatten = exports.loadFileAndReplaceKeywords = exports.convertClientNamesToIds = exports.convertClientNameToId = exports.keywordReplace = exports.keywordStringReplace = exports.keywordArrayReplace = void 0;
|
|
30
30
|
const path_1 = __importDefault(require("path"));
|
|
31
31
|
const fs_1 = __importStar(require("fs"));
|
|
32
32
|
const dot_prop_1 = __importDefault(require("dot-prop"));
|
|
33
33
|
const lodash_1 = __importDefault(require("lodash"));
|
|
34
|
-
const logger_1 = __importDefault(require("
|
|
34
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
35
|
+
const constants_1 = __importDefault(require("./constants"));
|
|
35
36
|
function keywordArrayReplace(input, mappings) {
|
|
36
37
|
Object.keys(mappings).forEach(function (key) {
|
|
37
38
|
// Matching against two sets of patterns because a developer may provide their array replacement keyword with or without wrapping quotes. It is not obvious to the developer which to do depending if they're operating in YAML or JSON.
|
|
@@ -175,3 +176,35 @@ function areArraysEquals(x, y) {
|
|
|
175
176
|
return lodash_1.default.isEqual(x && x.sort(), y && y.sort());
|
|
176
177
|
}
|
|
177
178
|
exports.areArraysEquals = areArraysEquals;
|
|
179
|
+
const obfuscateSensitiveValues = (data, sensitiveFieldsToObfuscate) => {
|
|
180
|
+
if (data === null)
|
|
181
|
+
return data;
|
|
182
|
+
if (Array.isArray(data)) {
|
|
183
|
+
return data.map((asset) => (0, exports.obfuscateSensitiveValues)(asset, sensitiveFieldsToObfuscate));
|
|
184
|
+
}
|
|
185
|
+
const newAsset = Object.assign({}, data);
|
|
186
|
+
sensitiveFieldsToObfuscate.forEach((sensitiveField) => {
|
|
187
|
+
if (dot_prop_1.default.get(newAsset, sensitiveField) !== undefined) {
|
|
188
|
+
dot_prop_1.default.set(newAsset, sensitiveField, constants_1.default.OBFUSCATED_SECRET_VALUE);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return newAsset;
|
|
192
|
+
};
|
|
193
|
+
exports.obfuscateSensitiveValues = obfuscateSensitiveValues;
|
|
194
|
+
// The reverse of `obfuscateSensitiveValues()`, preventing an obfuscated value from being passed to the API
|
|
195
|
+
const stripObfuscatedFieldsFromPayload = (data, obfuscatedFields) => {
|
|
196
|
+
if (data === null)
|
|
197
|
+
return data;
|
|
198
|
+
if (Array.isArray(data)) {
|
|
199
|
+
return data.map((asset) => (0, exports.stripObfuscatedFieldsFromPayload)(asset, obfuscatedFields));
|
|
200
|
+
}
|
|
201
|
+
const newAsset = Object.assign({}, data);
|
|
202
|
+
obfuscatedFields.forEach((sensitiveField) => {
|
|
203
|
+
const obfuscatedFieldValue = dot_prop_1.default.get(newAsset, sensitiveField);
|
|
204
|
+
if (obfuscatedFieldValue === constants_1.default.OBFUSCATED_SECRET_VALUE) {
|
|
205
|
+
dot_prop_1.default.delete(newAsset, sensitiveField);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
return newAsset;
|
|
209
|
+
};
|
|
210
|
+
exports.stripObfuscatedFieldsFromPayload = stripObfuscatedFieldsFromPayload;
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
declare type SharedPaginationParams = {
|
|
2
|
+
checkpoint?: boolean;
|
|
3
|
+
paginate?: boolean;
|
|
4
|
+
is_global?: boolean;
|
|
5
|
+
include_totals?: boolean;
|
|
6
|
+
id?: string;
|
|
7
|
+
strategy?: 'auth0';
|
|
8
|
+
};
|
|
9
|
+
export declare type CheckpointPaginationParams = SharedPaginationParams & {
|
|
10
|
+
from: string;
|
|
11
|
+
take: number;
|
|
12
|
+
};
|
|
13
|
+
export declare type PagePaginationParams = SharedPaginationParams & {
|
|
14
|
+
page: number;
|
|
15
|
+
per_page: number;
|
|
16
|
+
};
|
|
17
|
+
declare type APIClientBaseFunctions = {
|
|
18
|
+
getAll: (arg0: SharedPaginationParams) => Promise<Asset[]>;
|
|
19
|
+
create: (arg0: {
|
|
20
|
+
id: string;
|
|
21
|
+
}) => Promise<Asset>;
|
|
22
|
+
update: (arg0: {}, arg1: Asset) => Promise<Asset>;
|
|
23
|
+
delete: (arg0: Asset) => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
export declare type ApiResponse = {
|
|
26
|
+
start: number;
|
|
27
|
+
limit: number;
|
|
28
|
+
total: number;
|
|
29
|
+
next?: string;
|
|
30
|
+
} & {
|
|
31
|
+
[key in AssetTypes]: Asset[];
|
|
32
|
+
};
|
|
33
|
+
export declare type BaseAuth0APIClient = {
|
|
34
|
+
actions: APIClientBaseFunctions & {
|
|
35
|
+
deploy: ({ id: string }: {
|
|
36
|
+
id: any;
|
|
37
|
+
}) => Promise<void>;
|
|
38
|
+
getAllTriggers: () => Promise<{
|
|
39
|
+
triggers: Asset[];
|
|
40
|
+
}>;
|
|
41
|
+
getTriggerBindings: ({ trigger_id: string }: {
|
|
42
|
+
trigger_id: any;
|
|
43
|
+
}) => Promise<{
|
|
44
|
+
bindings: Asset[];
|
|
45
|
+
}>;
|
|
46
|
+
updateTriggerBindings: ({ trigger_id: string }: {
|
|
47
|
+
trigger_id: any;
|
|
48
|
+
}, { bindings: Object }: {
|
|
49
|
+
bindings: any;
|
|
50
|
+
}) => Promise<{
|
|
51
|
+
bindings: Asset[];
|
|
52
|
+
}>;
|
|
53
|
+
};
|
|
54
|
+
attackProtection: APIClientBaseFunctions & {
|
|
55
|
+
getBreachedPasswordDetectionConfig: () => Promise<Asset>;
|
|
56
|
+
getBruteForceConfig: () => Promise<Asset>;
|
|
57
|
+
getSuspiciousIpThrottlingConfig: () => Promise<Asset>;
|
|
58
|
+
updateBreachedPasswordDetectionConfig: ({}: {}, arg1: Asset) => Promise<void>;
|
|
59
|
+
updateSuspiciousIpThrottlingConfig: ({}: {}, arg1: Asset) => Promise<void>;
|
|
60
|
+
updateBruteForceConfig: ({}: {}, arg1: Asset) => Promise<void>;
|
|
61
|
+
};
|
|
62
|
+
branding: APIClientBaseFunctions & {
|
|
63
|
+
getSettings: () => Promise<Asset>;
|
|
64
|
+
getUniversalLoginTemplate: () => Promise<Asset>;
|
|
65
|
+
updateSettings: ({}: {}, Asset: any) => Promise<void>;
|
|
66
|
+
setUniversalLoginTemplate: ({}: {}, Asset: any) => Promise<void>;
|
|
67
|
+
};
|
|
68
|
+
clients: APIClientBaseFunctions;
|
|
69
|
+
clientGrants: APIClientBaseFunctions;
|
|
70
|
+
connections: APIClientBaseFunctions & {
|
|
71
|
+
get: (arg0: Asset) => Promise<Asset>;
|
|
72
|
+
getAll: (arg0: PagePaginationParams | CheckpointPaginationParams) => Promise<Asset[]>;
|
|
73
|
+
};
|
|
74
|
+
customDomains: APIClientBaseFunctions & {
|
|
75
|
+
getAll: () => Promise<Asset[]>;
|
|
76
|
+
};
|
|
77
|
+
emailProvider: APIClientBaseFunctions & {
|
|
78
|
+
delete: () => Promise<void>;
|
|
79
|
+
get: (arg0: Asset) => Promise<Asset>;
|
|
80
|
+
configure: (arg0: Object, arg1: Object) => Promise<Asset>;
|
|
81
|
+
};
|
|
82
|
+
emailTemplates: APIClientBaseFunctions & {
|
|
83
|
+
get: (arg0: Asset) => Promise<Asset>;
|
|
84
|
+
};
|
|
85
|
+
guardian: APIClientBaseFunctions & {
|
|
86
|
+
getFactorProvider: (arg0: Asset) => Promise<Asset>;
|
|
87
|
+
updateFactorProvider: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
88
|
+
getFactors: () => Promise<Asset[]>;
|
|
89
|
+
updateFactor: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
90
|
+
getPolicies: () => Promise<Asset[]>;
|
|
91
|
+
updatePolicies: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
92
|
+
getFactorTemplates: (arg0: {
|
|
93
|
+
name: string;
|
|
94
|
+
}) => Promise<Asset[]>;
|
|
95
|
+
updateFactorTemplates: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
96
|
+
updatePhoneFactorMessageTypes: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
97
|
+
getPhoneFactorSelectedProvider: () => Promise<Asset[]>;
|
|
98
|
+
getPhoneFactorMessageTypes: () => Promise<Asset[]>;
|
|
99
|
+
updatePhoneFactorSelectedProvider: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
100
|
+
};
|
|
101
|
+
hooks: APIClientBaseFunctions & {
|
|
102
|
+
get: ({ id: string }: {
|
|
103
|
+
id: any;
|
|
104
|
+
}) => Promise<Asset>;
|
|
105
|
+
removeSecrets: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
106
|
+
updateSecrets: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
107
|
+
getSecrets: ({ id: string }: {
|
|
108
|
+
id: any;
|
|
109
|
+
}) => Promise<Promise<Asset[]>>;
|
|
110
|
+
addSecrets: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
111
|
+
};
|
|
112
|
+
migrations: APIClientBaseFunctions & {
|
|
113
|
+
getMigrations: () => Promise<{
|
|
114
|
+
flags: Asset[];
|
|
115
|
+
}>;
|
|
116
|
+
updateMigrations: (arg0: {
|
|
117
|
+
flags: Asset[];
|
|
118
|
+
}) => Promise<void>;
|
|
119
|
+
};
|
|
120
|
+
organizations: APIClientBaseFunctions & {
|
|
121
|
+
updateEnabledConnection: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
122
|
+
addEnabledConnection: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
123
|
+
removeEnabledConnection: (arg0: Asset) => Promise<void>;
|
|
124
|
+
connections: {
|
|
125
|
+
get: (arg0: Asset) => Promise<Asset>;
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
prompts: APIClientBaseFunctions & {
|
|
129
|
+
getSettings: () => Promise<Asset[]>;
|
|
130
|
+
updateSettings: (arg0: {}, arg1: Asset) => Promise<void>;
|
|
131
|
+
};
|
|
132
|
+
resourceServers: APIClientBaseFunctions;
|
|
133
|
+
roles: APIClientBaseFunctions & {
|
|
134
|
+
permissions: APIClientBaseFunctions & {
|
|
135
|
+
delete: (arg0: {
|
|
136
|
+
id: string;
|
|
137
|
+
}, arg1: {
|
|
138
|
+
permissions: Asset[];
|
|
139
|
+
}) => Promise<void>;
|
|
140
|
+
create: (arg0: {
|
|
141
|
+
id: string;
|
|
142
|
+
}, arg1: {
|
|
143
|
+
permissions: Asset[];
|
|
144
|
+
}) => Promise<Asset>;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
rules: APIClientBaseFunctions;
|
|
148
|
+
rulesConfigs: APIClientBaseFunctions & {
|
|
149
|
+
getAll: () => Promise<Asset[]>;
|
|
150
|
+
};
|
|
151
|
+
tenant: APIClientBaseFunctions & {
|
|
152
|
+
getSettings: () => Promise<Asset>;
|
|
153
|
+
updateSettings: (arg0: Asset) => Promise<void>;
|
|
154
|
+
};
|
|
155
|
+
triggers: APIClientBaseFunctions & {
|
|
156
|
+
getTriggerBindings: () => Promise<Asset>;
|
|
157
|
+
};
|
|
158
|
+
updateRule: (arg0: {
|
|
159
|
+
id: string;
|
|
160
|
+
}, arg1: Asset) => Promise<Asset>;
|
|
161
|
+
};
|
|
162
|
+
export declare type Auth0APIClient = BaseAuth0APIClient & {
|
|
163
|
+
pool: {
|
|
164
|
+
addSingleTask: (arg0: {
|
|
165
|
+
data: Object;
|
|
166
|
+
generator: any;
|
|
167
|
+
}) => {
|
|
168
|
+
promise: () => Promise<ApiResponse>;
|
|
169
|
+
};
|
|
170
|
+
addEachTask: (arg0: {
|
|
171
|
+
data: Object;
|
|
172
|
+
generator: any;
|
|
173
|
+
}) => {
|
|
174
|
+
promise: () => Promise<Asset[][]>;
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
export declare type Config = {
|
|
179
|
+
AUTH0_DOMAIN: string;
|
|
180
|
+
AUTH0_CLIENT_ID: string;
|
|
181
|
+
AUTH0_CLIENT_SECRET: string;
|
|
182
|
+
AUTH0_INPUT_FILE: string;
|
|
183
|
+
AUTH0_ALLOW_DELETE: boolean;
|
|
184
|
+
AUTH0_EXCLUDED: AssetTypes[];
|
|
185
|
+
EXTENSION_SECRET: string;
|
|
186
|
+
AUTH0_ACCESS_TOKEN?: string;
|
|
187
|
+
AUTH0_BASE_PATH?: string;
|
|
188
|
+
AUTH0_AUDIENCE?: string;
|
|
189
|
+
AUTH0_API_MAX_RETRIES?: number;
|
|
190
|
+
AUTH0_KEYWORD_REPLACE_MAPPINGS?: KeywordMappings;
|
|
191
|
+
AUTH0_EXPORT_IDENTIFIERS?: boolean;
|
|
192
|
+
AUTH0_CONNECTIONS_DIRECTORY?: string;
|
|
193
|
+
EXCLUDED_PROPS?: {
|
|
194
|
+
[key: string]: string[];
|
|
195
|
+
};
|
|
196
|
+
INCLUDED_PROPS?: {
|
|
197
|
+
[key: string]: string[];
|
|
198
|
+
};
|
|
199
|
+
AUTH0_IGNORE_UNAVAILABLE_MIGRATIONS?: boolean;
|
|
200
|
+
AUTH0_EXCLUDED_RULES?: string[];
|
|
201
|
+
AUTH0_EXCLUDED_CLIENTS?: string[];
|
|
202
|
+
AUTH0_EXCLUDED_DATABASES?: string[];
|
|
203
|
+
AUTH0_EXCLUDED_CONNECTIONS?: string[];
|
|
204
|
+
AUTH0_EXCLUDED_RESOURCE_SERVERS?: string[];
|
|
205
|
+
AUTH0_EXCLUDED_DEFAULTS?: string[];
|
|
206
|
+
};
|
|
207
|
+
export declare type Asset = {
|
|
208
|
+
[key: string]: any;
|
|
209
|
+
};
|
|
210
|
+
export declare type Assets = {
|
|
211
|
+
actions: Asset[];
|
|
212
|
+
attackProtection: Asset;
|
|
213
|
+
branding: Asset;
|
|
214
|
+
clients: Asset[];
|
|
215
|
+
clientGrants: Asset[];
|
|
216
|
+
connections: Asset[];
|
|
217
|
+
databases: Asset[];
|
|
218
|
+
emailProvider: Asset;
|
|
219
|
+
emailTemplates: Asset[];
|
|
220
|
+
guardianFactorProviders: Asset[];
|
|
221
|
+
guardianFactors: Asset[];
|
|
222
|
+
guardianFactorTemplates: Asset[];
|
|
223
|
+
guardianPhoneFactorMessageTypes: {
|
|
224
|
+
message_types: Asset[];
|
|
225
|
+
};
|
|
226
|
+
guardianPhoneFactorSelectedProvider: Asset;
|
|
227
|
+
guardianPolicies: {
|
|
228
|
+
policies: Asset[];
|
|
229
|
+
};
|
|
230
|
+
hooks: Asset[];
|
|
231
|
+
migrations: Asset[];
|
|
232
|
+
organizations: Asset[];
|
|
233
|
+
pages: Asset[];
|
|
234
|
+
resourceServers: Asset[];
|
|
235
|
+
roles: Asset[];
|
|
236
|
+
rules: Asset[];
|
|
237
|
+
rulesConfigs: Asset[];
|
|
238
|
+
tenant: Asset;
|
|
239
|
+
triggers: Asset[];
|
|
240
|
+
exclude?: {
|
|
241
|
+
[key: string]: string[];
|
|
242
|
+
};
|
|
243
|
+
clientsOrig: Asset[];
|
|
244
|
+
};
|
|
245
|
+
export declare type CalculatedChanges = {
|
|
246
|
+
del: Asset[];
|
|
247
|
+
update: Asset[];
|
|
248
|
+
conflicts: Asset[];
|
|
249
|
+
create: Asset[];
|
|
250
|
+
};
|
|
251
|
+
export declare type AssetTypes = 'rules' | 'rulesConfigs' | 'hooks' | 'pages' | 'databases' | 'clientGrants' | 'resourceServers' | 'clients' | 'connections' | 'tenant' | 'emailProvider' | 'emailTemplates' | 'guardianFactors' | 'guardianFactorProviders' | 'guardianFactorTemplates' | 'migrations' | 'guardianPhoneFactorMessageTypes' | 'guardianPhoneFactorSelectedProvider' | 'guardianPolicies' | 'roles' | 'actions' | 'organizations' | 'triggers' | 'attackProtection' | 'branding';
|
|
252
|
+
export declare type KeywordMappings = {
|
|
253
|
+
[key: string]: (string | number)[] | string | number;
|
|
254
|
+
};
|
|
255
|
+
export {};
|