auth0-deploy-cli 7.4.0 → 7.5.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 +15 -0
- package/.github/CODEOWNERS +1 -0
- package/.husky/pre-commit +2 -0
- package/.nyc_output/60b76a45-577b-4171-9982-a8e836ab7fd6.json +1 -0
- package/.nyc_output/processinfo/60b76a45-577b-4171-9982-a8e836ab7fd6.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -1
- package/CHANGELOG.md +13 -1
- package/lib/args.js +89 -81
- package/lib/commands/export.js +51 -77
- package/lib/commands/import.js +45 -69
- package/lib/commands/index.js +11 -20
- package/lib/configFactory.js +19 -27
- package/lib/context/defaults.js +18 -41
- package/lib/context/directory/handlers/actions.js +77 -107
- package/lib/context/directory/handlers/attackProtection.js +59 -0
- package/lib/context/directory/handlers/clientGrants.js +45 -54
- package/lib/context/directory/handlers/clients.js +60 -79
- package/lib/context/directory/handlers/connections.js +65 -89
- package/lib/context/directory/handlers/databases.js +91 -123
- package/lib/context/directory/handlers/emailProvider.js +46 -57
- package/lib/context/directory/handlers/emailTemplates.js +67 -80
- package/lib/context/directory/handlers/guardianFactorProviders.js +41 -49
- package/lib/context/directory/handlers/guardianFactorTemplates.js +41 -49
- package/lib/context/directory/handlers/guardianFactors.js +41 -49
- package/lib/context/directory/handlers/guardianPhoneFactorMessageTypes.js +40 -50
- package/lib/context/directory/handlers/guardianPhoneFactorSelectedProvider.js +40 -50
- package/lib/context/directory/handlers/guardianPolicies.js +40 -50
- package/lib/context/directory/handlers/hooks.js +55 -70
- package/lib/context/directory/handlers/index.js +53 -123
- package/lib/context/directory/handlers/migrations.js +36 -41
- package/lib/context/directory/handlers/organizations.js +54 -69
- package/lib/context/directory/handlers/pages.js +72 -86
- package/lib/context/directory/handlers/resourceServers.js +41 -49
- package/lib/context/directory/handlers/roles.js +49 -62
- package/lib/context/directory/handlers/rules.js +52 -68
- package/lib/context/directory/handlers/rulesConfigs.js +33 -32
- package/lib/context/directory/handlers/tenant.js +52 -47
- package/lib/context/directory/handlers/triggers.js +39 -54
- package/lib/context/directory/index.js +113 -101
- package/lib/context/index.js +96 -105
- package/lib/context/yaml/handlers/actions.js +71 -88
- package/lib/context/yaml/handlers/attackProtection.js +29 -0
- package/lib/context/yaml/handlers/clientGrants.js +36 -29
- package/lib/context/yaml/handlers/clients.js +61 -76
- package/lib/context/yaml/handlers/connections.js +76 -103
- package/lib/context/yaml/handlers/databases.js +64 -79
- package/lib/context/yaml/handlers/emailProvider.js +33 -30
- package/lib/context/yaml/handlers/emailTemplates.js +45 -54
- package/lib/context/yaml/handlers/guardianFactorProviders.js +27 -18
- package/lib/context/yaml/handlers/guardianFactorTemplates.js +27 -18
- package/lib/context/yaml/handlers/guardianFactors.js +27 -18
- package/lib/context/yaml/handlers/guardianPhoneFactorMessageTypes.js +27 -20
- package/lib/context/yaml/handlers/guardianPhoneFactorSelectedProvider.js +27 -20
- package/lib/context/yaml/handlers/guardianPolicies.js +27 -20
- package/lib/context/yaml/handlers/hooks.js +57 -67
- package/lib/context/yaml/handlers/index.js +53 -123
- package/lib/context/yaml/handlers/migrations.js +23 -24
- package/lib/context/yaml/handlers/organizations.js +40 -38
- package/lib/context/yaml/handlers/pages.js +49 -58
- package/lib/context/yaml/handlers/resourceServers.js +27 -18
- package/lib/context/yaml/handlers/roles.js +34 -24
- package/lib/context/yaml/handlers/rules.js +48 -58
- package/lib/context/yaml/handlers/rulesConfigs.js +27 -18
- package/lib/context/yaml/handlers/tenant.js +44 -30
- package/lib/context/yaml/handlers/triggers.js +32 -23
- package/lib/context/yaml/index.js +127 -142
- package/lib/index.js +73 -79
- package/lib/logger.js +18 -22
- package/lib/readonly.js +74 -66
- package/lib/tools/ValidationError.js +8 -13
- package/lib/tools/auth0/client.js +143 -133
- package/lib/tools/auth0/handlers/actions.js +231 -243
- package/lib/tools/auth0/handlers/attackProtection.js +86 -0
- package/lib/tools/auth0/handlers/branding.js +47 -46
- package/lib/tools/auth0/handlers/clientGrants.js +118 -116
- package/lib/tools/auth0/handlers/clients.js +72 -90
- package/lib/tools/auth0/handlers/connections.js +150 -118
- package/lib/tools/auth0/handlers/databases.js +127 -124
- package/lib/tools/auth0/handlers/default.js +186 -189
- package/lib/tools/auth0/handlers/emailProvider.js +67 -78
- package/lib/tools/auth0/handlers/emailTemplates.js +116 -92
- package/lib/tools/auth0/handlers/guardianFactorProviders.js +66 -81
- package/lib/tools/auth0/handlers/guardianFactorTemplates.js +60 -71
- package/lib/tools/auth0/handlers/guardianFactors.js +56 -63
- package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +80 -79
- package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +77 -76
- package/lib/tools/auth0/handlers/guardianPolicies.js +59 -62
- package/lib/tools/auth0/handlers/hooks.js +201 -227
- package/lib/tools/auth0/handlers/index.js +53 -111
- package/lib/tools/auth0/handlers/migrations.js +99 -79
- package/lib/tools/auth0/handlers/organizations.js +225 -247
- package/lib/tools/auth0/handlers/pages.js +116 -154
- package/lib/tools/auth0/handlers/prompts.js +47 -46
- package/lib/tools/auth0/handlers/resourceServers.js +88 -112
- package/lib/tools/auth0/handlers/roles.js +203 -220
- package/lib/tools/auth0/handlers/rules.js +168 -189
- package/lib/tools/auth0/handlers/rulesConfigs.js +54 -63
- package/lib/tools/auth0/handlers/tenant.js +88 -64
- package/lib/tools/auth0/handlers/triggers.js +126 -126
- package/lib/tools/auth0/index.js +92 -85
- package/lib/tools/auth0/schema.js +39 -31
- package/lib/tools/constants.js +111 -21
- package/lib/tools/deploy.js +35 -32
- package/lib/tools/index.js +19 -32
- package/lib/tools/logger.js +11 -12
- package/lib/tools/utils.js +255 -282
- package/lib/utils.js +167 -190
- package/package.json +4 -3
- package/tsconfig.json +96 -0
- package/typescript-migration-progress.sh +22 -0
- package/.nyc_output/597f412e-a239-4319-ad5b-ddb87fc39e67.json +0 -1
- package/.nyc_output/processinfo/597f412e-a239-4319-ad5b-ddb87fc39e67.json +0 -1
package/lib/tools/utils.js
CHANGED
|
@@ -1,320 +1,293 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
6
|
-
exports.keywordArrayReplace =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
exports.flatten = flatten;
|
|
13
|
-
exports.dumpJSON = dumpJSON;
|
|
14
|
-
exports.processChangedObjectFields = processChangedObjectFields;
|
|
15
|
-
exports.calcChanges = calcChanges;
|
|
16
|
-
exports.stripFields = stripFields;
|
|
17
|
-
exports.getEnabledClients = getEnabledClients;
|
|
18
|
-
exports.duplicateItems = duplicateItems;
|
|
19
|
-
exports.filterExcluded = filterExcluded;
|
|
20
|
-
exports.areArraysEquals = areArraysEquals;
|
|
21
|
-
|
|
22
|
-
var _path = require("path");
|
|
23
|
-
|
|
24
|
-
var _path2 = _interopRequireDefault(_path);
|
|
25
|
-
|
|
26
|
-
var _fs = require("fs");
|
|
27
|
-
|
|
28
|
-
var _fs2 = _interopRequireDefault(_fs);
|
|
29
|
-
|
|
30
|
-
var _dotProp = require("dot-prop");
|
|
31
|
-
|
|
32
|
-
var _dotProp2 = _interopRequireDefault(_dotProp);
|
|
33
|
-
|
|
34
|
-
var _lodash = require("lodash");
|
|
35
|
-
|
|
36
|
-
var _lodash2 = _interopRequireDefault(_lodash);
|
|
37
|
-
|
|
38
|
-
var _logger = require("./logger");
|
|
39
|
-
|
|
40
|
-
var _logger2 = _interopRequireDefault(_logger);
|
|
41
|
-
|
|
42
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
43
|
-
|
|
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.areArraysEquals = exports.filterExcluded = exports.duplicateItems = exports.getEnabledClients = exports.stripFields = exports.calcChanges = exports.processChangedObjectFields = exports.dumpJSON = exports.flatten = exports.loadFileAndReplaceKeywords = exports.convertClientNamesToIds = exports.convertClientNameToId = exports.keywordReplace = exports.keywordStringReplace = exports.keywordArrayReplace = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const dot_prop_1 = __importDefault(require("dot-prop"));
|
|
10
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
11
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
44
12
|
function keywordArrayReplace(input, mappings) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
13
|
+
Object.keys(mappings).forEach(function (key) {
|
|
14
|
+
// 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.
|
|
15
|
+
const pattern = `@@${key}@@`;
|
|
16
|
+
const patternWithQuotes = `"${pattern}"`;
|
|
17
|
+
const regex = new RegExp(`${patternWithQuotes}|${pattern}`, 'g');
|
|
18
|
+
input = input.replace(regex, JSON.stringify(mappings[key]));
|
|
19
|
+
});
|
|
20
|
+
return input;
|
|
52
21
|
}
|
|
53
|
-
|
|
22
|
+
exports.keywordArrayReplace = keywordArrayReplace;
|
|
54
23
|
function keywordStringReplace(input, mappings) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
24
|
+
Object.keys(mappings).forEach(function (key) {
|
|
25
|
+
const regex = new RegExp(`##${key}##`, 'g');
|
|
26
|
+
input = input.replace(regex, mappings[key]);
|
|
27
|
+
});
|
|
28
|
+
return input;
|
|
60
29
|
}
|
|
61
|
-
|
|
30
|
+
exports.keywordStringReplace = keywordStringReplace;
|
|
62
31
|
function keywordReplace(input, mappings) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
32
|
+
// Replace keywords with mappings within input.
|
|
33
|
+
if (mappings && Object.keys(mappings).length > 0) {
|
|
34
|
+
input = keywordStringReplace(input, mappings);
|
|
35
|
+
input = keywordArrayReplace(input, mappings);
|
|
36
|
+
}
|
|
37
|
+
return input;
|
|
69
38
|
}
|
|
70
|
-
|
|
39
|
+
exports.keywordReplace = keywordReplace;
|
|
71
40
|
function convertClientNameToId(name, clients) {
|
|
72
|
-
|
|
73
|
-
|
|
41
|
+
const found = clients.find((c) => c.name === name);
|
|
42
|
+
return (found && found.client_id) || name;
|
|
74
43
|
}
|
|
75
|
-
|
|
44
|
+
exports.convertClientNameToId = convertClientNameToId;
|
|
76
45
|
function convertClientNamesToIds(names, clients) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return acc;
|
|
89
|
-
}, []);
|
|
90
|
-
const unresolved = resolvedNames.filter(item => !item.resolved).map(item => item.name);
|
|
91
|
-
return [...unresolved, ...result];
|
|
46
|
+
const resolvedNames = names.map((name) => ({ name, resolved: false }));
|
|
47
|
+
const result = clients.reduce((acc, client) => {
|
|
48
|
+
if (names.includes(client.name)) {
|
|
49
|
+
const index = resolvedNames.findIndex((item) => item.name === client.name);
|
|
50
|
+
resolvedNames[index].resolved = true;
|
|
51
|
+
acc.push(client.client_id);
|
|
52
|
+
}
|
|
53
|
+
return acc;
|
|
54
|
+
}, []);
|
|
55
|
+
const unresolved = resolvedNames.filter((item) => !item.resolved).map((item) => item.name);
|
|
56
|
+
return [...unresolved, ...result];
|
|
92
57
|
}
|
|
93
|
-
|
|
58
|
+
exports.convertClientNamesToIds = convertClientNamesToIds;
|
|
94
59
|
function loadFileAndReplaceKeywords(file, mappings) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
60
|
+
// Load file and replace keyword mappings
|
|
61
|
+
const f = path_1.default.resolve(file);
|
|
62
|
+
try {
|
|
63
|
+
fs_1.default.accessSync(f, fs_1.default.F_OK);
|
|
64
|
+
if (mappings) {
|
|
65
|
+
return keywordReplace(fs_1.default.readFileSync(f, 'utf8'), mappings);
|
|
66
|
+
}
|
|
67
|
+
return fs_1.default.readFileSync(f, 'utf8');
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw new Error(`Unable to load file ${f} due to ${error}`);
|
|
102
71
|
}
|
|
103
|
-
|
|
104
|
-
return _fs2.default.readFileSync(f, 'utf8');
|
|
105
|
-
} catch (error) {
|
|
106
|
-
throw new Error(`Unable to load file ${f} due to ${error}`);
|
|
107
|
-
}
|
|
108
72
|
}
|
|
109
|
-
|
|
73
|
+
exports.loadFileAndReplaceKeywords = loadFileAndReplaceKeywords;
|
|
110
74
|
function flatten(list) {
|
|
111
|
-
|
|
75
|
+
// Flatten an multiple arrays to single array
|
|
76
|
+
return list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
|
|
112
77
|
}
|
|
113
|
-
|
|
78
|
+
exports.flatten = flatten;
|
|
114
79
|
function dumpJSON(obj, spacing = 0) {
|
|
115
|
-
|
|
80
|
+
return JSON.stringify(obj, null, spacing);
|
|
116
81
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
82
|
+
exports.dumpJSON = dumpJSON;
|
|
83
|
+
/**
|
|
84
|
+
* @template T
|
|
85
|
+
* @param {typeof import('./auth0/handlers/default').default} handler
|
|
86
|
+
* @param {T} desiredAssetState
|
|
87
|
+
* @param {T} currentAssetState
|
|
88
|
+
* @param {string[]} [objectFields=[]]
|
|
89
|
+
* @param {boolean} [allowDelete=false]
|
|
90
|
+
* @returns T
|
|
91
|
+
*/
|
|
92
|
+
function processChangedObjectFields({ handler, desiredAssetState, currentAssetState, allowDelete = false }) {
|
|
93
|
+
const desiredAssetStateWithChanges = Object.assign({}, desiredAssetState);
|
|
94
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
95
|
+
for (const fieldName of handler.objectFields) {
|
|
96
|
+
const areDesiredStateAndCurrentStateEmpty = Object.keys(desiredAssetState[fieldName] || {}).length === 0 && Object.keys(currentAssetState[fieldName] || {}).length === 0;
|
|
97
|
+
if (areDesiredStateAndCurrentStateEmpty) {
|
|
98
|
+
// If both the desired state and current state for a given object is empty, it is a no-op and can skip
|
|
99
|
+
// eslint-disable-next-line no-continue
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// A desired state that omits the objectField OR that has it as an empty object should
|
|
103
|
+
// signal that all fields should be removed (subject to ALLOW_DELETE).
|
|
104
|
+
if (desiredAssetState[fieldName] && Object.keys(desiredAssetState[fieldName]).length) {
|
|
105
|
+
// Both the current and desired state have the object field. Here's where we need to map
|
|
106
|
+
// to the APIv2 protocol of setting `null` values for deleted fields.
|
|
107
|
+
// For new and modified properties of the object field, we can just pass them through to
|
|
108
|
+
// APIv2.
|
|
109
|
+
if (currentAssetState[fieldName]) {
|
|
110
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
111
|
+
for (const currentObjectFieldPropertyName of Object.keys(currentAssetState[fieldName])) {
|
|
112
|
+
// Loop through each object property that exists currently
|
|
113
|
+
if (desiredAssetState[fieldName][currentObjectFieldPropertyName] === undefined) {
|
|
114
|
+
// If the object has a property that exists now but doesn't exist in the proposed state
|
|
115
|
+
if (allowDelete) {
|
|
116
|
+
desiredAssetStateWithChanges[fieldName][currentObjectFieldPropertyName] = null;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// If deletes aren't allowed, do outright delete the property within the object
|
|
120
|
+
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)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
142
124
|
}
|
|
143
|
-
}
|
|
144
125
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
126
|
+
else if (allowDelete) {
|
|
127
|
+
// If the desired state does not have the object field and the current state does, we
|
|
128
|
+
// should mark *all* properties for deletion by specifying an empty object.
|
|
129
|
+
//
|
|
130
|
+
// See: https://auth0.com/docs/users/metadata/manage-metadata-api#delete-user-metadata
|
|
131
|
+
desiredAssetStateWithChanges[fieldName] = {};
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
delete desiredAssetStateWithChanges[fieldName];
|
|
135
|
+
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)}`);
|
|
136
|
+
}
|
|
152
137
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return desiredAssetStateWithChanges;
|
|
138
|
+
return desiredAssetStateWithChanges;
|
|
156
139
|
}
|
|
157
|
-
|
|
140
|
+
exports.processChangedObjectFields = processChangedObjectFields;
|
|
158
141
|
function calcChanges(handler, assets, existing, identifiers = ['id', 'name'], allowDelete = false) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
} else {
|
|
172
|
-
return e[key] === value;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return false;
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
const processAssets = (id, arr) => {
|
|
179
|
-
arr.forEach(asset => {
|
|
180
|
-
let assetIdValue;
|
|
181
|
-
|
|
182
|
-
if (Array.isArray(id)) {
|
|
183
|
-
const values = id.map(i => asset[i]);
|
|
184
|
-
|
|
185
|
-
if (values.every(v => v)) {
|
|
186
|
-
assetIdValue = values.join('-');
|
|
142
|
+
// Calculate the changes required between two sets of assets.
|
|
143
|
+
const update = [];
|
|
144
|
+
let del = [...existing];
|
|
145
|
+
let create = [...assets];
|
|
146
|
+
const conflicts = [];
|
|
147
|
+
const findByKeyValue = (key, value, arr) => arr.find((e) => {
|
|
148
|
+
if (Array.isArray(key)) {
|
|
149
|
+
const values = key.map((k) => e[k]);
|
|
150
|
+
if (values.every((v) => v)) {
|
|
151
|
+
return value === values.join('-');
|
|
152
|
+
}
|
|
187
153
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (assetIdValue) {
|
|
193
|
-
const found = findByKeyValue(id, assetIdValue, del);
|
|
194
|
-
|
|
195
|
-
if (found) {
|
|
196
|
-
del = del.filter(e => e !== found);
|
|
197
|
-
create = create.filter(e => e !== asset);
|
|
198
|
-
update.push({ ...identifiers.reduce((obj, i) => {
|
|
199
|
-
if (found[i]) obj[i] = found[i];
|
|
200
|
-
return obj;
|
|
201
|
-
}, {}),
|
|
202
|
-
...(handler.objectFields.length ? processChangedObjectFields({
|
|
203
|
-
handler,
|
|
204
|
-
desiredAssetState: asset,
|
|
205
|
-
currentAssetState: found,
|
|
206
|
-
allowDelete
|
|
207
|
-
}) : asset)
|
|
208
|
-
});
|
|
154
|
+
else {
|
|
155
|
+
return e[key] === value;
|
|
209
156
|
}
|
|
210
|
-
|
|
157
|
+
return false;
|
|
211
158
|
});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
159
|
+
const processAssets = (id, arr) => {
|
|
160
|
+
arr.forEach((asset) => {
|
|
161
|
+
let assetIdValue;
|
|
162
|
+
if (Array.isArray(id)) {
|
|
163
|
+
const values = id.map((i) => asset[i]);
|
|
164
|
+
if (values.every((v) => v)) {
|
|
165
|
+
assetIdValue = values.join('-');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
assetIdValue = asset[id];
|
|
170
|
+
}
|
|
171
|
+
if (assetIdValue) {
|
|
172
|
+
const found = findByKeyValue(id, assetIdValue, del);
|
|
173
|
+
if (found) {
|
|
174
|
+
// Delete from existing
|
|
175
|
+
del = del.filter((e) => e !== found);
|
|
176
|
+
// Delete from create as it's an update
|
|
177
|
+
create = create.filter((e) => e !== asset);
|
|
178
|
+
// Append identifiers to asset
|
|
179
|
+
update.push(Object.assign(Object.assign({}, identifiers.reduce((obj, i) => {
|
|
180
|
+
if (found[i])
|
|
181
|
+
obj[i] = found[i];
|
|
182
|
+
return obj;
|
|
183
|
+
}, {})), (handler.objectFields.length
|
|
184
|
+
? processChangedObjectFields({
|
|
185
|
+
handler, desiredAssetState: asset, currentAssetState: found, allowDelete
|
|
186
|
+
})
|
|
187
|
+
: asset)));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
// Loop through identifiers (in order) to try match assets to existing
|
|
193
|
+
// If existing then update if not create
|
|
194
|
+
// The remainder will be deleted
|
|
195
|
+
for (const id of identifiers) { // eslint-disable-line
|
|
196
|
+
processAssets(id, [...create]);
|
|
197
|
+
}
|
|
198
|
+
// Check if there are assets with names that will conflict with existing names during the update process
|
|
199
|
+
// This will rename those assets to a temp random name first
|
|
200
|
+
// This assumes the first identifiers is the unique identifier
|
|
201
|
+
if (identifiers.includes('name')) {
|
|
202
|
+
const uniqueID = identifiers[0];
|
|
203
|
+
const futureAssets = [...create, ...update];
|
|
204
|
+
futureAssets.forEach((a) => {
|
|
205
|
+
// If the conflicting item is going to be deleted then skip
|
|
206
|
+
const inDeleted = del.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
|
|
207
|
+
if (!inDeleted) {
|
|
208
|
+
const conflict = existing.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
|
|
209
|
+
if (conflict) {
|
|
210
|
+
const temp = Math.random().toString(36).substr(2, 5);
|
|
211
|
+
conflicts.push(Object.assign(Object.assign({}, conflict), { name: `${conflict.name}-${temp}` }));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
del,
|
|
218
|
+
update,
|
|
219
|
+
conflicts,
|
|
220
|
+
create
|
|
221
|
+
};
|
|
243
222
|
}
|
|
244
|
-
|
|
223
|
+
exports.calcChanges = calcChanges;
|
|
245
224
|
function stripFields(obj, fields) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
225
|
+
// Strip object fields supporting dot notation (ie: a.deep.field)
|
|
226
|
+
const stripped = [];
|
|
227
|
+
const newObj = Object.assign({}, obj);
|
|
228
|
+
fields.forEach((f) => {
|
|
229
|
+
if (dot_prop_1.default.get(newObj, f) !== undefined) {
|
|
230
|
+
dot_prop_1.default.delete(newObj, f);
|
|
231
|
+
stripped.push(f);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
if (stripped) {
|
|
235
|
+
const name = ['id', 'client_id', 'template', 'name'].reduce((n, k) => newObj[k] || n, '');
|
|
236
|
+
logger_1.default.debug(`Stripping "${name}" read-only fields ${JSON.stringify(stripped)}`);
|
|
254
237
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (stripped) {
|
|
258
|
-
const name = ['id', 'client_id', 'template', 'name'].reduce((n, k) => newObj[k] || n, '');
|
|
259
|
-
|
|
260
|
-
_logger2.default.debug(`Stripping "${name}" read-only fields ${JSON.stringify(stripped)}`);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return newObj;
|
|
238
|
+
return newObj;
|
|
264
239
|
}
|
|
265
|
-
|
|
240
|
+
exports.stripFields = stripFields;
|
|
266
241
|
function getEnabledClients(assets, connection, existing, clients) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
242
|
+
// Convert enabled_clients by name to the id
|
|
243
|
+
const excludedClientsByNames = (assets.exclude && assets.exclude.clients) || [];
|
|
244
|
+
const excludedClients = convertClientNamesToIds(excludedClientsByNames, clients);
|
|
245
|
+
const enabledClients = [
|
|
246
|
+
...convertClientNamesToIds(connection.enabled_clients || [], clients).filter((item) => ![...excludedClientsByNames, ...excludedClients].includes(item))
|
|
247
|
+
];
|
|
248
|
+
// If client is excluded and in the existing connection this client is enabled, it should keep enabled
|
|
249
|
+
// If client is excluded and in the existing connection this client is disabled, it should keep disabled
|
|
250
|
+
existing.forEach((conn) => {
|
|
251
|
+
if (conn.name === connection.name) {
|
|
252
|
+
excludedClients.forEach((excludedClient) => {
|
|
253
|
+
if (conn.enabled_clients.includes(excludedClient)) {
|
|
254
|
+
enabledClients.push(excludedClient);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
275
257
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
});
|
|
279
|
-
return enabledClients;
|
|
258
|
+
});
|
|
259
|
+
return enabledClients;
|
|
280
260
|
}
|
|
281
|
-
|
|
261
|
+
exports.getEnabledClients = getEnabledClients;
|
|
282
262
|
function duplicateItems(arr, key) {
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
263
|
+
// Find duplicates objects within array that have the same key value
|
|
264
|
+
const duplicates = arr.reduce((accum, obj) => {
|
|
265
|
+
const keyValue = obj[key];
|
|
266
|
+
if (keyValue) {
|
|
267
|
+
if (!(keyValue in accum))
|
|
268
|
+
accum[keyValue] = [];
|
|
269
|
+
accum[keyValue].push(obj);
|
|
270
|
+
}
|
|
271
|
+
return accum;
|
|
272
|
+
}, {});
|
|
273
|
+
return Object.values(duplicates).filter((g) => g.length > 1);
|
|
294
274
|
}
|
|
295
|
-
|
|
275
|
+
exports.duplicateItems = duplicateItems;
|
|
296
276
|
function filterExcluded(changes, exclude) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const filter = list => list.filter(item => !exclude.includes(item.name));
|
|
309
|
-
|
|
310
|
-
return {
|
|
311
|
-
del: filter(del),
|
|
312
|
-
update: filter(update),
|
|
313
|
-
create: filter(create),
|
|
314
|
-
conflicts: filter(conflicts)
|
|
315
|
-
};
|
|
277
|
+
const { del, update, create, conflicts } = changes;
|
|
278
|
+
if (!exclude.length) {
|
|
279
|
+
return changes;
|
|
280
|
+
}
|
|
281
|
+
const filter = (list) => list.filter((item) => !exclude.includes(item.name));
|
|
282
|
+
return {
|
|
283
|
+
del: filter(del),
|
|
284
|
+
update: filter(update),
|
|
285
|
+
create: filter(create),
|
|
286
|
+
conflicts: filter(conflicts)
|
|
287
|
+
};
|
|
316
288
|
}
|
|
317
|
-
|
|
289
|
+
exports.filterExcluded = filterExcluded;
|
|
318
290
|
function areArraysEquals(x, y) {
|
|
319
|
-
|
|
320
|
-
}
|
|
291
|
+
return lodash_1.default.isEqual(x && x.sort(), y && y.sort());
|
|
292
|
+
}
|
|
293
|
+
exports.areArraysEquals = areArraysEquals;
|