@rockcarver/frodo-lib 0.11.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/.eslintrc +32 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +30 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/README.md +121 -0
- package/.github/workflows/pipeline.yml +287 -0
- package/.prettierrc +6 -0
- package/CHANGELOG.md +512 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/LICENSE +21 -0
- package/README.md +8 -0
- package/docs/CONTRIBUTE.md +96 -0
- package/docs/PIPELINE.md +169 -0
- package/docs/images/npm_versioning_guidelines.png +0 -0
- package/docs/images/release_pipeline.png +0 -0
- package/jsconfig.json +6 -0
- package/package.json +95 -0
- package/resources/sampleEntitiesFile.json +8 -0
- package/resources/sampleEnvFile.env +2 -0
- package/src/api/AuthenticateApi.js +33 -0
- package/src/api/BaseApi.js +242 -0
- package/src/api/CirclesOfTrustApi.js +87 -0
- package/src/api/EmailTemplateApi.js +37 -0
- package/src/api/IdmConfigApi.js +88 -0
- package/src/api/LogApi.js +45 -0
- package/src/api/ManagedObjectApi.js +62 -0
- package/src/api/OAuth2ClientApi.js +69 -0
- package/src/api/OAuth2OIDCApi.js +73 -0
- package/src/api/OAuth2ProviderApi.js +32 -0
- package/src/api/RealmApi.js +99 -0
- package/src/api/Saml2Api.js +176 -0
- package/src/api/ScriptApi.js +84 -0
- package/src/api/SecretsApi.js +151 -0
- package/src/api/ServerInfoApi.js +41 -0
- package/src/api/SocialIdentityProvidersApi.js +114 -0
- package/src/api/StartupApi.js +45 -0
- package/src/api/ThemeApi.js +181 -0
- package/src/api/TreeApi.js +207 -0
- package/src/api/VariablesApi.js +104 -0
- package/src/api/utils/ApiUtils.js +77 -0
- package/src/api/utils/ApiUtils.test.js +96 -0
- package/src/api/utils/Base64.js +62 -0
- package/src/index.js +32 -0
- package/src/index.test.js +13 -0
- package/src/ops/AdminOps.js +901 -0
- package/src/ops/AuthenticateOps.js +342 -0
- package/src/ops/CirclesOfTrustOps.js +350 -0
- package/src/ops/ConnectionProfileOps.js +254 -0
- package/src/ops/EmailTemplateOps.js +326 -0
- package/src/ops/IdmOps.js +227 -0
- package/src/ops/IdpOps.js +342 -0
- package/src/ops/JourneyOps.js +2026 -0
- package/src/ops/LogOps.js +357 -0
- package/src/ops/ManagedObjectOps.js +34 -0
- package/src/ops/OAuth2ClientOps.js +151 -0
- package/src/ops/OrganizationOps.js +85 -0
- package/src/ops/RealmOps.js +139 -0
- package/src/ops/SamlOps.js +541 -0
- package/src/ops/ScriptOps.js +211 -0
- package/src/ops/SecretsOps.js +288 -0
- package/src/ops/StartupOps.js +114 -0
- package/src/ops/ThemeOps.js +379 -0
- package/src/ops/VariablesOps.js +185 -0
- package/src/ops/templates/OAuth2ClientTemplate.json +270 -0
- package/src/ops/templates/OrgModelUserAttributesTemplate.json +149 -0
- package/src/ops/templates/cloud/GenericExtensionAttributesTemplate.json +392 -0
- package/src/ops/templates/cloud/managed.json +4119 -0
- package/src/ops/utils/Console.js +434 -0
- package/src/ops/utils/DataProtection.js +92 -0
- package/src/ops/utils/DataProtection.test.js +28 -0
- package/src/ops/utils/ExportImportUtils.js +146 -0
- package/src/ops/utils/ExportImportUtils.test.js +119 -0
- package/src/ops/utils/OpsUtils.js +76 -0
- package/src/ops/utils/Wordwrap.js +11 -0
- package/src/storage/SessionStorage.js +45 -0
- package/src/storage/StaticStorage.js +15 -0
- package/test/e2e/journey/baseline/ForgottenUsername.journey.json +216 -0
- package/test/e2e/journey/baseline/Login.journey.json +205 -0
- package/test/e2e/journey/baseline/PasswordGrant.journey.json +139 -0
- package/test/e2e/journey/baseline/ProgressiveProfile.journey.json +198 -0
- package/test/e2e/journey/baseline/Registration.journey.json +249 -0
- package/test/e2e/journey/baseline/ResetPassword.journey.json +268 -0
- package/test/e2e/journey/baseline/UpdatePassword.journey.json +323 -0
- package/test/e2e/journey/baseline/allAlphaJourneys.journeys.json +1520 -0
- package/test/e2e/journey/delete/ForgottenUsername.journey.json +216 -0
- package/test/e2e/journey/delete/Login.journey.json +205 -0
- package/test/e2e/journey/delete/PasswordGrant.journey.json +139 -0
- package/test/e2e/journey/delete/ProgressiveProfile.journey.json +198 -0
- package/test/e2e/journey/delete/Registration.journey.json +249 -0
- package/test/e2e/journey/delete/ResetPassword.journey.json +268 -0
- package/test/e2e/journey/delete/UpdatePassword.journey.json +323 -0
- package/test/e2e/journey/delete/deleteMe.journey.json +230 -0
- package/test/e2e/journey/list/Disabled.journey.json +43 -0
- package/test/e2e/journey/list/ForgottenUsername.journey.json +216 -0
- package/test/e2e/journey/list/Login.journey.json +205 -0
- package/test/e2e/journey/list/PasswordGrant.journey.json +139 -0
- package/test/e2e/journey/list/ProgressiveProfile.journey.json +198 -0
- package/test/e2e/journey/list/Registration.journey.json +249 -0
- package/test/e2e/journey/list/ResetPassword.journey.json +268 -0
- package/test/e2e/journey/list/UpdatePassword.journey.json +323 -0
- package/test/e2e/setup.js +107 -0
- package/test/e2e/theme/baseline/Contrast.theme.json +95 -0
- package/test/e2e/theme/baseline/Highlander.theme.json +95 -0
- package/test/e2e/theme/baseline/Robroy.theme.json +95 -0
- package/test/e2e/theme/baseline/Starter-Theme.theme.json +94 -0
- package/test/e2e/theme/baseline/Zardoz.theme.json +95 -0
- package/test/e2e/theme/import/Contrast.theme.json +95 -0
- package/test/e2e/theme/import/Highlander.theme.json +95 -0
- package/test/e2e/theme/import/Robroy.theme.json +95 -0
- package/test/e2e/theme/import/Starter-Theme.theme.json +94 -0
- package/test/e2e/theme/import/Zardoz.default.theme.json +95 -0
- package/test/fs_tmp/.gitkeep +2 -0
- package/test/global/setup.js +65 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import fse from 'fs-extra';
|
|
3
|
+
import replaceall from 'replaceall';
|
|
4
|
+
import propertiesReader from 'properties-reader';
|
|
5
|
+
import {
|
|
6
|
+
getAllConfigEntities,
|
|
7
|
+
getConfigEntity,
|
|
8
|
+
queryAllManagedObjectsByType,
|
|
9
|
+
} from '../api/IdmConfigApi.js';
|
|
10
|
+
import { printMessage, showSpinner, succeedSpinner } from './utils/Console.js';
|
|
11
|
+
import { getTypedFilename } from './utils/ExportImportUtils.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* List all IDM configuration objects
|
|
15
|
+
*/
|
|
16
|
+
export async function listAllConfigEntities() {
|
|
17
|
+
let configEntities = [];
|
|
18
|
+
try {
|
|
19
|
+
configEntities = (await getAllConfigEntities()).data;
|
|
20
|
+
} catch (getAllConfigEntitiesError) {
|
|
21
|
+
printMessage(getAllConfigEntitiesError, 'error');
|
|
22
|
+
printMessage(
|
|
23
|
+
`Error getting config entities: ${getAllConfigEntitiesError}`,
|
|
24
|
+
'error'
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
if ('configurations' in configEntities) {
|
|
28
|
+
configEntities.configurations.forEach((configEntity) => {
|
|
29
|
+
printMessage(`${configEntity._id}`, 'data');
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Export an IDM configuration object.
|
|
36
|
+
* @param {String} id the desired configuration object
|
|
37
|
+
* @param {String} file optional export file
|
|
38
|
+
*/
|
|
39
|
+
export async function exportConfigEntity(id, file) {
|
|
40
|
+
let fileName = file;
|
|
41
|
+
if (!fileName) {
|
|
42
|
+
fileName = getTypedFilename(`${id}`, 'idm');
|
|
43
|
+
}
|
|
44
|
+
const configEntity = (await getConfigEntity(id)).data;
|
|
45
|
+
fs.writeFile(fileName, JSON.stringify(configEntity, null, 2), (err) => {
|
|
46
|
+
if (err) {
|
|
47
|
+
return printMessage(`ERROR - can't save ${id} export to file`, 'error');
|
|
48
|
+
}
|
|
49
|
+
return '';
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Export all IDM configuration objects into separate JSON files in a directory specified by <directory>
|
|
55
|
+
* @param {String} directory export directory
|
|
56
|
+
*/
|
|
57
|
+
export async function exportAllRawConfigEntities(directory) {
|
|
58
|
+
let configEntities = [];
|
|
59
|
+
try {
|
|
60
|
+
configEntities = (await getAllConfigEntities()).data;
|
|
61
|
+
} catch (getAllConfigEntitiesError) {
|
|
62
|
+
printMessage(getAllConfigEntitiesError, 'error');
|
|
63
|
+
printMessage(
|
|
64
|
+
`Error getting config entities: ${getAllConfigEntitiesError}`,
|
|
65
|
+
'error'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if ('configurations' in configEntities) {
|
|
69
|
+
if (!fs.existsSync(directory)) {
|
|
70
|
+
fs.mkdirSync(directory);
|
|
71
|
+
}
|
|
72
|
+
showSpinner('Exporting config objects...');
|
|
73
|
+
const entityPromises = [];
|
|
74
|
+
configEntities.configurations.forEach((x) => {
|
|
75
|
+
entityPromises.push(
|
|
76
|
+
getConfigEntity(x._id)
|
|
77
|
+
.then((response) => response.data)
|
|
78
|
+
.catch((getConfigEntityError) => {
|
|
79
|
+
if (
|
|
80
|
+
!(
|
|
81
|
+
getConfigEntityError.response.status === 403 &&
|
|
82
|
+
getConfigEntityError.response.data.message ===
|
|
83
|
+
'This operation is not available in ForgeRock Identity Cloud.'
|
|
84
|
+
)
|
|
85
|
+
) {
|
|
86
|
+
printMessage(getConfigEntityError, 'error');
|
|
87
|
+
printMessage(
|
|
88
|
+
`Error getting config entity: ${getConfigEntityError}`,
|
|
89
|
+
'error'
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
Promise.all(entityPromises).then((result) => {
|
|
96
|
+
// console.log(result);
|
|
97
|
+
result.forEach((item) => {
|
|
98
|
+
if (item != null) {
|
|
99
|
+
fse.outputFile(
|
|
100
|
+
`${directory}/${item._id}.json`,
|
|
101
|
+
JSON.stringify(item, null, 2),
|
|
102
|
+
// eslint-disable-next-line consistent-return
|
|
103
|
+
(err) => {
|
|
104
|
+
if (err) {
|
|
105
|
+
return printMessage(
|
|
106
|
+
`ERROR - can't save config ${item._id} to file - ${err}`,
|
|
107
|
+
'error'
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
succeedSpinner();
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Export all IDM configuration objects
|
|
121
|
+
* @param {String} directory export directory
|
|
122
|
+
* @param {String} entitiesFile JSON file that specifies the config entities to export/import
|
|
123
|
+
* @param {String} envFile File that defines environment specific variables for replacement during configuration export/import
|
|
124
|
+
*/
|
|
125
|
+
export async function exportAllConfigEntities(
|
|
126
|
+
directory,
|
|
127
|
+
entitiesFile,
|
|
128
|
+
envFile
|
|
129
|
+
) {
|
|
130
|
+
let entriesToExport = [];
|
|
131
|
+
// read list of entities to export
|
|
132
|
+
fs.readFile(entitiesFile, 'utf8', async (err, data) => {
|
|
133
|
+
if (err) throw err;
|
|
134
|
+
const entriesData = JSON.parse(data);
|
|
135
|
+
entriesToExport = entriesData.idm;
|
|
136
|
+
// console.log(`entriesToExport ${entriesToExport}`);
|
|
137
|
+
|
|
138
|
+
// read list of configs to parameterize for environment specific values
|
|
139
|
+
const envParams = propertiesReader(envFile);
|
|
140
|
+
|
|
141
|
+
let configEntities = [];
|
|
142
|
+
try {
|
|
143
|
+
configEntities = (await getAllConfigEntities()).data;
|
|
144
|
+
} catch (getAllConfigEntitiesError) {
|
|
145
|
+
printMessage(getAllConfigEntitiesError, 'error');
|
|
146
|
+
printMessage(
|
|
147
|
+
`Error getting config entities: ${getAllConfigEntitiesError}`,
|
|
148
|
+
'error'
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
if ('configurations' in configEntities) {
|
|
152
|
+
// create export directory if not exist
|
|
153
|
+
if (!fs.existsSync(directory)) {
|
|
154
|
+
fs.mkdirSync(directory);
|
|
155
|
+
}
|
|
156
|
+
showSpinner('Exporting config objects...');
|
|
157
|
+
const entityPromises = [];
|
|
158
|
+
configEntities.configurations.forEach((x) => {
|
|
159
|
+
if (entriesToExport.includes(x._id)) {
|
|
160
|
+
// console.log(`- ${x._id}`);
|
|
161
|
+
entityPromises.push(
|
|
162
|
+
getConfigEntity(x._id).then((response) => response.data)
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
Promise.all(entityPromises).then((result) => {
|
|
167
|
+
// console.log(result);
|
|
168
|
+
result.forEach((item) => {
|
|
169
|
+
if (item != null) {
|
|
170
|
+
let configEntityString = JSON.stringify(item, null, 2);
|
|
171
|
+
envParams.each((key, value) => {
|
|
172
|
+
configEntityString = replaceall(
|
|
173
|
+
value,
|
|
174
|
+
`\${${key}}`,
|
|
175
|
+
configEntityString
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
fse.outputFile(
|
|
179
|
+
`${directory}/${item._id}.json`,
|
|
180
|
+
JSON.stringify(item, null, 2),
|
|
181
|
+
// eslint-disable-next-line consistent-return
|
|
182
|
+
(error) => {
|
|
183
|
+
if (err) {
|
|
184
|
+
return printMessage(
|
|
185
|
+
`ERROR - can't save config ${item._id} to file - ${error}`,
|
|
186
|
+
'error'
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
succeedSpinner();
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Count number of managed objects of a given type
|
|
201
|
+
* @param {String} type managed object type, e.g. alpha_user
|
|
202
|
+
*/
|
|
203
|
+
export async function countManagedObjects(type) {
|
|
204
|
+
let count = 0;
|
|
205
|
+
let result = {
|
|
206
|
+
result: [],
|
|
207
|
+
resultCount: 0,
|
|
208
|
+
pagedResultsCookie: null,
|
|
209
|
+
totalPagedResultsPolicy: 'NONE',
|
|
210
|
+
totalPagedResults: -1,
|
|
211
|
+
remainingPagedResults: -1,
|
|
212
|
+
};
|
|
213
|
+
try {
|
|
214
|
+
do {
|
|
215
|
+
// eslint-disable-next-line no-await-in-loop
|
|
216
|
+
result = (
|
|
217
|
+
await queryAllManagedObjectsByType(type, [], result.pagedResultsCookie)
|
|
218
|
+
).data;
|
|
219
|
+
count += result.resultCount;
|
|
220
|
+
// printMessage(result);
|
|
221
|
+
} while (result.pagedResultsCookie);
|
|
222
|
+
printMessage(`${type}: ${count}`);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
printMessage(error.response.data, 'error');
|
|
225
|
+
printMessage(`Error querying managed objects by type: ${error}`, 'error');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import {
|
|
3
|
+
getSocialIdentityProviders,
|
|
4
|
+
putProviderByTypeAndId,
|
|
5
|
+
} from '../api/SocialIdentityProvidersApi.js';
|
|
6
|
+
import { getScript } from '../api/ScriptApi.js';
|
|
7
|
+
import { createOrUpdateScript } from './ScriptOps.js';
|
|
8
|
+
import {
|
|
9
|
+
convertBase64TextToArray,
|
|
10
|
+
convertTextArrayToBase64,
|
|
11
|
+
getRealmString,
|
|
12
|
+
getTypedFilename,
|
|
13
|
+
saveJsonToFile,
|
|
14
|
+
validateImport,
|
|
15
|
+
} from './utils/ExportImportUtils.js';
|
|
16
|
+
import {
|
|
17
|
+
printMessage,
|
|
18
|
+
createProgressBar,
|
|
19
|
+
updateProgressBar,
|
|
20
|
+
stopProgressBar,
|
|
21
|
+
} from './utils/Console.js';
|
|
22
|
+
|
|
23
|
+
// use a function vs a template variable to avoid problems in loops
|
|
24
|
+
function getFileDataTemplate() {
|
|
25
|
+
return {
|
|
26
|
+
meta: {},
|
|
27
|
+
script: {},
|
|
28
|
+
idp: {},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* List providers
|
|
34
|
+
*/
|
|
35
|
+
export async function listProviders() {
|
|
36
|
+
getSocialIdentityProviders()
|
|
37
|
+
.then((response) => {
|
|
38
|
+
response.data.result.sort((a, b) => a._id.localeCompare(b._id));
|
|
39
|
+
response.data.result.forEach((socialIdentityProvider) => {
|
|
40
|
+
printMessage(`${socialIdentityProvider._id}`, 'data');
|
|
41
|
+
});
|
|
42
|
+
})
|
|
43
|
+
.catch((err) => {
|
|
44
|
+
printMessage(`listProviders ERROR: ${err.message}`, 'error');
|
|
45
|
+
printMessage(err, 'error');
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get social identity provider by id
|
|
51
|
+
* @param {String} id social identity provider id/name
|
|
52
|
+
* @returns {Promise} a promise that resolves a social identity provider object
|
|
53
|
+
*/
|
|
54
|
+
export async function getSocialIdentityProviderById(id) {
|
|
55
|
+
return getSocialIdentityProviders().then((response) => {
|
|
56
|
+
const foundProviders = response.data.result.filter(
|
|
57
|
+
(provider) => provider._id === id
|
|
58
|
+
);
|
|
59
|
+
switch (foundProviders.length) {
|
|
60
|
+
case 1:
|
|
61
|
+
return foundProviders[0];
|
|
62
|
+
case 0:
|
|
63
|
+
throw new Error(`Provider '${id}' not found`);
|
|
64
|
+
default:
|
|
65
|
+
throw new Error(`${foundProviders.length} providers '${id}' found`);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Export provider by id
|
|
72
|
+
* @param {String} id provider id/name
|
|
73
|
+
* @param {String} file optional export file name
|
|
74
|
+
*/
|
|
75
|
+
export async function exportProvider(id, file = null) {
|
|
76
|
+
let fileName = file;
|
|
77
|
+
if (!fileName) {
|
|
78
|
+
fileName = getTypedFilename(id, 'idp');
|
|
79
|
+
}
|
|
80
|
+
createProgressBar(1, `Exporting ${id}`);
|
|
81
|
+
try {
|
|
82
|
+
const idpData = await getSocialIdentityProviderById(id);
|
|
83
|
+
updateProgressBar(`Writing file ${fileName}`);
|
|
84
|
+
const fileData = getFileDataTemplate();
|
|
85
|
+
fileData.idp[idpData._id] = idpData;
|
|
86
|
+
if (idpData.transform) {
|
|
87
|
+
const scriptData = (await getScript(idpData.transform)).data;
|
|
88
|
+
scriptData.script = convertBase64TextToArray(scriptData.script);
|
|
89
|
+
fileData.script[idpData.transform] = scriptData;
|
|
90
|
+
}
|
|
91
|
+
saveJsonToFile(fileData, fileName);
|
|
92
|
+
stopProgressBar(`Exported ${id.brightCyan} to ${fileName.brightCyan}.`);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
stopProgressBar(`${err}`);
|
|
95
|
+
printMessage(`${err}`, 'error');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Export all providers
|
|
101
|
+
* @param {String} file optional export file name
|
|
102
|
+
*/
|
|
103
|
+
export async function exportProvidersToFile(file) {
|
|
104
|
+
let fileName = file;
|
|
105
|
+
if (!fileName) {
|
|
106
|
+
fileName = getTypedFilename(`all${getRealmString()}Providers`, 'idp');
|
|
107
|
+
}
|
|
108
|
+
const fileData = getFileDataTemplate();
|
|
109
|
+
const allIdpsData = (await getSocialIdentityProviders()).data.result;
|
|
110
|
+
createProgressBar(allIdpsData.length, 'Exporting providers');
|
|
111
|
+
for (const idpData of allIdpsData) {
|
|
112
|
+
updateProgressBar(`Exporting provider ${idpData._id}`);
|
|
113
|
+
fileData.idp[idpData._id] = idpData;
|
|
114
|
+
if (idpData.transform) {
|
|
115
|
+
// eslint-disable-next-line no-await-in-loop
|
|
116
|
+
const scriptData = (await getScript(idpData.transform)).data;
|
|
117
|
+
scriptData.script = convertBase64TextToArray(scriptData.script);
|
|
118
|
+
fileData.script[idpData.transform] = scriptData;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
saveJsonToFile(fileData, fileName);
|
|
122
|
+
stopProgressBar(`${allIdpsData.length} providers exported to ${fileName}.`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Export all providers to individual files
|
|
127
|
+
*/
|
|
128
|
+
export async function exportProvidersToFiles() {
|
|
129
|
+
const allIdpsData = await (await getSocialIdentityProviders()).data.result;
|
|
130
|
+
// printMessage(allIdpsData, 'data');
|
|
131
|
+
createProgressBar(allIdpsData.length, 'Exporting providers');
|
|
132
|
+
for (const idpData of allIdpsData) {
|
|
133
|
+
updateProgressBar(`Writing provider ${idpData._id}`);
|
|
134
|
+
const fileName = getTypedFilename(idpData._id, 'idp');
|
|
135
|
+
const fileData = getFileDataTemplate();
|
|
136
|
+
fileData.idp[idpData._id] = idpData;
|
|
137
|
+
if (idpData.transform) {
|
|
138
|
+
// eslint-disable-next-line no-await-in-loop
|
|
139
|
+
const scriptData = (await getScript(idpData.transform)).data;
|
|
140
|
+
scriptData.script = convertBase64TextToArray(scriptData.script);
|
|
141
|
+
fileData.script[idpData.transform] = scriptData;
|
|
142
|
+
}
|
|
143
|
+
saveJsonToFile(fileData, fileName);
|
|
144
|
+
}
|
|
145
|
+
stopProgressBar(`${allIdpsData.length} providers exported.`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Import provider by id/name
|
|
150
|
+
* @param {String} id provider id/name
|
|
151
|
+
* @param {String} file import file name
|
|
152
|
+
*/
|
|
153
|
+
export async function importProviderById(id, file) {
|
|
154
|
+
fs.readFile(file, 'utf8', async (err, data) => {
|
|
155
|
+
if (err) throw err;
|
|
156
|
+
const fileData = JSON.parse(data);
|
|
157
|
+
if (validateImport(fileData.meta)) {
|
|
158
|
+
createProgressBar(1, 'Importing provider...');
|
|
159
|
+
let found = false;
|
|
160
|
+
for (const idpId in fileData.idp) {
|
|
161
|
+
if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
|
|
162
|
+
if (idpId === id) {
|
|
163
|
+
found = true;
|
|
164
|
+
updateProgressBar(`Importing ${fileData.idp[idpId]._id}`);
|
|
165
|
+
const scriptId = fileData.idp[idpId].transform;
|
|
166
|
+
const scriptData = fileData.script[scriptId];
|
|
167
|
+
if (scriptId && scriptData) {
|
|
168
|
+
scriptData.script = convertTextArrayToBase64(scriptData.script);
|
|
169
|
+
// eslint-disable-next-line no-await-in-loop
|
|
170
|
+
await createOrUpdateScript(
|
|
171
|
+
fileData.idp[idpId].transform,
|
|
172
|
+
fileData.script[fileData.idp[idpId].transform]
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
putProviderByTypeAndId(
|
|
176
|
+
fileData.idp[idpId]._type._id,
|
|
177
|
+
idpId,
|
|
178
|
+
fileData.idp[idpId]
|
|
179
|
+
)
|
|
180
|
+
.then(() => {
|
|
181
|
+
stopProgressBar(`Successfully imported provider ${id}.`);
|
|
182
|
+
})
|
|
183
|
+
.catch((importProviderErr) => {
|
|
184
|
+
stopProgressBar(
|
|
185
|
+
`Error importing provider ${fileData.idp[idpId]._id}`
|
|
186
|
+
);
|
|
187
|
+
printMessage(`\nError importing provider ${id}`, 'error');
|
|
188
|
+
printMessage(importProviderErr.response.data, 'error');
|
|
189
|
+
});
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (!found) {
|
|
195
|
+
stopProgressBar(
|
|
196
|
+
`Provider ${id.brightCyan} not found in ${file.brightCyan}!`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
printMessage('Import validation failed...', 'error');
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Import first provider from file
|
|
207
|
+
* @param {String} file import file name
|
|
208
|
+
*/
|
|
209
|
+
export async function importFirstProvider(file) {
|
|
210
|
+
fs.readFile(file, 'utf8', async (err, data) => {
|
|
211
|
+
if (err) throw err;
|
|
212
|
+
const fileData = JSON.parse(data);
|
|
213
|
+
if (validateImport(fileData.meta)) {
|
|
214
|
+
createProgressBar(1, 'Importing provider...');
|
|
215
|
+
for (const idpId in fileData.idp) {
|
|
216
|
+
if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
|
|
217
|
+
updateProgressBar(`Importing ${fileData.idp[idpId]._id}`);
|
|
218
|
+
const scriptId = fileData.idp[idpId].transform;
|
|
219
|
+
const scriptData = fileData.script[scriptId];
|
|
220
|
+
if (scriptId && scriptData) {
|
|
221
|
+
scriptData.script = convertTextArrayToBase64(scriptData.script);
|
|
222
|
+
// eslint-disable-next-line no-await-in-loop
|
|
223
|
+
await createOrUpdateScript(
|
|
224
|
+
fileData.idp[idpId].transform,
|
|
225
|
+
fileData.script[fileData.idp[idpId].transform]
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
putProviderByTypeAndId(
|
|
229
|
+
fileData.idp[idpId]._type._id,
|
|
230
|
+
idpId,
|
|
231
|
+
fileData.idp[idpId]
|
|
232
|
+
).then((result) => {
|
|
233
|
+
if (result == null) {
|
|
234
|
+
stopProgressBar(
|
|
235
|
+
`Error importing provider ${fileData.idp[idpId]._id}`
|
|
236
|
+
);
|
|
237
|
+
printMessage(
|
|
238
|
+
`Error importing provider ${fileData.idp[idpId]._id}`,
|
|
239
|
+
'error'
|
|
240
|
+
);
|
|
241
|
+
} else {
|
|
242
|
+
stopProgressBar(
|
|
243
|
+
`Successfully imported provider ${fileData.idp[idpId]._id}.`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
printMessage('Import validation failed...', 'error');
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Import all providers from file
|
|
258
|
+
* @param {String} file import file name
|
|
259
|
+
*/
|
|
260
|
+
export async function importProvidersFromFile(file) {
|
|
261
|
+
fs.readFile(file, 'utf8', async (err, data) => {
|
|
262
|
+
if (err) throw err;
|
|
263
|
+
const fileData = JSON.parse(data);
|
|
264
|
+
if (validateImport(fileData.meta)) {
|
|
265
|
+
createProgressBar(
|
|
266
|
+
Object.keys(fileData.idp).length,
|
|
267
|
+
'Importing providers...'
|
|
268
|
+
);
|
|
269
|
+
for (const idpId in fileData.idp) {
|
|
270
|
+
if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
|
|
271
|
+
const scriptId = fileData.idp[idpId].transform;
|
|
272
|
+
const scriptData = fileData.script[scriptId];
|
|
273
|
+
if (scriptId && scriptData) {
|
|
274
|
+
scriptData.script = convertTextArrayToBase64(scriptData.script);
|
|
275
|
+
// eslint-disable-next-line no-await-in-loop
|
|
276
|
+
await createOrUpdateScript(
|
|
277
|
+
fileData.idp[idpId].transform,
|
|
278
|
+
fileData.script[fileData.idp[idpId].transform]
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
// eslint-disable-next-line no-await-in-loop
|
|
282
|
+
const result = await putProviderByTypeAndId(
|
|
283
|
+
fileData.idp[idpId]._type._id,
|
|
284
|
+
idpId,
|
|
285
|
+
fileData.idp[idpId]
|
|
286
|
+
);
|
|
287
|
+
if (!result) {
|
|
288
|
+
updateProgressBar(
|
|
289
|
+
`Successfully imported ${fileData.idp[idpId].name}`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
stopProgressBar(`Providers imported.`);
|
|
295
|
+
} else {
|
|
296
|
+
printMessage('Import validation failed...', 'error');
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Import providers from *.idp.json files in current working directory
|
|
303
|
+
*/
|
|
304
|
+
export async function importProvidersFromFiles() {
|
|
305
|
+
const names = fs.readdirSync('.');
|
|
306
|
+
const jsonFiles = names.filter((name) =>
|
|
307
|
+
name.toLowerCase().endsWith('.idp.json')
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
createProgressBar(jsonFiles.length, 'Importing providers...');
|
|
311
|
+
let total = 0;
|
|
312
|
+
for (const file of jsonFiles) {
|
|
313
|
+
const data = fs.readFileSync(file, 'utf8');
|
|
314
|
+
const fileData = JSON.parse(data);
|
|
315
|
+
if (validateImport(fileData.meta)) {
|
|
316
|
+
const count = Object.keys(fileData.idp).length;
|
|
317
|
+
total += count;
|
|
318
|
+
for (const idpId in fileData.idp) {
|
|
319
|
+
if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
|
|
320
|
+
// eslint-disable-next-line no-await-in-loop
|
|
321
|
+
const result = await putProviderByTypeAndId(
|
|
322
|
+
fileData.idp[idpId]._type._id,
|
|
323
|
+
idpId,
|
|
324
|
+
fileData.idp[idpId]
|
|
325
|
+
);
|
|
326
|
+
if (result == null) {
|
|
327
|
+
printMessage(
|
|
328
|
+
`Error importing ${count} providers from ${file}`,
|
|
329
|
+
'error'
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
updateProgressBar(`Imported ${count} provider(s) from ${file}`);
|
|
335
|
+
} else {
|
|
336
|
+
printMessage(`Validation of ${file} failed!`, 'error');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
stopProgressBar(
|
|
340
|
+
`Finished importing ${total} provider(s) from ${jsonFiles.length} file(s).`
|
|
341
|
+
);
|
|
342
|
+
}
|