auth0-deploy-cli 7.5.2 → 7.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.eslintrc +7 -41
  2. package/.husky/pre-commit +4 -0
  3. package/.husky/pre-push +3 -1
  4. package/.prettierignore +10 -0
  5. package/.prettierrc.json +4 -0
  6. package/CHANGELOG.md +219 -7
  7. package/CONTRIBUTING.md +2 -2
  8. package/README.md +3 -0
  9. package/lib/args.js +16 -17
  10. package/lib/commands/export.js +3 -3
  11. package/lib/commands/import.js +7 -6
  12. package/lib/commands/index.js +1 -1
  13. package/lib/configFactory.js +5 -1
  14. package/lib/context/defaults.js +4 -3
  15. package/lib/context/directory/handlers/actions.js +6 -5
  16. package/lib/context/directory/handlers/attackProtection.js +10 -9
  17. package/lib/context/directory/handlers/branding.js +60 -0
  18. package/lib/context/directory/handlers/clientGrants.js +6 -4
  19. package/lib/context/directory/handlers/clients.js +4 -3
  20. package/lib/context/directory/handlers/connections.js +7 -4
  21. package/lib/context/directory/handlers/databases.js +30 -22
  22. package/lib/context/directory/handlers/emailProvider.js +6 -4
  23. package/lib/context/directory/handlers/emailTemplates.js +13 -11
  24. package/lib/context/directory/handlers/guardianFactorProviders.js +6 -4
  25. package/lib/context/directory/handlers/guardianFactorTemplates.js +6 -4
  26. package/lib/context/directory/handlers/guardianFactors.js +6 -4
  27. package/lib/context/directory/handlers/guardianPhoneFactorMessageTypes.js +4 -3
  28. package/lib/context/directory/handlers/guardianPhoneFactorSelectedProvider.js +4 -3
  29. package/lib/context/directory/handlers/guardianPolicies.js +4 -3
  30. package/lib/context/directory/handlers/hooks.js +5 -4
  31. package/lib/context/directory/handlers/index.js +5 -2
  32. package/lib/context/directory/handlers/migrations.js +8 -8
  33. package/lib/context/directory/handlers/organizations.js +4 -3
  34. package/lib/context/directory/handlers/pages.js +20 -20
  35. package/lib/context/directory/handlers/resourceServers.js +6 -4
  36. package/lib/context/directory/handlers/roles.js +4 -3
  37. package/lib/context/directory/handlers/rules.js +5 -4
  38. package/lib/context/directory/handlers/rulesConfigs.js +7 -5
  39. package/lib/context/directory/handlers/tenant.js +7 -4
  40. package/lib/context/directory/handlers/triggers.js +3 -2
  41. package/lib/context/directory/index.js +23 -22
  42. package/lib/context/index.js +83 -61
  43. package/lib/context/yaml/handlers/actions.js +12 -8
  44. package/lib/context/yaml/handlers/attackProtection.js +6 -12
  45. package/lib/context/yaml/handlers/branding.js +66 -0
  46. package/lib/context/yaml/handlers/clientGrants.js +5 -4
  47. package/lib/context/yaml/handlers/clients.js +9 -6
  48. package/lib/context/yaml/handlers/connections.js +10 -7
  49. package/lib/context/yaml/handlers/databases.js +15 -10
  50. package/lib/context/yaml/handlers/emailProvider.js +7 -5
  51. package/lib/context/yaml/handlers/emailTemplates.js +6 -5
  52. package/lib/context/yaml/handlers/guardianFactorProviders.js +6 -13
  53. package/lib/context/yaml/handlers/guardianFactorTemplates.js +6 -13
  54. package/lib/context/yaml/handlers/guardianFactors.js +6 -13
  55. package/lib/context/yaml/handlers/guardianPhoneFactorMessageTypes.js +6 -13
  56. package/lib/context/yaml/handlers/guardianPhoneFactorSelectedProvider.js +6 -13
  57. package/lib/context/yaml/handlers/guardianPolicies.js +6 -13
  58. package/lib/context/yaml/handlers/hooks.js +7 -5
  59. package/lib/context/yaml/handlers/index.js +5 -2
  60. package/lib/context/yaml/handlers/migrations.js +3 -2
  61. package/lib/context/yaml/handlers/organizations.js +6 -5
  62. package/lib/context/yaml/handlers/pages.js +6 -5
  63. package/lib/context/yaml/handlers/resourceServers.js +5 -4
  64. package/lib/context/yaml/handlers/roles.js +6 -5
  65. package/lib/context/yaml/handlers/rules.js +6 -5
  66. package/lib/context/yaml/handlers/rulesConfigs.js +6 -5
  67. package/lib/context/yaml/handlers/tenant.js +7 -5
  68. package/lib/context/yaml/handlers/triggers.js +5 -4
  69. package/lib/context/yaml/index.js +33 -24
  70. package/lib/index.js +20 -15
  71. package/lib/logger.js +4 -3
  72. package/lib/readonly.js +11 -16
  73. package/lib/sessionDurationsToMinutes.js +15 -0
  74. package/lib/tools/auth0/client.js +12 -12
  75. package/lib/tools/auth0/handlers/actions.js +21 -23
  76. package/lib/tools/auth0/handlers/attackProtection.js +14 -17
  77. package/lib/tools/auth0/handlers/branding.js +71 -13
  78. package/lib/tools/auth0/handlers/clientGrants.js +17 -10
  79. package/lib/tools/auth0/handlers/clients.js +15 -8
  80. package/lib/tools/auth0/handlers/connections.js +30 -10
  81. package/lib/tools/auth0/handlers/databases.js +25 -13
  82. package/lib/tools/auth0/handlers/default.js +46 -28
  83. package/lib/tools/auth0/handlers/emailTemplates.js +8 -10
  84. package/lib/tools/auth0/handlers/guardianFactorProviders.js +3 -3
  85. package/lib/tools/auth0/handlers/guardianFactorTemplates.js +3 -3
  86. package/lib/tools/auth0/handlers/guardianFactors.js +3 -3
  87. package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +11 -10
  88. package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +10 -9
  89. package/lib/tools/auth0/handlers/guardianPolicies.js +5 -4
  90. package/lib/tools/auth0/handlers/hooks.js +34 -21
  91. package/lib/tools/auth0/handlers/index.js +31 -27
  92. package/lib/tools/auth0/handlers/migrations.js +2 -1
  93. package/lib/tools/auth0/handlers/organizations.js +67 -32
  94. package/lib/tools/auth0/handlers/pages.js +20 -14
  95. package/lib/tools/auth0/handlers/prompts.js +1 -0
  96. package/lib/tools/auth0/handlers/resourceServers.js +28 -15
  97. package/lib/tools/auth0/handlers/roles.js +61 -32
  98. package/lib/tools/auth0/handlers/rules.js +58 -35
  99. package/lib/tools/auth0/handlers/rulesConfigs.js +12 -6
  100. package/lib/tools/auth0/handlers/tenant.js +8 -4
  101. package/lib/tools/auth0/handlers/triggers.js +11 -12
  102. package/lib/tools/auth0/index.js +15 -31
  103. package/lib/tools/auth0/schema.js +7 -27
  104. package/lib/tools/calculateChanges.js +149 -0
  105. package/lib/tools/constants.js +162 -154
  106. package/lib/tools/deploy.js +1 -1
  107. package/lib/tools/index.js +1 -1
  108. package/lib/tools/logger.js +14 -8
  109. package/lib/tools/utils.js +34 -150
  110. package/lib/tools/{ValidationError.js → validationError.js} +3 -1
  111. package/lib/types.js +2 -0
  112. package/lib/utils.js +18 -25
  113. package/package.json +11 -2
  114. package/tsconfig.json +2 -3
  115. package/typescript-migration-progress.sh +1 -1
@@ -13,13 +13,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.schema = exports.excludeSchema = void 0;
16
- const ValidationError_1 = __importDefault(require("../../ValidationError"));
16
+ const validationError_1 = __importDefault(require("../../validationError"));
17
17
  const utils_1 = require("../../utils");
18
18
  const default_1 = __importDefault(require("./default"));
19
19
  const logger_1 = __importDefault(require("../../logger"));
20
+ const calculateChanges_1 = require("../../calculateChanges");
20
21
  exports.excludeSchema = {
21
22
  type: 'array',
22
- items: { type: 'string' }
23
+ items: { type: 'string' },
23
24
  };
24
25
  exports.schema = {
25
26
  type: 'array',
@@ -29,38 +30,37 @@ exports.schema = {
29
30
  properties: {
30
31
  script: {
31
32
  type: 'string',
32
- description: 'A script that contains the rule\'s code',
33
- default: ''
33
+ description: "A script that contains the rule's code",
34
+ default: '',
34
35
  },
35
36
  name: {
36
37
  type: 'string',
37
- description: 'The name of the rule. Can only contain alphanumeric characters, spaces and \'-\'. Can neither start nor end with \'-\' or spaces',
38
- pattern: '^[^-\\s][a-zA-Z0-9-\\s]+[^-\\s]$'
38
+ description: "The name of the rule. Can only contain alphanumeric characters, spaces and '-'. Can neither start nor end with '-' or spaces",
39
+ pattern: '^[^-\\s][a-zA-Z0-9-\\s]+[^-\\s]$',
39
40
  },
40
41
  order: {
41
42
  type: ['number', 'null'],
42
- description: 'The rule\'s order in relation to other rules. A rule with a lower order than another rule executes first.',
43
- default: null
43
+ description: "The rule's order in relation to other rules. A rule with a lower order than another rule executes first.",
44
+ default: null,
44
45
  },
45
46
  enabled: {
46
47
  type: 'boolean',
47
48
  description: 'true if the rule is enabled, false otherwise',
48
- default: true
49
+ default: true,
49
50
  },
50
51
  stage: {
51
52
  type: 'string',
52
- description: 'The rule\'s execution stage',
53
+ description: "The rule's execution stage",
53
54
  default: 'login_success',
54
- enum: ['login_success', 'login_failure', 'pre_authorize']
55
- }
55
+ enum: ['login_success', 'login_failure', 'pre_authorize'],
56
+ },
56
57
  },
57
- required: ['name']
58
- }
58
+ required: ['name'],
59
+ },
59
60
  };
60
61
  class RulesHandler extends default_1.default {
61
62
  constructor(options) {
62
- super(Object.assign(Object.assign({}, options), { type: 'rules', stripUpdateFields: ['stage'] // Fields not allowed in updates
63
- }));
63
+ super(Object.assign(Object.assign({}, options), { type: 'rules', stripUpdateFields: ['stage'] }));
64
64
  }
65
65
  getType() {
66
66
  return __awaiter(this, void 0, void 0, function* () {
@@ -84,17 +84,27 @@ class RulesHandler extends default_1.default {
84
84
  existing = existing.filter((r) => !excludedRules.includes(r.name));
85
85
  }
86
86
  // Figure out what needs to be updated vs created
87
- const { del, update, create, conflicts } = (0, utils_1.calcChanges)(this, rules, existing, ['id', 'name']);
87
+ const { del, update, create, conflicts } = (0, calculateChanges_1.calculateChanges)({
88
+ handler: this,
89
+ assets: rules,
90
+ existing,
91
+ identifiers: ['id', 'name'],
92
+ allowDelete: false, //TODO: actually pass in correct allowDelete value
93
+ });
88
94
  // Figure out the rules that need to be re-ordered
89
95
  const futureRules = [...create, ...update];
90
96
  const futureMaxOrder = Math.max(...futureRules.map((r) => r.order));
91
97
  const existingMaxOrder = Math.max(...existing.map((r) => r.order));
92
98
  let nextOrderNo = Math.max(futureMaxOrder, existingMaxOrder);
99
+ //@ts-ignore because we know reOrder is Asset[]
93
100
  const reOrder = futureRules.reduce((accum, r) => {
94
101
  const conflict = existing.find((f) => r.order === f.order && r.name !== f.name);
95
- if (conflict) {
102
+ if (conflict !== undefined) {
96
103
  nextOrderNo += 1;
97
- accum.push(Object.assign(Object.assign({}, conflict), { order: nextOrderNo }));
104
+ return [
105
+ ...accum,
106
+ Object.assign(Object.assign({}, conflict), { order: nextOrderNo }),
107
+ ];
98
108
  }
99
109
  return accum;
100
110
  }, []);
@@ -103,7 +113,7 @@ class RulesHandler extends default_1.default {
103
113
  update,
104
114
  create,
105
115
  reOrder,
106
- conflicts
116
+ conflicts,
107
117
  };
108
118
  });
109
119
  }
@@ -121,24 +131,30 @@ class RulesHandler extends default_1.default {
121
131
  const { update, create, del } = yield this.calcChanges(assets, true);
122
132
  // Include del rules which are actually not going to be deleted but are excluded
123
133
  // they can still muck up the ordering so we must take it into consideration.
124
- const futureRules = [...create, ...update, ...del.filter((r) => excludedRules.includes(r.name))];
134
+ const futureRules = [
135
+ ...create,
136
+ ...update,
137
+ ...del.filter((r) => excludedRules.includes(r.name)),
138
+ ];
125
139
  // Detect rules with the same order
126
140
  const rulesSameOrder = (0, utils_1.duplicateItems)(futureRules, 'order');
127
141
  if (rulesSameOrder.length > 0) {
128
142
  const formatted = rulesSameOrder.map((dups) => dups.map((d) => `${d.name}`));
129
- throw new ValidationError_1.default(`There are multiple rules for the following stage-order combinations
130
- ${(0, utils_1.dumpJSON)(formatted)}.
143
+ throw new validationError_1.default(`There are multiple rules for the following stage-order combinations
144
+ ${(0, utils_1.convertJsonToString)(formatted)}.
131
145
  Only one rule must be defined for the same order number in a stage.`);
132
146
  }
133
147
  // Detect Rules that are changing stage as it's not allowed.
134
148
  const existing = yield this.getType();
135
- const stateChanged = futureRules.reduce((changed, rule) => ([
149
+ const stateChanged = futureRules
150
+ .reduce((changed, rule) => [
136
151
  ...changed,
137
- ...existing.filter((r) => rule.name.toLowerCase() === r.name.toLowerCase() && r.stage !== rule.stage)
138
- ]), []).map((r) => r.name);
152
+ ...existing.filter((r) => rule.name.toLowerCase() === r.name.toLowerCase() && r.stage !== rule.stage),
153
+ ], [])
154
+ .map((r) => r.name);
139
155
  if (stateChanged.length > 0) {
140
- throw new ValidationError_1.default(`The following rules changed stage which is not allowed:
141
- ${(0, utils_1.dumpJSON)(stateChanged)}.
156
+ throw new validationError_1.default(`The following rules changed stage which is not allowed:
157
+ ${(0, utils_1.convertJsonToString)(stateChanged)}.
142
158
  Rename the rules to recreate them and avoid this error.`);
143
159
  }
144
160
  yield _super.validate.call(this, assets);
@@ -156,20 +172,27 @@ class RulesHandler extends default_1.default {
156
172
  // Figure out what needs to be updated vs created
157
173
  const changes = yield this.calcChanges(assets);
158
174
  // Temporally re-order rules with conflicting ordering
159
- yield this.client.pool.addEachTask({
175
+ yield this.client.pool
176
+ .addEachTask({
160
177
  data: changes.reOrder,
161
- generator: (rule) => this.client.updateRule({ id: rule.id }, (0, utils_1.stripFields)(rule, this.stripUpdateFields)).then(() => {
178
+ generator: (rule) => this.client
179
+ .updateRule({ id: rule.id }, (0, utils_1.stripFields)(rule, this.stripUpdateFields))
180
+ .then(() => {
162
181
  const updated = {
163
- name: rule.name, stage: rule.stage, order: rule.order, id: rule.id
182
+ name: rule.name,
183
+ stage: rule.stage,
184
+ order: rule.order,
185
+ id: rule.id,
164
186
  };
165
- logger_1.default.info(`Temporally re-order Rule ${(0, utils_1.dumpJSON)(updated)}`);
166
- })
167
- }).promise();
187
+ logger_1.default.info(`Temporally re-order Rule ${(0, utils_1.convertJsonToString)(updated)}`);
188
+ }),
189
+ })
190
+ .promise();
168
191
  yield _super.processChanges.call(this, assets, {
169
192
  del: changes.del,
170
193
  create: changes.create,
171
194
  update: changes.update,
172
- conflicts: changes.conflicts
195
+ conflicts: changes.conflicts,
173
196
  });
174
197
  });
175
198
  }
@@ -20,16 +20,16 @@ exports.schema = {
20
20
  type: 'object',
21
21
  properties: {
22
22
  key: { type: 'string', pattern: '^[A-Za-z0-9_-]*$' },
23
- value: { type: 'string' }
23
+ value: { type: 'string' },
24
24
  },
25
- required: ['key', 'value']
25
+ required: ['key', 'value'],
26
26
  },
27
- additionalProperties: false
27
+ additionalProperties: false,
28
28
  };
29
29
  class RulesConfigsHandler extends default_1.default {
30
30
  constructor(options) {
31
31
  super(Object.assign(Object.assign({}, options), { type: 'rulesConfigs', id: 'key', functions: {
32
- update: 'set' // Update or Creation of a ruleConfig is via set not update
32
+ update: 'set', // Update or Creation of a ruleConfig is via set not update
33
33
  } }));
34
34
  }
35
35
  getType() {
@@ -45,12 +45,18 @@ class RulesConfigsHandler extends default_1.default {
45
45
  const { rulesConfigs } = assets;
46
46
  // Do nothing if not set
47
47
  if (!rulesConfigs || !rulesConfigs.length)
48
- return {};
48
+ return {
49
+ del: [],
50
+ update: [],
51
+ create: [],
52
+ conflicts: [],
53
+ };
49
54
  // Intention is to not delete/cleanup old configRules, that needs to be handled manually.
50
55
  return {
51
56
  del: [],
52
57
  update: rulesConfigs,
53
- create: []
58
+ create: [],
59
+ conflicts: [],
54
60
  };
55
61
  });
56
62
  }
@@ -42,14 +42,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
42
42
  };
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
44
  exports.schema = void 0;
45
- const ValidationError_1 = __importDefault(require("../../ValidationError"));
45
+ const validationError_1 = __importDefault(require("../../validationError"));
46
46
  const default_1 = __importStar(require("./default"));
47
47
  const pages_1 = require("./pages");
48
48
  const utils_1 = require("../../utils");
49
49
  exports.schema = {
50
- type: 'object'
50
+ type: 'object',
51
51
  };
52
- const blockPageKeys = [...Object.keys(pages_1.pageNameMap), ...Object.values(pages_1.pageNameMap), ...pages_1.supportedPages];
52
+ const blockPageKeys = [
53
+ ...Object.keys(pages_1.pageNameMap),
54
+ ...Object.values(pages_1.pageNameMap),
55
+ ...pages_1.supportedPages,
56
+ ];
53
57
  class TenantHandler extends default_1.default {
54
58
  constructor(options) {
55
59
  super(Object.assign(Object.assign({}, options), { type: 'tenant' }));
@@ -72,7 +76,7 @@ class TenantHandler extends default_1.default {
72
76
  return;
73
77
  const pageKeys = Object.keys(tenant).filter((k) => blockPageKeys.includes(k));
74
78
  if (pageKeys.length > 0) {
75
- throw new ValidationError_1.default(`The following pages ${(0, utils_1.dumpJSON)(pageKeys)} were found in tenant settings. Pages should be set separately. Please refer to the documentation.`);
79
+ throw new validationError_1.default(`The following pages ${(0, utils_1.convertJsonToString)(pageKeys)} were found in tenant settings. Pages should be set separately. Please refer to the documentation.`);
76
80
  }
77
81
  });
78
82
  }
@@ -56,15 +56,15 @@ exports.schema = {
56
56
  type: 'object',
57
57
  properties: {
58
58
  action_name: { type: 'string', enum: constants_1.default.ACTIONS_TRIGGERS },
59
- display_name: { type: 'string', default: '' }
60
- }
61
- }
62
- }
63
- }
59
+ display_name: { type: 'string', default: '' },
60
+ },
61
+ },
62
+ },
63
+ },
64
64
  };
65
65
  function isActionsDisabled(err) {
66
66
  const errorBody = lodash_1.default.get(err, 'originalError.response.body') || {};
67
- return (err.statusCode === 403 && errorBody.errorCode === 'feature_not_enabled');
67
+ return err.statusCode === 403 && errorBody.errorCode === 'feature_not_enabled';
68
68
  }
69
69
  class TriggersHandler extends default_1.default {
70
70
  constructor(options) {
@@ -76,8 +76,7 @@ class TriggersHandler extends default_1.default {
76
76
  return this.existing;
77
77
  }
78
78
  // in case client version does not support actions
79
- if (!this.client.actions
80
- || typeof this.client.actions.getAllTriggers !== 'function') {
79
+ if (!this.client.actions || typeof this.client.actions.getAllTriggers !== 'function') {
81
80
  return [];
82
81
  }
83
82
  const triggerBindings = {};
@@ -87,12 +86,12 @@ class TriggersHandler extends default_1.default {
87
86
  for (let i = 0; i < triggers.length; i++) {
88
87
  const triggerId = triggers[i];
89
88
  const { bindings } = yield this.client.actions.getTriggerBindings({
90
- trigger_id: triggerId
89
+ trigger_id: triggerId,
91
90
  });
92
91
  if (bindings.length > 0) {
93
92
  triggerBindings[triggerId] = bindings.map((binding) => ({
94
93
  action_name: binding.action.name,
95
- display_name: binding.display_name
94
+ display_name: binding.display_name,
96
95
  }));
97
96
  }
98
97
  }
@@ -123,9 +122,9 @@ class TriggersHandler extends default_1.default {
123
122
  const bindings = data.map((binding) => ({
124
123
  ref: {
125
124
  type: 'action_name',
126
- value: binding.action_name
125
+ value: binding.action_name,
127
126
  },
128
- display_name: binding.display_name
127
+ display_name: binding.display_name,
129
128
  }));
130
129
  yield this.client.actions.updateTriggerBindings({ trigger_id: name }, { bindings });
131
130
  this.didUpdate({ trigger_id: name });
@@ -1,27 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -38,12 +15,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
15
  const ajv_1 = __importDefault(require("ajv/lib/ajv"));
39
16
  const client_1 = __importDefault(require("./client"));
40
17
  const schema_1 = __importDefault(require("./schema"));
41
- const handlers = __importStar(require("./handlers"));
42
- const defaultOrder = 50;
18
+ const handlers_1 = __importDefault(require("./handlers"));
43
19
  function sortByOrder(toSort, stage) {
20
+ const defaultOrder = 50;
44
21
  const sorted = [...toSort];
45
22
  sorted.sort((a, b) => {
23
+ //@ts-ignore because this doesn't actually work. TODO: apply stage order
46
24
  const aOrder = a[stage].order || defaultOrder;
25
+ //@ts-ignore because this doesn't actually work. TODO: apply stage order
47
26
  const bOrder = b[stage].order || defaultOrder;
48
27
  return aOrder - bOrder;
49
28
  });
@@ -54,19 +33,24 @@ class Auth0 {
54
33
  this.client = (0, client_1.default)(client);
55
34
  this.config = config;
56
35
  this.assets = assets;
57
- this.handlers = [];
58
- Object.values(handlers).forEach((h) => {
59
- const handler = new h.default({ client: this.client, config });
60
- this.handlers.push(handler);
36
+ this.handlers = Object.values(handlers_1.default)
37
+ .map((handler) => {
38
+ //@ts-ignore because class expects `type` property but gets directly injected into class constructors
39
+ return new handler.default({ client: this.client, config: this.config });
40
+ })
41
+ .filter((handler) => {
42
+ const excludedAssetTypes = config('AUTH0_EXCLUDED') || [];
43
+ return !excludedAssetTypes.includes(handler.type);
61
44
  });
62
45
  }
63
46
  runStage(stage) {
64
47
  return __awaiter(this, void 0, void 0, function* () {
65
48
  // Sort by priority
66
- for (const handler of sortByOrder(this.handlers, stage)) { // eslint-disable-line
49
+ for (const handler of sortByOrder(this.handlers, stage)) {
50
+ // eslint-disable-line
67
51
  try {
68
52
  const stageFn = Object.getPrototypeOf(handler)[stage];
69
- this.assets = Object.assign(Object.assign({}, this.assets), (yield stageFn.apply(handler, [this.assets])) || {});
53
+ this.assets = Object.assign(Object.assign({}, this.assets), ((yield stageFn.apply(handler, [this.assets])) || {}));
70
54
  }
71
55
  catch (err) {
72
56
  err.type = handler.type;
@@ -1,34 +1,14 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
4
  };
25
5
  Object.defineProperty(exports, "__esModule", { value: true });
26
- const handlers = __importStar(require("./handlers"));
27
- const typesSchema = Object.entries(handlers).reduce((map, [name, obj]) => {
6
+ const handlers_1 = __importDefault(require("./handlers"));
7
+ const typesSchema = Object.entries(handlers_1.default).reduce((map, [name, obj]) => {
28
8
  map[name] = obj.schema; //eslint-disable-line
29
9
  return map;
30
10
  }, {});
31
- const excludeSchema = Object.entries(handlers).reduce((map, [name, obj]) => {
11
+ const excludeSchema = Object.entries(handlers_1.default).reduce((map, [name, obj]) => {
32
12
  if (obj.excludeSchema) {
33
13
  map[name] = obj.excludeSchema;
34
14
  }
@@ -40,7 +20,7 @@ exports.default = {
40
20
  properties: Object.assign(Object.assign({}, typesSchema), { exclude: {
41
21
  type: 'object',
42
22
  properties: Object.assign({}, excludeSchema),
43
- default: {}
23
+ default: {},
44
24
  } }),
45
- additionalProperties: false
25
+ additionalProperties: false,
46
26
  };
@@ -0,0 +1,149 @@
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.calculateChanges = exports.processChangedObjectFields = void 0;
7
+ const logger_1 = __importDefault(require("./logger"));
8
+ /**
9
+ * @template T
10
+ * @param {typeof import('./auth0/handlers/default').default} handler
11
+ * @param {T} desiredAssetState
12
+ * @param {T} currentAssetState
13
+ * @param {string[]} [objectFields=[]]
14
+ * @param {boolean} [allowDelete=false]
15
+ * @returns T
16
+ */
17
+ function processChangedObjectFields({ handler, desiredAssetState, currentAssetState, allowDelete = false, }) {
18
+ const desiredAssetStateWithChanges = Object.assign({}, desiredAssetState);
19
+ // eslint-disable-next-line no-restricted-syntax
20
+ for (const fieldName of handler.objectFields) {
21
+ const areDesiredStateAndCurrentStateEmpty = Object.keys(desiredAssetState[fieldName] || {}).length === 0 &&
22
+ Object.keys(currentAssetState[fieldName] || {}).length === 0;
23
+ if (areDesiredStateAndCurrentStateEmpty) {
24
+ // If both the desired state and current state for a given object is empty, it is a no-op and can skip
25
+ // eslint-disable-next-line no-continue
26
+ continue;
27
+ }
28
+ // A desired state that omits the objectField OR that has it as an empty object should
29
+ // signal that all fields should be removed (subject to ALLOW_DELETE).
30
+ if (desiredAssetState[fieldName] && Object.keys(desiredAssetState[fieldName]).length) {
31
+ // Both the current and desired state have the object field. Here's where we need to map
32
+ // to the APIv2 protocol of setting `null` values for deleted fields.
33
+ // For new and modified properties of the object field, we can just pass them through to
34
+ // APIv2.
35
+ if (currentAssetState[fieldName]) {
36
+ // eslint-disable-next-line no-restricted-syntax
37
+ for (const currentObjectFieldPropertyName of Object.keys(currentAssetState[fieldName])) {
38
+ // Loop through each object property that exists currently
39
+ if (desiredAssetState[fieldName][currentObjectFieldPropertyName] === undefined) {
40
+ // If the object has a property that exists now but doesn't exist in the proposed state
41
+ if (allowDelete) {
42
+ desiredAssetStateWithChanges[fieldName][currentObjectFieldPropertyName] = null;
43
+ }
44
+ else {
45
+ // If deletes aren't allowed, do outright delete the property within the object
46
+ logger_1.default.warn(`Detected that the ${fieldName} of the following ${handler.name || handler.id || ''} should be deleted. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${handler.objString(currentAssetState)}`);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ else if (allowDelete) {
53
+ // If the desired state does not have the object field and the current state does, we
54
+ // should mark *all* properties for deletion by specifying an empty object.
55
+ //
56
+ // See: https://auth0.com/docs/users/metadata/manage-metadata-api#delete-user-metadata
57
+ desiredAssetStateWithChanges[fieldName] = {};
58
+ }
59
+ else {
60
+ delete desiredAssetStateWithChanges[fieldName];
61
+ logger_1.default.warn(`Detected that the ${fieldName} of the following ${handler.name || handler.id || ''} should be emptied. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${handler.objString(currentAssetState)}`);
62
+ }
63
+ }
64
+ return desiredAssetStateWithChanges;
65
+ }
66
+ exports.processChangedObjectFields = processChangedObjectFields;
67
+ function calculateChanges({ handler, assets, existing, identifiers = ['id', 'name'], allowDelete, }) {
68
+ // Calculate the changes required between two sets of assets.
69
+ const update = [];
70
+ let del = [...existing];
71
+ let create = [...assets];
72
+ const conflicts = [];
73
+ const findByKeyValue = (key, value, arr) => arr.find((e) => {
74
+ if (Array.isArray(key)) {
75
+ const values = key.map((k) => e[k]);
76
+ if (values.every((v) => v)) {
77
+ return value === values.join('-');
78
+ }
79
+ }
80
+ return e[key] === value;
81
+ });
82
+ const processAssets = (id, arr) => {
83
+ arr.forEach((asset) => {
84
+ const assetIdValue = (() => {
85
+ if (Array.isArray(id)) {
86
+ const values = id.map((i) => asset[i]);
87
+ if (values.every((v) => v)) {
88
+ return values.join('-');
89
+ }
90
+ }
91
+ return asset[id];
92
+ })();
93
+ if (assetIdValue !== undefined) {
94
+ const found = findByKeyValue(id, assetIdValue, del);
95
+ if (found !== undefined) {
96
+ // Delete from existing
97
+ del = del.filter((e) => e !== found);
98
+ // Delete from create as it's an update
99
+ create = create.filter((e) => e !== asset);
100
+ // Append identifiers to asset
101
+ update.push(Object.assign(Object.assign({}, identifiers.reduce((obj, i) => {
102
+ if (found[i])
103
+ obj[i] = found[i];
104
+ return obj;
105
+ }, {})), (handler.objectFields.length
106
+ ? processChangedObjectFields({
107
+ handler,
108
+ desiredAssetState: asset,
109
+ currentAssetState: found,
110
+ allowDelete,
111
+ })
112
+ : asset)));
113
+ }
114
+ }
115
+ });
116
+ };
117
+ // Loop through identifiers (in order) to try match assets to existing
118
+ // If existing then update if not create
119
+ // The remainder will be deleted
120
+ for (const id of identifiers) {
121
+ // eslint-disable-line
122
+ processAssets(id, [...create]);
123
+ }
124
+ // Check if there are assets with names that will conflict with existing names during the update process
125
+ // This will rename those assets to a temp random name first
126
+ // This assumes the first identifiers is the unique identifier
127
+ if (identifiers.includes('name')) {
128
+ const uniqueID = identifiers[0];
129
+ const futureAssets = [...create, ...update];
130
+ futureAssets.forEach((a) => {
131
+ // If the conflicting item is going to be deleted then skip
132
+ const inDeleted = del.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
133
+ if (!inDeleted) {
134
+ const conflict = existing.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
135
+ if (conflict) {
136
+ const temp = Math.random().toString(36).substr(2, 5);
137
+ conflicts.push(Object.assign(Object.assign({}, conflict), { name: `${conflict.name}-${temp}` }));
138
+ }
139
+ }
140
+ });
141
+ }
142
+ return {
143
+ del,
144
+ update,
145
+ conflicts,
146
+ create,
147
+ };
148
+ }
149
+ exports.calculateChanges = calculateChanges;