auth0-deploy-cli 7.12.3 → 7.14.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/.circleci/config.yml +2 -0
- package/.github/dependabot.yml +3 -0
- package/CHANGELOG.md +37 -1
- package/README.md +121 -65
- package/docs/available-resource-config-formats.md +19 -0
- package/docs/configuring-the-deploy-cli.md +140 -0
- package/docs/excluding-from-management.md +81 -0
- package/docs/how-to-contribute.md +49 -0
- package/docs/keyword-replacement.md +45 -0
- package/docs/multi-environment-workflow.md +98 -0
- package/docs/terraform-provider.md +20 -0
- package/docs/using-as-cli.md +89 -0
- package/docs/using-as-node-module.md +114 -0
- package/lib/commands/import.d.ts +2 -0
- package/lib/commands/import.js +36 -1
- package/lib/context/directory/handlers/index.js +2 -0
- package/lib/context/directory/handlers/themes.d.ts +6 -0
- package/lib/context/directory/handlers/themes.js +48 -0
- package/lib/context/yaml/handlers/index.js +2 -0
- package/lib/context/yaml/handlers/pages.js +1 -1
- package/lib/context/yaml/handlers/themes.d.ts +6 -0
- package/lib/context/yaml/handlers/themes.js +26 -0
- package/lib/index.d.ts +1 -0
- package/lib/tools/auth0/handlers/index.d.ts +5 -0
- package/lib/tools/auth0/handlers/index.js +2 -0
- package/lib/tools/auth0/handlers/prompts.js +5 -2
- package/lib/tools/auth0/handlers/tenant.d.ts +12 -1
- package/lib/tools/auth0/handlers/tenant.js +39 -4
- package/lib/tools/auth0/handlers/themes.d.ts +455 -0
- package/lib/tools/auth0/handlers/themes.js +500 -0
- package/lib/tools/constants.d.ts +1 -0
- package/lib/tools/constants.js +1 -0
- package/lib/tools/index.d.ts +1 -0
- package/lib/tools/utils.d.ts +1 -1
- package/lib/tools/utils.js +2 -0
- package/lib/types.d.ts +15 -6
- package/lib/utils.d.ts +2 -1
- package/package.json +4 -4
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Incorporating Into Multi-environment Workflows
|
|
2
|
+
|
|
3
|
+
The Deploy CLI supports working within a multi-tenant, multi-environment context. When integrated into your CI/CD development workflows, can be used to propagate Auth0 changes from feature development all the way through production.
|
|
4
|
+
|
|
5
|
+
In general, the advised workflow is as follows:
|
|
6
|
+
|
|
7
|
+
- Create a separate Auth0 tenant for each environment (ex: dev, staging, prod)
|
|
8
|
+
- Create a single repository of resource configuration files for all environments
|
|
9
|
+
- Add a step in your CI/CD pipeline when deploying to environments that applies the Auth0 resource configurations to the appropriate Auth0 tenant
|
|
10
|
+
|
|
11
|
+
## Tenant to Environment
|
|
12
|
+
|
|
13
|
+
It is recommended to have a separate Auth0 tenant/account for each environment you have. For example:
|
|
14
|
+
|
|
15
|
+
| Environment | Tenant |
|
|
16
|
+
| ----------- | ------------- |
|
|
17
|
+
| Development | travel0-dev |
|
|
18
|
+
| Testing | travel0-uat |
|
|
19
|
+
| Staging | travel0-stage |
|
|
20
|
+
| Production | travel0-prod |
|
|
21
|
+
|
|
22
|
+
## Resource configuration repository
|
|
23
|
+
|
|
24
|
+
When exported, your Auth0 tenant state will be represented as a set of resource configuration files, either in a [YAML or JSON format](./available-resource-config-formats.md). In a multi-environment context it is expected to have a single repository of resource configurations that is applied to all environments. In practice, this may exist as a directory in your project’s codebase or in a separate codebase altogether.
|
|
25
|
+
|
|
26
|
+
You should have at least one branch for each tenant in your repository, which allows you to make changes without deploying them (the changes would only deploy when you merged your branch into the master, or primary, branch). With this setup, you can have a continuous integration task for each environment that automatically deploys changes to the targeted environment whenever the master branch receives updates.
|
|
27
|
+
|
|
28
|
+
Your workflow could potentially look something like this:
|
|
29
|
+
|
|
30
|
+
1. Make changes to development.
|
|
31
|
+
2. Merge changes to testing (or `uat`).
|
|
32
|
+
3. Test changes to `uat`. When ready, move and merge the changes to `staging`.
|
|
33
|
+
4. Test `staging`. When ready, move and merge the changes to `production`.
|
|
34
|
+
|
|
35
|
+
You may want to set your production environment to deploy only when triggered manually.
|
|
36
|
+
|
|
37
|
+
## Uni-directional Flow
|
|
38
|
+
|
|
39
|
+
The multi-environment workflow works best when changes are propagated “up” in a single direction. Changes to the resource configuration files should first be applied to the lowest level environment (ex: dev) and then incrementally applied up through all other environments until applied to production. This uni-directional practice ensures sufficient testing and approval for changes to your tenant. Once set, it is recommended to not apply configurations directly to production through other means such as the Auth0 Dashboard or Management API unless those changes are captured by a subsequent Deploy CLI export. Otherwise, those changes are subject to overwrite.
|
|
40
|
+
|
|
41
|
+
## Environment-specific values
|
|
42
|
+
|
|
43
|
+
While it is expected that all environments will share the same set of resource configuration files, environment-specific values can be expressed through separate tool configuration files and dynamic [keyword replacement](keyword-replacement.md).
|
|
44
|
+
|
|
45
|
+
### Separate Config Files
|
|
46
|
+
|
|
47
|
+
Specifying a separate tool configuration file per environment can be used to keep the resource configuration files agnostic of environment but still cater for the needs of each environment. At a minimum, you will need to provide separate credentials for each environment, but it is also possible to exclude certain resources, enable deletion and perform dynamic keyword replacement on a per-environment basis.
|
|
48
|
+
|
|
49
|
+
### Example file structure
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
project-root
|
|
53
|
+
│
|
|
54
|
+
└───auth0
|
|
55
|
+
│ │ config-dev.json # Dev env config file
|
|
56
|
+
│ │ config-test.json # Test env config file
|
|
57
|
+
│ │ config-prod.json # Prod env config file
|
|
58
|
+
│ │ ... all other resource configuration files
|
|
59
|
+
│
|
|
60
|
+
└───src
|
|
61
|
+
│ ... your project code
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Dynamic Values via Keyword Replacement
|
|
65
|
+
|
|
66
|
+
Once separate configurations files are adopted for each environment, keyword replacement via the `AUTH0_KEYWORD_REPLACE_MAPPINGS` configuration property can be used to express the dynamic replacement values depending on the environment. For example, you may find it necessary to have a separate set of allowed origins for your clients (see below). To learn more, see [Keyword Replacement](keyword-replacement.md).
|
|
67
|
+
|
|
68
|
+
#### Example `config-dev.json`
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"AUTH0_DOMAIN": "travel0-dev.us.auth0.com",
|
|
73
|
+
"AUTH0_CLIENT_ID": "PdwQpGy62sHcsV6ufZNEVrV4GDlDhm74",
|
|
74
|
+
"AUTH0_ALLOW_DELETE": true,
|
|
75
|
+
"AUTH0_KEYWORD_REPLACE_MAPPINGS": {
|
|
76
|
+
"ENV": "dev",
|
|
77
|
+
"ALLOWED_ORIGINS": ["http://localhost:3000", "http://dev.travel0.com"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Example `config-prod.json`
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"AUTH0_DOMAIN": "travel0.us.auth0.com",
|
|
87
|
+
"AUTH0_CLIENT_ID": "vZCEFsDYzXc1x9IomB8dF185e4cdVah5",
|
|
88
|
+
"AUTH0_ALLOW_DELETE": false,
|
|
89
|
+
"AUTH0_KEYWORD_REPLACE_MAPPINGS": {
|
|
90
|
+
"ENV": "prod",
|
|
91
|
+
"ALLOWED_ORIGINS": ["http://travel0.com"]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
[[table of contents]](../README.md#documentation)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Auth0 Terraform Provider
|
|
2
|
+
|
|
3
|
+
The Deploy CLI is not the only tool available for managing your Auth0 tenant configuration, there is also an [officially supported Terraform Provider](https://github.com/auth0/terraform-provider-auth0). [Terraform](https://terraform.io/) is a third-party tool for representing your cloud resources’s configurations as code. It has an established plug-in framework that supports a wide array of cloud providers, including Auth0.
|
|
4
|
+
|
|
5
|
+
Both the Deploy CLI and Terraform Provider exist to help you manage your Auth0 tenant configurations, but each has their own set of pros and cons.
|
|
6
|
+
|
|
7
|
+
You may want to consider the Auth0 Terraform Provider if:
|
|
8
|
+
|
|
9
|
+
- Your development workflows already leverages Terraform
|
|
10
|
+
- Your tenant management needs are granular or only pertain to a few specific resources
|
|
11
|
+
|
|
12
|
+
You may **not** want to consider the Auth0 Terraform Provider if:
|
|
13
|
+
|
|
14
|
+
- Your development workflow does not use Terraform, requiring extra setup upfront
|
|
15
|
+
- Your development workflows are primarily concerned with managing your tenants in bulk
|
|
16
|
+
- Your tenant has lots of existing resources, may require significant effort to “import”
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
[[table of contents]](../README.md#documentation)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Using as a CLI
|
|
2
|
+
|
|
3
|
+
The Deploy CLI can be used as a standalone command line utility. Doing so provides a simple way to manage your Auth0 tenant configuration in CI/CD workflows.
|
|
4
|
+
|
|
5
|
+
## `export` command
|
|
6
|
+
|
|
7
|
+
Fetching configurations from Auth0 tenant to the local machine.
|
|
8
|
+
|
|
9
|
+
### `--output_folder`, `-o`
|
|
10
|
+
|
|
11
|
+
Path. Specifies the target directory for configuration files to be written to.
|
|
12
|
+
|
|
13
|
+
### `--config_file`, `-c`
|
|
14
|
+
|
|
15
|
+
Path. Specifies the user-defined configuration file (`config.json`). Refer to the list of [all configurable properties](./configuring-the-deploy-cli.md).
|
|
16
|
+
|
|
17
|
+
### `--format`, `-f`
|
|
18
|
+
|
|
19
|
+
Options: yaml or directory. Determines the file format of the exported resource configuration files. See: [Available Resource Config Formats](available-resource-config-formats).
|
|
20
|
+
|
|
21
|
+
### `--export_ids`, `-e`
|
|
22
|
+
|
|
23
|
+
Boolean. When enabled, will export the identifier fields for each resource. Default: `false`.
|
|
24
|
+
|
|
25
|
+
### `--env`
|
|
26
|
+
|
|
27
|
+
Boolean. Indicates if the tool should ingest environment variables or not. Default: `true`.
|
|
28
|
+
|
|
29
|
+
### `--debug`
|
|
30
|
+
|
|
31
|
+
Boolean. Enables more verbose error logging; useful during troubleshooting. Default: `false`.
|
|
32
|
+
|
|
33
|
+
### `--proxy_url`, `-p`
|
|
34
|
+
|
|
35
|
+
A url for proxying requests. Only set this if you are behind a proxy.
|
|
36
|
+
|
|
37
|
+
### Examples
|
|
38
|
+
|
|
39
|
+
```shell
|
|
40
|
+
# Fetching Auth0 tenant configuration in the YAML format
|
|
41
|
+
a0deploy export -c=config.json --format=yaml --output_folder=local
|
|
42
|
+
|
|
43
|
+
# Fetching Auth0 tenant configuration in directory (JSON) format
|
|
44
|
+
a0deploy export -c=config.json --format=directory --output_folder=local
|
|
45
|
+
|
|
46
|
+
# Fetching Auth0 tenant configurations with IDs of all assets
|
|
47
|
+
a0deploy export -c=config.json --format=yaml --output_folder=local --export_ids=true
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## `import` command
|
|
51
|
+
|
|
52
|
+
Applying configurations from local machine to Auth0 tenant.
|
|
53
|
+
|
|
54
|
+
### `--input_file`, `-i`
|
|
55
|
+
|
|
56
|
+
Path. Specifies the location of the resource configuration files. For YAML formats, this will point to the `tenant.yaml` file, for directory formats, this will point to the resource configuration directory.
|
|
57
|
+
|
|
58
|
+
### `--config_file`, `-c`
|
|
59
|
+
|
|
60
|
+
Path. Specifies the user-defined configuration file (config.json). Refer to the list of [all configurable properties](./configuring-the-deploy-cli.md).
|
|
61
|
+
|
|
62
|
+
### `--env`
|
|
63
|
+
|
|
64
|
+
Boolean. Indicates if the tool should ingest environment variables or not. Default: `true`.
|
|
65
|
+
|
|
66
|
+
### `--proxy_url`, `-p`
|
|
67
|
+
|
|
68
|
+
A url for proxying requests. Only set this if you are behind a proxy.
|
|
69
|
+
|
|
70
|
+
### `--debug`
|
|
71
|
+
|
|
72
|
+
Boolean. Enables more verbose error logging; useful during troubleshooting. Default: `false`.
|
|
73
|
+
|
|
74
|
+
### Examples
|
|
75
|
+
|
|
76
|
+
```shell
|
|
77
|
+
# Deploying configuration for YAML formats
|
|
78
|
+
a0deploy import -c=config.json --input_file=local/tenant.yaml
|
|
79
|
+
|
|
80
|
+
# Deploying configuration for directory format
|
|
81
|
+
a0deploy import -c=config.json --input_file=local
|
|
82
|
+
|
|
83
|
+
# Deploying configuration with environment variables ignored
|
|
84
|
+
a0deploy import -c=config.json --input_file=local/tenant.yaml --env=false
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
[[table of contents]](../README.md#documentation)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Using as a Node Module
|
|
2
|
+
|
|
3
|
+
The Deploy CLI can not only be used as a standalone CLI, but as a node module. Doing so allows you to manage Auth0 resources within expressive node scripts.
|
|
4
|
+
|
|
5
|
+
## `dump` function
|
|
6
|
+
|
|
7
|
+
Fetches configurations from Auth0 tenant to the local machine.
|
|
8
|
+
|
|
9
|
+
### Example
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { dump } from 'auth0-deploy-cli';
|
|
13
|
+
|
|
14
|
+
dump({
|
|
15
|
+
output_folder: './local',
|
|
16
|
+
format: 'yaml',
|
|
17
|
+
config: {
|
|
18
|
+
AUTH0_DOMAIN: '<YOUR_AUTH0_TENANT_DOMAIN>',
|
|
19
|
+
AUTH0_CLIENT_ID: '<YOUR_AUTH0_CLIENT_ID>',
|
|
20
|
+
AUTH0_CLIENT_SECRET: '<YOUR_AUTH0_CLIENT_SECRET>',
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
.then(() => {
|
|
24
|
+
console.log('Auth0 configuration export successful');
|
|
25
|
+
})
|
|
26
|
+
.catch((err) => {
|
|
27
|
+
console.log('Error during Auth0 configuration export:', err);
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Argument parameters
|
|
32
|
+
|
|
33
|
+
#### `format`
|
|
34
|
+
|
|
35
|
+
Options: `yaml` or `directory`. Determines the file format of the exported resource configuration files. See: [Available Resource Configuration Formats](available-resource-config-formats).
|
|
36
|
+
|
|
37
|
+
#### `output_folder`
|
|
38
|
+
|
|
39
|
+
Path. Specifies the target directory for configuration files to be written to.
|
|
40
|
+
|
|
41
|
+
#### `config`
|
|
42
|
+
|
|
43
|
+
Object. Configures behavior of utility. Refer to the list of [all configurable properties](./configuring-the-deploy-cli.md).
|
|
44
|
+
|
|
45
|
+
#### `config_file`
|
|
46
|
+
|
|
47
|
+
Path. Specifies the user-defined configuration file (config.json). Refer to the list of [all configurable properties](./configuring-the-deploy-cli.md).
|
|
48
|
+
|
|
49
|
+
#### `export_ids`
|
|
50
|
+
|
|
51
|
+
Boolean: When enabled, will export the identifier fields for each resource. Default: false.
|
|
52
|
+
|
|
53
|
+
#### `env`
|
|
54
|
+
|
|
55
|
+
Boolean. Indicates if the tool should ingest environment variables or not. Default: `false`.
|
|
56
|
+
|
|
57
|
+
#### `proxy_url`
|
|
58
|
+
|
|
59
|
+
A url for proxying requests. Only set this if you are behind a proxy.
|
|
60
|
+
|
|
61
|
+
## `deploy` function
|
|
62
|
+
|
|
63
|
+
Applies configurations from local machine to Auth0 tenant.
|
|
64
|
+
|
|
65
|
+
### Argument parameters
|
|
66
|
+
|
|
67
|
+
#### `input_file`
|
|
68
|
+
|
|
69
|
+
Path. Specifies the location of the resource configuration files. For YAML formats, this will point to the tenant.yaml file. For directory formats, this will point to the resource configuration directory.
|
|
70
|
+
|
|
71
|
+
#### `config`
|
|
72
|
+
|
|
73
|
+
Object. Configures behavior of utility. Refer to the list of [all configurable properties](./configuring-the-deploy-cli.md).
|
|
74
|
+
|
|
75
|
+
#### `config_file`
|
|
76
|
+
|
|
77
|
+
Path. Specifies the user-defined configuration file (config.json). Refer to the list of [all configurable properties](./configuring-the-deploy-cli.md).
|
|
78
|
+
|
|
79
|
+
#### `export_ids`
|
|
80
|
+
|
|
81
|
+
Boolean: When enabled, will export the identifier fields for each resource. Default: `false`.
|
|
82
|
+
|
|
83
|
+
#### `env`
|
|
84
|
+
|
|
85
|
+
Boolean. Indicates if the tool should ingest environment variables or not. Default: `false`.
|
|
86
|
+
|
|
87
|
+
#### `proxy_url`
|
|
88
|
+
|
|
89
|
+
A url for proxying requests. Only set this if you are behind a proxy.
|
|
90
|
+
|
|
91
|
+
### Example
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { deploy } from 'auth0-deploy-cli';
|
|
95
|
+
|
|
96
|
+
deploy({
|
|
97
|
+
input_file: './local/tenant.yaml',
|
|
98
|
+
config: {
|
|
99
|
+
AUTH0_DOMAIN: '<YOUR_AUTH0_TENANT_DOMAIN>',
|
|
100
|
+
AUTH0_CLIENT_ID: '<YOUR_AUTH0_CLIENT_ID>',
|
|
101
|
+
AUTH0_CLIENT_SECRET: '<YOUR_AUTH0_CLIENT_SECRET>',
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
.then(() => {
|
|
105
|
+
console.log('Auth0 configuration applied to tenant successful');
|
|
106
|
+
})
|
|
107
|
+
.catch((err) => {
|
|
108
|
+
console.log('Error when applying configuration to Auth0 tenant:', err);
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
[[table of contents]](../README.md#documentation)
|
package/lib/commands/import.d.ts
CHANGED
package/lib/commands/import.js
CHANGED
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.findUnreplacedKeywords = void 0;
|
|
15
16
|
const nconf_1 = __importDefault(require("nconf"));
|
|
16
17
|
const configFactory_1 = require("../configFactory");
|
|
17
18
|
const tools_1 = require("../tools");
|
|
@@ -40,9 +41,43 @@ function importCMD(params) {
|
|
|
40
41
|
yield context.load();
|
|
41
42
|
const config = (0, configFactory_1.configFactory)();
|
|
42
43
|
config.setProvider((key) => nconf_1.default.get(key));
|
|
43
|
-
|
|
44
|
+
(0, exports.findUnreplacedKeywords)(context.assets);
|
|
44
45
|
yield (0, tools_1.deploy)(context.assets, context.mgmtClient, config);
|
|
45
46
|
logger_1.default.info('Import Successful');
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
49
|
exports.default = importCMD;
|
|
50
|
+
const findUnreplacedKeywords = (assets) => {
|
|
51
|
+
const recursiveFindUnreplacedKeywords = (target) => {
|
|
52
|
+
let unreplaced = [];
|
|
53
|
+
if (target === undefined || target === null)
|
|
54
|
+
return [];
|
|
55
|
+
if (Array.isArray(target)) {
|
|
56
|
+
target.forEach((child) => {
|
|
57
|
+
unreplaced.push(...recursiveFindUnreplacedKeywords(child));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else if (typeof target === 'object') {
|
|
61
|
+
Object.values(target).forEach((child) => {
|
|
62
|
+
unreplaced.push(...recursiveFindUnreplacedKeywords(child));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (typeof target === 'string') {
|
|
66
|
+
const arrayMatches = target.match(/(?<=@@).*(?=@@)/g);
|
|
67
|
+
if (arrayMatches !== null) {
|
|
68
|
+
return arrayMatches;
|
|
69
|
+
}
|
|
70
|
+
const keywordMatches = target.match(/(?<=##).*(?=##)/g);
|
|
71
|
+
if (keywordMatches !== null) {
|
|
72
|
+
return keywordMatches;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return unreplaced;
|
|
76
|
+
};
|
|
77
|
+
const unreplacedKeywords = recursiveFindUnreplacedKeywords(assets);
|
|
78
|
+
if (unreplacedKeywords.length > 0) {
|
|
79
|
+
throw `Unreplaced keywords found: ${unreplacedKeywords.join(', ')}. Either correct these values or add to AUTH0_KEYWORD_REPLACE_MAPPINGS configuration.`;
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
};
|
|
83
|
+
exports.findUnreplacedKeywords = findUnreplacedKeywords;
|
|
@@ -31,6 +31,7 @@ const branding_1 = __importDefault(require("./branding"));
|
|
|
31
31
|
const logStreams_1 = __importDefault(require("./logStreams"));
|
|
32
32
|
const prompts_1 = __importDefault(require("./prompts"));
|
|
33
33
|
const customDomains_1 = __importDefault(require("./customDomains"));
|
|
34
|
+
const themes_1 = __importDefault(require("./themes"));
|
|
34
35
|
const directoryHandlers = {
|
|
35
36
|
rules: rules_1.default,
|
|
36
37
|
rulesConfigs: rulesConfigs_1.default,
|
|
@@ -60,5 +61,6 @@ const directoryHandlers = {
|
|
|
60
61
|
logStreams: logStreams_1.default,
|
|
61
62
|
prompts: prompts_1.default,
|
|
62
63
|
customDomains: customDomains_1.default,
|
|
64
|
+
themes: themes_1.default,
|
|
63
65
|
};
|
|
64
66
|
exports.default = directoryHandlers;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DirectoryHandler } from '.';
|
|
2
|
+
import { ParsedAsset } from '../../../types';
|
|
3
|
+
import { Theme } from '../../../tools/auth0/handlers/themes';
|
|
4
|
+
declare type ParsedThemes = ParsedAsset<'themes', Theme[]>;
|
|
5
|
+
declare const themesHandler: DirectoryHandler<ParsedThemes>;
|
|
6
|
+
export default themesHandler;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const fs_extra_1 = require("fs-extra");
|
|
17
|
+
const utils_1 = require("../../../utils");
|
|
18
|
+
const tools_1 = require("../../../tools");
|
|
19
|
+
function parse(context) {
|
|
20
|
+
const baseFolder = path_1.default.join(context.filePath, tools_1.constants.THEMES_DIRECTORY);
|
|
21
|
+
if (!(0, utils_1.existsMustBeDir)(baseFolder)) {
|
|
22
|
+
return { themes: null };
|
|
23
|
+
}
|
|
24
|
+
const themeDefinitionsFiles = (0, utils_1.getFiles)(baseFolder, ['.json']);
|
|
25
|
+
if (!themeDefinitionsFiles.length) {
|
|
26
|
+
return { themes: [] };
|
|
27
|
+
}
|
|
28
|
+
const themes = themeDefinitionsFiles.map((themeDefinitionsFile) => (0, utils_1.loadJSON)(themeDefinitionsFile, context.mappings));
|
|
29
|
+
return { themes };
|
|
30
|
+
}
|
|
31
|
+
function dump(context) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const { themes } = context.assets;
|
|
34
|
+
if (!themes) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const baseFolder = path_1.default.join(context.filePath, tools_1.constants.THEMES_DIRECTORY);
|
|
38
|
+
(0, fs_extra_1.ensureDirSync)(baseFolder);
|
|
39
|
+
themes.forEach((themeDefinition, i) => {
|
|
40
|
+
(0, utils_1.dumpJSON)(path_1.default.join(baseFolder, `theme${i ? i : ''}.json`), themeDefinition);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const themesHandler = {
|
|
45
|
+
parse,
|
|
46
|
+
dump,
|
|
47
|
+
};
|
|
48
|
+
exports.default = themesHandler;
|
|
@@ -31,6 +31,7 @@ const branding_1 = __importDefault(require("./branding"));
|
|
|
31
31
|
const logStreams_1 = __importDefault(require("./logStreams"));
|
|
32
32
|
const prompts_1 = __importDefault(require("./prompts"));
|
|
33
33
|
const customDomains_1 = __importDefault(require("./customDomains"));
|
|
34
|
+
const themes_1 = __importDefault(require("./themes"));
|
|
34
35
|
const yamlHandlers = {
|
|
35
36
|
rules: rules_1.default,
|
|
36
37
|
hooks: hooks_1.default,
|
|
@@ -60,5 +61,6 @@ const yamlHandlers = {
|
|
|
60
61
|
logStreams: logStreams_1.default,
|
|
61
62
|
prompts: prompts_1.default,
|
|
62
63
|
customDomains: customDomains_1.default,
|
|
64
|
+
themes: themes_1.default,
|
|
63
65
|
};
|
|
64
66
|
exports.default = yamlHandlers;
|
|
@@ -44,7 +44,7 @@ function dump(context) {
|
|
|
44
44
|
// Dump html to file
|
|
45
45
|
const htmlFile = path_1.default.join(pagesFolder, `${page.name}.html`);
|
|
46
46
|
logger_1.default.info(`Writing ${htmlFile}`);
|
|
47
|
-
fs_extra_1.default.writeFileSync(htmlFile, page.html);
|
|
47
|
+
fs_extra_1.default.writeFileSync(htmlFile, page.html || '');
|
|
48
48
|
return Object.assign(Object.assign({}, page), { html: `./pages/${page.name}.html` });
|
|
49
49
|
});
|
|
50
50
|
return { pages };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { YAMLHandler } from '.';
|
|
2
|
+
import { ParsedAsset } from '../../../types';
|
|
3
|
+
import { Theme } from '../../../tools/auth0/handlers/themes';
|
|
4
|
+
declare type ParsedThemes = ParsedAsset<'themes', Theme[]>;
|
|
5
|
+
declare const themesHandler: YAMLHandler<ParsedThemes>;
|
|
6
|
+
export default themesHandler;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
function parseAndDump(context) {
|
|
13
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
const { themes } = context.assets;
|
|
15
|
+
if (!themes)
|
|
16
|
+
return { themes: null };
|
|
17
|
+
return {
|
|
18
|
+
themes,
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const themesHandler = {
|
|
23
|
+
parse: parseAndDump,
|
|
24
|
+
dump: parseAndDump,
|
|
25
|
+
};
|
|
26
|
+
exports.default = themesHandler;
|
package/lib/index.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ declare const _default: {
|
|
|
79
79
|
LOG_STREAMS_DIRECTORY: string;
|
|
80
80
|
PROMPTS_DIRECTORY: string;
|
|
81
81
|
CUSTOM_DOMAINS_DIRECTORY: string;
|
|
82
|
+
THEMES_DIRECTORY: string;
|
|
82
83
|
};
|
|
83
84
|
deploy: typeof import("./tools").deploy;
|
|
84
85
|
keywordReplace: typeof import("./tools").keywordReplace;
|
|
@@ -52,6 +52,7 @@ const organizations = __importStar(require("./organizations"));
|
|
|
52
52
|
const attackProtection = __importStar(require("./attackProtection"));
|
|
53
53
|
const logStreams = __importStar(require("./logStreams"));
|
|
54
54
|
const customDomains = __importStar(require("./customDomains"));
|
|
55
|
+
const themes = __importStar(require("./themes"));
|
|
55
56
|
const auth0ApiHandlers = {
|
|
56
57
|
rules,
|
|
57
58
|
rulesConfigs,
|
|
@@ -82,5 +83,6 @@ const auth0ApiHandlers = {
|
|
|
82
83
|
attackProtection,
|
|
83
84
|
logStreams,
|
|
84
85
|
customDomains,
|
|
86
|
+
themes,
|
|
85
87
|
};
|
|
86
88
|
exports.default = auth0ApiHandlers; // TODO: apply stronger types to schema properties
|
|
@@ -164,7 +164,8 @@ class PromptsHandler extends default_1.default {
|
|
|
164
164
|
const supportedLanguages = yield this.client.tenant
|
|
165
165
|
.getSettings()
|
|
166
166
|
.then(({ enabled_locales }) => enabled_locales);
|
|
167
|
-
const data = yield Promise.all(supportedLanguages
|
|
167
|
+
const data = yield Promise.all(supportedLanguages
|
|
168
|
+
.map((language) => {
|
|
168
169
|
return promptTypes.map((promptType) => {
|
|
169
170
|
return this.client.prompts
|
|
170
171
|
.getCustomTextByLanguage({
|
|
@@ -180,7 +181,9 @@ class PromptsHandler extends default_1.default {
|
|
|
180
181
|
};
|
|
181
182
|
});
|
|
182
183
|
});
|
|
183
|
-
})
|
|
184
|
+
})
|
|
185
|
+
.reduce((acc, val) => acc.concat(val), []) // TODO: replace .map().reduce() with .flatMap() once we officially eliminate Node v10 support
|
|
186
|
+
).then((customTextData) => {
|
|
184
187
|
return customTextData
|
|
185
188
|
.filter((customTextData) => {
|
|
186
189
|
return customTextData !== null;
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import DefaultHandler from './default';
|
|
2
|
-
import { Asset, Assets } from '../../../types';
|
|
2
|
+
import { Asset, Assets, Language } from '../../../types';
|
|
3
3
|
export declare const schema: {
|
|
4
4
|
type: string;
|
|
5
5
|
};
|
|
6
|
+
export declare type Tenant = Asset & {
|
|
7
|
+
enabled_locales: Language[];
|
|
8
|
+
flags: {
|
|
9
|
+
[key: string]: boolean;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
6
12
|
export default class TenantHandler extends DefaultHandler {
|
|
13
|
+
existing: Tenant;
|
|
7
14
|
constructor(options: DefaultHandler);
|
|
8
15
|
getType(): Promise<Asset>;
|
|
9
16
|
validate(assets: Assets): Promise<void>;
|
|
10
17
|
processChanges(assets: Assets): Promise<void>;
|
|
11
18
|
}
|
|
19
|
+
export declare const sanitizeMigrationFlags: ({ existingFlags, proposedFlags, }: {
|
|
20
|
+
existingFlags: Tenant['flags'];
|
|
21
|
+
proposedFlags: Tenant['flags'];
|
|
22
|
+
}) => Tenant['flags'];
|
|
@@ -41,7 +41,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
41
41
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
42
|
};
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.schema = void 0;
|
|
44
|
+
exports.sanitizeMigrationFlags = exports.schema = void 0;
|
|
45
45
|
const validationError_1 = __importDefault(require("../../validationError"));
|
|
46
46
|
const default_1 = __importStar(require("./default"));
|
|
47
47
|
const pages_1 = require("./pages");
|
|
@@ -61,6 +61,7 @@ class TenantHandler extends default_1.default {
|
|
|
61
61
|
getType() {
|
|
62
62
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
63
|
const tenant = yield this.client.tenant.getSettings();
|
|
64
|
+
this.existing = tenant;
|
|
64
65
|
blockPageKeys.forEach((key) => {
|
|
65
66
|
if (tenant[key])
|
|
66
67
|
delete tenant[key];
|
|
@@ -84,10 +85,18 @@ class TenantHandler extends default_1.default {
|
|
|
84
85
|
processChanges(assets) {
|
|
85
86
|
return __awaiter(this, void 0, void 0, function* () {
|
|
86
87
|
const { tenant } = assets;
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
// Do nothing if not set
|
|
89
|
+
if (!tenant)
|
|
90
|
+
return;
|
|
91
|
+
const existingTenant = this.existing || (yield this.getType());
|
|
92
|
+
const updatedTenant = Object.assign(Object.assign({}, tenant), { flags: (0, exports.sanitizeMigrationFlags)({
|
|
93
|
+
existingFlags: existingTenant.flags,
|
|
94
|
+
proposedFlags: tenant.flags,
|
|
95
|
+
}) });
|
|
96
|
+
if (updatedTenant && Object.keys(updatedTenant).length > 0) {
|
|
97
|
+
yield this.client.tenant.updateSettings(updatedTenant);
|
|
89
98
|
this.updated += 1;
|
|
90
|
-
this.didUpdate(
|
|
99
|
+
this.didUpdate(updatedTenant);
|
|
91
100
|
}
|
|
92
101
|
});
|
|
93
102
|
}
|
|
@@ -96,3 +105,29 @@ __decorate([
|
|
|
96
105
|
(0, default_1.order)('100')
|
|
97
106
|
], TenantHandler.prototype, "processChanges", null);
|
|
98
107
|
exports.default = TenantHandler;
|
|
108
|
+
const sanitizeMigrationFlags = ({ existingFlags = {}, proposedFlags = {}, }) => {
|
|
109
|
+
/*
|
|
110
|
+
Tenants can only update migration flags that are already configured.
|
|
111
|
+
If moving configuration from one tenant to another, there may be instances
|
|
112
|
+
where different migration flags exist and cause an error on update. This
|
|
113
|
+
function removes any migration flags that aren't already present on the target
|
|
114
|
+
tenant. See: https://github.com/auth0/auth0-deploy-cli/issues/374
|
|
115
|
+
*/
|
|
116
|
+
const tenantMigrationFlags = [
|
|
117
|
+
'disable_clickjack_protection_headers',
|
|
118
|
+
'enable_mgmt_api_v1',
|
|
119
|
+
'trust_azure_adfs_email_verified_connection_property',
|
|
120
|
+
'include_email_in_reset_pwd_redirect',
|
|
121
|
+
'include_email_in_verify_email_redirect',
|
|
122
|
+
];
|
|
123
|
+
return Object.keys(proposedFlags).reduce((acc, proposedKey) => {
|
|
124
|
+
const isMigrationFlag = tenantMigrationFlags.includes(proposedKey);
|
|
125
|
+
if (!isMigrationFlag)
|
|
126
|
+
return Object.assign(Object.assign({}, acc), { [proposedKey]: proposedFlags[proposedKey] });
|
|
127
|
+
const keyCurrentlyExists = existingFlags[proposedKey] !== undefined;
|
|
128
|
+
if (keyCurrentlyExists)
|
|
129
|
+
return Object.assign(Object.assign({}, acc), { [proposedKey]: proposedFlags[proposedKey] });
|
|
130
|
+
return acc;
|
|
131
|
+
}, {});
|
|
132
|
+
};
|
|
133
|
+
exports.sanitizeMigrationFlags = sanitizeMigrationFlags;
|