@rockcarver/frodo-lib 0.17.2 → 0.17.4

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 (94) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/cjs/api/ApiTypes.js +16 -16
  3. package/cjs/api/ApiTypes.js.map +1 -1
  4. package/cjs/api/IdmConfigApi.js +28 -7
  5. package/cjs/api/IdmConfigApi.js.map +1 -1
  6. package/cjs/api/Saml2Api.js +36 -14
  7. package/cjs/api/Saml2Api.js.map +1 -1
  8. package/cjs/api/ScriptApi.js +23 -2
  9. package/cjs/api/ScriptApi.js.map +1 -1
  10. package/cjs/api/SocialIdentityProvidersApi.js +22 -0
  11. package/cjs/api/SocialIdentityProvidersApi.js.map +1 -1
  12. package/cjs/index.js +3 -1
  13. package/cjs/index.js.map +1 -1
  14. package/cjs/ops/AgentOps.test.js.map +1 -1
  15. package/cjs/ops/ConnectionProfileOps.test.js.map +1 -1
  16. package/cjs/ops/EmailTemplateOps.test.js.map +1 -1
  17. package/cjs/ops/IdmOps.test.js.map +1 -1
  18. package/cjs/ops/IdpOps.js +182 -275
  19. package/cjs/ops/IdpOps.js.map +1 -1
  20. package/cjs/ops/IdpOps.test.js.map +1 -1
  21. package/cjs/ops/JourneyOps.js +49 -35
  22. package/cjs/ops/JourneyOps.js.map +1 -1
  23. package/cjs/ops/JourneyOps.test.js.map +1 -1
  24. package/cjs/ops/OpsTypes.js.map +1 -1
  25. package/cjs/ops/Saml2Ops.js +104 -57
  26. package/cjs/ops/Saml2Ops.js.map +1 -1
  27. package/cjs/ops/Saml2Ops.test.js.map +1 -1
  28. package/cjs/ops/ScriptOps.js +193 -186
  29. package/cjs/ops/ScriptOps.js.map +1 -1
  30. package/cjs/ops/ScriptOps.test.js.map +1 -0
  31. package/cjs/test/mocks/ForgeRockApiMockEngine.js +6 -108
  32. package/cjs/test/mocks/ForgeRockApiMockEngine.js.map +1 -1
  33. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney1.journey.json +148 -0
  34. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney2.journey.json +76 -0
  35. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney3.journey.json +873 -0
  36. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney4.journey.json +930 -0
  37. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney5.journey.json +873 -0
  38. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney6.journey.json +148 -0
  39. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney7.journey.json +148 -0
  40. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney8.journey.json +148 -0
  41. package/cjs/test/mocks/JourneyOps/importJourney/FrodoTestJourney9.journey.json +148 -0
  42. package/esm/api/ApiTypes.mjs +16 -16
  43. package/esm/api/IdmConfigApi.mjs +19 -4
  44. package/esm/api/Saml2Api.mjs +17 -1
  45. package/esm/api/ScriptApi.mjs +17 -2
  46. package/esm/api/SocialIdentityProvidersApi.mjs +16 -0
  47. package/esm/index.mjs +1 -0
  48. package/esm/ops/AgentOps.test.mjs +1 -1
  49. package/esm/ops/ConnectionProfileOps.test.mjs +94 -54
  50. package/esm/ops/EmailTemplateOps.test.mjs +140 -28
  51. package/esm/ops/IdmOps.test.mjs +159 -62
  52. package/esm/ops/IdpOps.mjs +140 -211
  53. package/esm/ops/IdpOps.test.mjs +651 -52
  54. package/esm/ops/JourneyOps.mjs +30 -21
  55. package/esm/ops/JourneyOps.test.mjs +220 -246
  56. package/esm/ops/Saml2Ops.mjs +66 -31
  57. package/esm/ops/Saml2Ops.test.mjs +399 -333
  58. package/esm/ops/ScriptOps.mjs +148 -152
  59. package/esm/ops/ScriptOps.test.mjs +282 -0
  60. package/esm/test/mocks/ForgeRockApiMockEngine.mjs +5 -98
  61. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney1.journey.json +148 -0
  62. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney2.journey.json +76 -0
  63. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney3.journey.json +873 -0
  64. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney4.journey.json +930 -0
  65. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney5.journey.json +873 -0
  66. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney6.journey.json +148 -0
  67. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney7.journey.json +148 -0
  68. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney8.journey.json +148 -0
  69. package/esm/test/mocks/JourneyOps/importJourney/FrodoTestJourney9.journey.json +148 -0
  70. package/package.json +10 -2
  71. package/types/api/ApiTypes.d.ts +21 -21
  72. package/types/api/ApiTypes.d.ts.map +1 -1
  73. package/types/api/IdmConfigApi.d.ts +11 -5
  74. package/types/api/IdmConfigApi.d.ts.map +1 -1
  75. package/types/api/Saml2Api.d.ts +8 -1
  76. package/types/api/Saml2Api.d.ts.map +1 -1
  77. package/types/api/ScriptApi.d.ts +7 -1
  78. package/types/api/ScriptApi.d.ts.map +1 -1
  79. package/types/api/SocialIdentityProvidersApi.d.ts +7 -0
  80. package/types/api/SocialIdentityProvidersApi.d.ts.map +1 -1
  81. package/types/index.d.ts +1 -0
  82. package/types/index.d.ts.map +1 -1
  83. package/types/ops/IdpOps.d.ts +31 -24
  84. package/types/ops/IdpOps.d.ts.map +1 -1
  85. package/types/ops/JourneyOps.d.ts +17 -3
  86. package/types/ops/JourneyOps.d.ts.map +1 -1
  87. package/types/ops/OpsTypes.d.ts +1 -1
  88. package/types/ops/OpsTypes.d.ts.map +1 -1
  89. package/types/ops/Saml2Ops.d.ts +24 -12
  90. package/types/ops/Saml2Ops.d.ts.map +1 -1
  91. package/types/ops/ScriptOps.d.ts +56 -20
  92. package/types/ops/ScriptOps.d.ts.map +1 -1
  93. package/types/test/mocks/ForgeRockApiMockEngine.d.ts +2 -11
  94. package/types/test/mocks/ForgeRockApiMockEngine.d.ts.map +1 -1
@@ -1,72 +1,169 @@
1
- import fs from 'fs';
2
- import axios from 'axios';
3
- import MockAdapter from 'axios-mock-adapter';
4
- import { fileURLToPath } from 'url';
5
- import { Idm, state } from '../index';
6
- import * as global from '../storage/StaticStorage';
7
- import { mockGetAllConfigEntities, mockPutConfigEntity, mockGetConfigEntity, mockGetConfigEntitiesByType } from '../test/mocks/ForgeRockApiMockEngine';
8
- import path from 'path';
9
- const mock = new MockAdapter(axios);
10
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
- state.setHost('https://openam-frodo-dev.forgeblocks.com/am');
12
- state.setRealm('alpha');
13
- state.setCookieName('cookieName');
14
- state.setCookieValue('cookieValue');
15
- state.setDeploymentType(global.CLOUD_DEPLOYMENT_TYPE_KEY);
16
- describe('IdmOps - getAllConfigEntities()', () => {
17
- test('getAllConfigEntities() 0: Method is implemented', async () => {
18
- expect(Idm.getAllConfigEntities).toBeDefined();
1
+ /**
2
+ * To record and update snapshots, you must perform 3 steps in order:
3
+ *
4
+ * 1. Record API responses & update ESM snapshots
5
+ *
6
+ * To record and update ESM snapshots, you must call the test:record
7
+ * script and override all the connection state variables required
8
+ * to connect to the env to record from:
9
+ *
10
+ * FRODO_DEBUG=1 FRODO_HOST=frodo-dev npm run test:record IdmOps
11
+ *
12
+ * The above command assumes that you have a connection profile for
13
+ * 'frodo-dev' on your development machine.
14
+ *
15
+ * 2. Update CJS snapshots
16
+ *
17
+ * After recording, the ESM snapshots will already be updated as that happens
18
+ * in one go, but you musty manually update the CJS snapshots by running:
19
+ *
20
+ * FRODO_DEBUG=1 npm run test:update IdmOps
21
+ *
22
+ * 3. Test your changes
23
+ *
24
+ * If 1 and 2 didn't produce any errors, you are ready to run the tests in
25
+ * replay mode and make sure they all succeed as well:
26
+ *
27
+ * npm run test:only IdmOps
28
+ *
29
+ * Note: FRODO_DEBUG=1 is optional and enables debug logging for some output
30
+ * in case things don't function as expected
31
+ */
32
+ import { Idm, IdmConfigRaw } from '../index';
33
+ import { autoSetupPolly } from '../utils/AutoSetupPolly';
34
+ autoSetupPolly();
35
+ async function stageConfigEntity(configEntity, create = true) {
36
+ // delete if exists, then create
37
+ try {
38
+ await IdmConfigRaw.getConfigEntity(configEntity.id);
39
+ await IdmConfigRaw.deleteConfigEntity(configEntity.id);
40
+ } catch (error) {
41
+ // ignore
42
+ } finally {
43
+ if (create) {
44
+ await IdmConfigRaw.putConfigEntity(configEntity.id, configEntity.data);
45
+ }
46
+ }
47
+ }
48
+ describe('IdmOps', () => {
49
+ const configEntity1 = {
50
+ id: 'emailTemplate/FrodoTestConfigEntity1',
51
+ data: {
52
+ defaultLocale: 'en',
53
+ displayName: 'Frodo Test Email Template One',
54
+ enabled: true,
55
+ from: '',
56
+ message: {
57
+ en: '<h3>Click to reset your password</h3><h4><a href="{{object.resumeURI}}">Password reset link</a></h4>',
58
+ fr: '<h3>Cliquez pour réinitialiser votre mot de passe</h3><h4><a href="{{object.resumeURI}}">Mot de passe lien de réinitialisation</a></h4>'
59
+ },
60
+ mimeType: 'text/html',
61
+ subject: {
62
+ en: 'Reset your password',
63
+ fr: 'Réinitialisez votre mot de passe'
64
+ }
65
+ }
66
+ };
67
+ const configEntity2 = {
68
+ id: 'emailTemplate/FrodoTestConfigEntity2',
69
+ data: {
70
+ defaultLocale: 'en',
71
+ displayName: 'Frodo Test Email Template Two',
72
+ enabled: true,
73
+ from: '',
74
+ message: {
75
+ en: '<h3>This is your one-time password:</h3><h4>{{object.description}}</a></h4>'
76
+ },
77
+ mimeType: 'text/html',
78
+ subject: {
79
+ en: 'One-Time Password for login'
80
+ }
81
+ }
82
+ };
83
+ const configEntity3 = {
84
+ id: 'emailTemplate/FrodoTestConfigEntity3',
85
+ data: {
86
+ defaultLocale: 'en',
87
+ displayName: 'Frodo Test Email Template Three',
88
+ enabled: true,
89
+ from: '',
90
+ message: {
91
+ en: '<html><body><h3>You started a login or profile update that requires MFA. </h3><h4><a href="{{object.resumeURI}}">Click to Proceed</a></h4></body></html>'
92
+ },
93
+ mimeType: 'text/html',
94
+ subject: {
95
+ en: 'Multi-Factor Email for Identity Cloud login'
96
+ }
97
+ }
98
+ };
99
+ // in recording mode, setup test data before recording
100
+ beforeAll(async () => {
101
+ if (process.env.FRODO_POLLY_MODE === 'record') {
102
+ await stageConfigEntity(configEntity1);
103
+ await stageConfigEntity(configEntity2);
104
+ await stageConfigEntity(configEntity3, false);
105
+ }
19
106
  });
20
- test('getAllConfigEntities() 1: get all config entities', async () => {
21
- mockGetAllConfigEntities(mock);
22
- expect.assertions(2);
23
- const configEntities = await Idm.getAllConfigEntities();
24
- expect(configEntities).toBeTruthy();
25
- expect(configEntities.configurations.length).toBeGreaterThan(0);
107
+ // in recording mode, remove test data after recording
108
+ afterAll(async () => {
109
+ if (process.env.FRODO_POLLY_MODE === 'record') {
110
+ await stageConfigEntity(configEntity1, false);
111
+ await stageConfigEntity(configEntity2, false);
112
+ await stageConfigEntity(configEntity3, false);
113
+ }
26
114
  });
27
- });
28
- describe('IdmOps - getConfigEntitiesByType()', () => {
29
- test('getConfigEntitiesByType() 0: Method is implemented', async () => {
30
- expect(Idm.getConfigEntitiesByType).toBeDefined();
31
- });
32
- test('getConfigEntitiesByType() 1: Get config entity by type', async () => {
33
- mockGetConfigEntitiesByType(mock);
34
- expect.assertions(2);
35
- const configEntity = await Idm.getConfigEntitiesByType('emailTemplate');
36
- expect(configEntity).toBeTruthy();
37
- expect(configEntity).toMatchSnapshot();
38
- });
39
- });
40
- describe('IdmOps - getConfigEntity()', () => {
41
- test('getConfigEntity() 0: Method is implemented', async () => {
42
- expect(Idm.getConfigEntity).toBeDefined();
115
+ describe('getAllConfigEntities()', () => {
116
+ test('0: Method is implemented', async () => {
117
+ expect(Idm.getAllConfigEntities).toBeDefined();
118
+ });
119
+ test('1: get all config entities', async () => {
120
+ const response = await Idm.getAllConfigEntities();
121
+ expect(response).toMatchSnapshot();
122
+ });
43
123
  });
44
- test('getConfigEntity() 1: Get config entity by Id', async () => {
45
- mockGetConfigEntity(mock);
46
- // expect.assertions(2);
47
- const configEntity = await Idm.getConfigEntity('managed');
48
- expect(configEntity).toBeTruthy();
49
- expect(configEntity).toMatchSnapshot();
124
+ describe('getConfigEntitiesByType()', () => {
125
+ test('0: Method is implemented', async () => {
126
+ expect(Idm.getConfigEntitiesByType).toBeDefined();
127
+ });
128
+ test('1: Get config entity by type (emailTemplate)', async () => {
129
+ const response = await Idm.getConfigEntitiesByType('emailTemplate');
130
+ expect(response).toMatchSnapshot();
131
+ });
132
+ test('2: Get config entity by type (managed)', async () => {
133
+ const response = await Idm.getConfigEntitiesByType('managed');
134
+ expect(response).toMatchSnapshot();
135
+ });
50
136
  });
51
- });
52
- describe('IdmOps - putConfigEntity()', () => {
53
- test('putConfigEntity() 0: Method is implemented', async () => {
54
- expect(Idm.putConfigEntity).toBeDefined();
137
+ describe('getConfigEntity()', () => {
138
+ test('0: Method is implemented', async () => {
139
+ expect(Idm.getConfigEntity).toBeDefined();
140
+ });
141
+ test(`1: Get config entity '${configEntity1.id}'`, async () => {
142
+ const response = await Idm.getConfigEntity(configEntity1.id);
143
+ expect(response).toMatchSnapshot();
144
+ });
145
+ test("2: Get config entity 'managed'", async () => {
146
+ const response = await Idm.getConfigEntity('managed');
147
+ expect(response).toMatchSnapshot();
148
+ });
55
149
  });
56
- test('putConfigEntity() 1: Put a config entity', async () => {
57
- const templateData = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../test/mocks/IdmConfigApi/getConfigEntity/emailTemplate/welcome.json'), 'utf8'));
58
- let uploaded = null;
59
- mockPutConfigEntity(mock, (id, data) => {
60
- uploaded = data;
150
+ describe('putConfigEntity()', () => {
151
+ test('0: Method is implemented', async () => {
152
+ expect(Idm.putConfigEntity).toBeDefined();
153
+ });
154
+ test(`1: Put a config entity '${configEntity3.id}'`, async () => {
155
+ const response = await Idm.putConfigEntity(configEntity3.id, configEntity3.data);
156
+ expect(response).toMatchSnapshot();
61
157
  });
62
- await Idm.putConfigEntity('emailTemplate/welcome', templateData);
63
- expect(uploaded).toBeDefined();
64
- expect(uploaded).toMatchSnapshot();
65
158
  });
66
- });
67
- describe('IdmOps - queryAllManagedObjectsByType()', () => {
68
- test('queryAllManagedObjectsByType() 0: Method is implemented', async () => {
69
- expect(Idm.queryAllManagedObjectsByType).toBeDefined();
159
+ describe('queryAllManagedObjectsByType()', () => {
160
+ test('0: Method is implemented', async () => {
161
+ expect(Idm.queryAllManagedObjectsByType).toBeDefined();
162
+ });
163
+ test(`1: Query managed objects of type 'alpha_user'`, async () => {
164
+ const response = await Idm.queryAllManagedObjectsByType('alpha_user', ['*'], null);
165
+ expect(response).toMatchSnapshot();
166
+ });
70
167
  });
71
168
  });
72
169
  //# sourceMappingURL=IdmOps.test.js.map
@@ -1,33 +1,32 @@
1
- import fs from 'fs';
2
- import { getSocialIdentityProviders, putProviderByTypeAndId } from '../api/SocialIdentityProvidersApi';
1
+ import { deleteProviderByTypeAndId, getSocialIdentityProviders as _getSocialIdentityProviders, putProviderByTypeAndId as _putProviderByTypeAndId } from '../api/SocialIdentityProvidersApi';
3
2
  import { getScript } from '../api/ScriptApi';
4
- import { createOrUpdateScript } from './ScriptOps';
5
- import { convertBase64TextToArray, convertTextArrayToBase64, getRealmString, getTypedFilename, saveJsonToFile, validateImport } from './utils/ExportImportUtils';
3
+ import { putScript } from './ScriptOps';
4
+ import { convertBase64TextToArray, convertTextArrayToBase64 } from './utils/ExportImportUtils';
6
5
  import { printMessage, createProgressIndicator, updateProgressIndicator, stopProgressIndicator } from './utils/Console';
7
-
8
- // use a function vs a template variable to avoid problems in loops
9
- function getFileDataTemplate() {
6
+ import { getMetadata } from './utils/ExportImportUtils';
7
+ import * as state from '../shared/State';
8
+ import { debugMessage } from './utils/Console';
9
+ /**
10
+ * Create an empty idp export template
11
+ * @returns {SocialProviderExportInterface} an empty idp export template
12
+ */
13
+ function createIdpExportTemplate() {
10
14
  return {
11
- meta: {},
15
+ meta: getMetadata(),
12
16
  script: {},
13
17
  idp: {}
14
18
  };
15
19
  }
16
20
 
17
21
  /**
18
- * List providers
22
+ * Get all social identity providers
23
+ * @returns {Promise} a promise that resolves to an object containing an array of social identity providers
19
24
  */
20
- export async function listSocialProviders() {
21
- try {
22
- const providers = await getSocialIdentityProviders();
23
- providers.result.sort((a, b) => a._id.localeCompare(b._id));
24
- providers.result.forEach(socialIdentityProvider => {
25
- printMessage(`${socialIdentityProvider._id}`, 'data');
26
- });
27
- } catch (err) {
28
- printMessage(`listSocialProviders ERROR: ${err.message}`, 'error');
29
- printMessage(err, 'error');
30
- }
25
+ export async function getSocialIdentityProviders() {
26
+ const {
27
+ result
28
+ } = await _getSocialIdentityProviders();
29
+ return result;
31
30
  }
32
31
 
33
32
  /**
@@ -36,239 +35,169 @@ export async function listSocialProviders() {
36
35
  * @returns {Promise} a promise that resolves a social identity provider object
37
36
  */
38
37
  export async function getSocialProvider(providerId) {
39
- return getSocialIdentityProviders().then(response => {
40
- const foundProviders = response.result.filter(provider => provider._id === providerId);
41
- switch (foundProviders.length) {
42
- case 1:
43
- return foundProviders[0];
44
- case 0:
45
- throw new Error(`Provider '${providerId}' not found`);
46
- default:
47
- throw new Error(`${foundProviders.length} providers '${providerId}' found`);
38
+ const response = await getSocialIdentityProviders();
39
+ const foundProviders = response.filter(provider => provider._id === providerId);
40
+ switch (foundProviders.length) {
41
+ case 1:
42
+ return foundProviders[0];
43
+ case 0:
44
+ throw new Error(`Provider '${providerId}' not found`);
45
+ default:
46
+ throw new Error(`${foundProviders.length} providers '${providerId}' found`);
47
+ }
48
+ }
49
+ export async function putProviderByTypeAndId(providerType, providerId, providerData) {
50
+ debugMessage(`IdpOps.putProviderByTypeAndId: start`);
51
+ try {
52
+ const response = await _putProviderByTypeAndId(providerType, providerId, providerData);
53
+ debugMessage(`IdpOps.putProviderByTypeAndId: end`);
54
+ return response;
55
+ } catch (importError) {
56
+ var _importError$response, _importError$response2, _importError$response3;
57
+ if (((_importError$response = importError.response) === null || _importError$response === void 0 ? void 0 : _importError$response.status) === 400 && ((_importError$response2 = importError.response) === null || _importError$response2 === void 0 ? void 0 : (_importError$response3 = _importError$response2.data) === null || _importError$response3 === void 0 ? void 0 : _importError$response3.message) === 'Invalid attribute specified.') {
58
+ const {
59
+ validAttributes
60
+ } = importError.response.data.detail;
61
+ validAttributes.push('_id', '_type');
62
+ for (const attribute of Object.keys(providerData)) {
63
+ if (!validAttributes.includes(attribute)) {
64
+ if (state.getVerbose()) printMessage(`\nRemoving invalid attribute: ${attribute}`, 'warn', false);
65
+ delete providerData[attribute];
66
+ }
67
+ }
68
+ if (state.getVerbose()) printMessage('\n', 'warn', false);
69
+ const response = await _putProviderByTypeAndId(providerType, providerId, providerData);
70
+ debugMessage(`IdpOps.putProviderByTypeAndId: end (after retry)`);
71
+ return response;
72
+ } else {
73
+ // re-throw unhandleable error
74
+ throw importError;
48
75
  }
49
- });
76
+ }
50
77
  }
51
78
 
52
79
  /**
53
- * Export provider by id
54
- * @param {String} providerId provider id/name
55
- * @param {String} file optional export file name
80
+ * Delete social identity provider by id
81
+ * @param {String} providerId social identity provider id/name
82
+ * @returns {Promise} a promise that resolves a social identity provider object
56
83
  */
57
- export async function exportSocialProviderToFile(providerId, file = '') {
58
- let fileName = file;
59
- if (!fileName) {
60
- fileName = getTypedFilename(providerId, 'idp');
61
- }
62
- createProgressIndicator(1, `Exporting ${providerId}`);
63
- try {
64
- const idpData = await getSocialProvider(providerId);
65
- updateProgressIndicator(`Writing file ${fileName}`);
66
- const fileData = getFileDataTemplate();
67
- fileData.idp[idpData._id] = idpData;
68
- if (idpData.transform) {
69
- const scriptData = await getScript(idpData.transform);
70
- scriptData.script = convertBase64TextToArray(scriptData.script);
71
- fileData.script[idpData.transform] = scriptData;
72
- }
73
- saveJsonToFile(fileData, fileName);
74
- stopProgressIndicator(`Exported ${providerId['brightCyan']} to ${fileName['brightCyan']}.`);
75
- } catch (err) {
76
- stopProgressIndicator(`${err}`);
77
- printMessage(`${err}`, 'error');
84
+ export async function deleteSocialProvider(providerId) {
85
+ const response = await getSocialIdentityProviders();
86
+ const foundProviders = response.filter(provider => provider._id === providerId);
87
+ switch (foundProviders.length) {
88
+ case 1:
89
+ return await deleteProviderByTypeAndId(foundProviders[0]._type._id, foundProviders[0]._id);
90
+ case 0:
91
+ throw new Error(`Provider '${providerId}' not found`);
92
+ default:
93
+ throw new Error(`${foundProviders.length} providers '${providerId}' found`);
78
94
  }
79
95
  }
80
96
 
81
97
  /**
82
- * Export all providers
83
- * @param {String} file optional export file name
98
+ * Export social provider by id
99
+ * @param {string} providerId provider id/name
100
+ * @returns {Promise<SocialProviderExportInterface>} a promise that resolves to a SocialProviderExportInterface object
84
101
  */
85
- export async function exportSocialProvidersToFile(file) {
86
- let fileName = file;
87
- if (!fileName) {
88
- fileName = getTypedFilename(`all${getRealmString()}Providers`, 'idp');
89
- }
90
- const fileData = getFileDataTemplate();
91
- const allIdpsData = (await getSocialIdentityProviders()).result;
92
- createProgressIndicator(allIdpsData.length, 'Exporting providers');
93
- for (const idpData of allIdpsData) {
94
- updateProgressIndicator(`Exporting provider ${idpData._id}`);
95
- fileData.idp[idpData._id] = idpData;
96
- if (idpData.transform) {
97
- // eslint-disable-next-line no-await-in-loop
98
- const scriptData = await getScript(idpData.transform);
99
- scriptData.script = convertBase64TextToArray(scriptData.script);
100
- fileData.script[idpData.transform] = scriptData;
101
- }
102
+ export async function exportSocialProvider(providerId) {
103
+ debugMessage(`IdpOps.exportSocialProvider: start`);
104
+ const idpData = await getSocialProvider(providerId);
105
+ const exportData = createIdpExportTemplate();
106
+ exportData.idp[idpData._id] = idpData;
107
+ if (idpData.transform) {
108
+ const scriptData = await getScript(idpData.transform);
109
+ scriptData.script = convertBase64TextToArray(scriptData.script);
110
+ exportData.script[idpData.transform] = scriptData;
102
111
  }
103
- saveJsonToFile(fileData, fileName);
104
- stopProgressIndicator(`${allIdpsData.length} providers exported to ${fileName}.`);
112
+ debugMessage(`IdpOps.exportSocialProvider: end`);
113
+ return exportData;
105
114
  }
106
115
 
107
116
  /**
108
- * Export all providers to individual files
117
+ * Export all providers
118
+ * @returns {Promise<SocialProviderExportInterface>} a promise that resolves to a SocialProviderExportInterface object
109
119
  */
110
- export async function exportSocialProvidersToFiles() {
111
- const allIdpsData = await (await getSocialIdentityProviders()).result;
112
- // printMessage(allIdpsData, 'data');
120
+ export async function exportSocialProviders() {
121
+ const exportData = createIdpExportTemplate();
122
+ const allIdpsData = await getSocialIdentityProviders();
113
123
  createProgressIndicator(allIdpsData.length, 'Exporting providers');
114
124
  for (const idpData of allIdpsData) {
115
- updateProgressIndicator(`Writing provider ${idpData._id}`);
116
- const fileName = getTypedFilename(idpData._id, 'idp');
117
- const fileData = getFileDataTemplate();
118
- fileData.idp[idpData._id] = idpData;
125
+ updateProgressIndicator(`Exporting provider ${idpData._id}`);
126
+ exportData.idp[idpData._id] = idpData;
119
127
  if (idpData.transform) {
120
128
  // eslint-disable-next-line no-await-in-loop
121
129
  const scriptData = await getScript(idpData.transform);
122
130
  scriptData.script = convertBase64TextToArray(scriptData.script);
123
- fileData.script[idpData.transform] = scriptData;
131
+ exportData.script[idpData.transform] = scriptData;
124
132
  }
125
- saveJsonToFile(fileData, fileName);
126
133
  }
127
134
  stopProgressIndicator(`${allIdpsData.length} providers exported.`);
135
+ return exportData;
128
136
  }
129
137
 
130
138
  /**
131
139
  * Import provider by id/name
132
- * @param {String} providerId provider id/name
133
- * @param {String} file import file name
140
+ * @param {string} providerId provider id/name
141
+ * @param {SocialProviderExportInterface} importData import data
134
142
  */
135
- export async function importSocialProviderFromFile(providerId, file) {
136
- fs.readFile(file, 'utf8', async (err, data) => {
137
- if (err) throw err;
138
- const fileData = JSON.parse(data);
139
- if (validateImport(fileData.meta)) {
140
- createProgressIndicator(1, 'Importing provider...');
141
- let found = false;
142
- for (const idpId in fileData.idp) {
143
- if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
144
- if (idpId === providerId) {
145
- found = true;
146
- updateProgressIndicator(`Importing ${fileData.idp[idpId]._id}`);
147
- const scriptId = fileData.idp[idpId].transform;
148
- const scriptData = fileData.script[scriptId];
149
- if (scriptId && scriptData) {
150
- scriptData.script = convertTextArrayToBase64(scriptData.script);
151
- // eslint-disable-next-line no-await-in-loop
152
- await createOrUpdateScript(fileData.idp[idpId].transform, fileData.script[fileData.idp[idpId].transform]);
153
- }
154
- putProviderByTypeAndId(fileData.idp[idpId]._type._id, idpId, fileData.idp[idpId]).then(() => {
155
- stopProgressIndicator(`Successfully imported provider ${providerId}.`);
156
- }).catch(importProviderErr => {
157
- stopProgressIndicator(`Error importing provider ${fileData.idp[idpId]._id}`);
158
- printMessage(`\nError importing provider ${providerId}`, 'error');
159
- printMessage(importProviderErr.response.data, 'error');
160
- });
161
- break;
162
- }
163
- }
164
- }
165
- if (!found) {
166
- stopProgressIndicator(`Provider ${providerId.brightCyan} not found in ${file.brightCyan}!`);
143
+ export async function importSocialProvider(providerId, importData) {
144
+ for (const idpId of Object.keys(importData.idp)) {
145
+ if (idpId === providerId) {
146
+ const scriptId = importData.idp[idpId].transform;
147
+ const scriptData = importData.script[scriptId];
148
+ if (scriptId && scriptData) {
149
+ scriptData.script = convertTextArrayToBase64(scriptData.script);
150
+ await putScript(scriptId, scriptData);
167
151
  }
168
- } else {
169
- printMessage('Import validation failed...', 'error');
152
+ await putProviderByTypeAndId(importData.idp[idpId]._type._id, idpId, importData.idp[idpId]);
153
+ return true;
170
154
  }
171
- });
172
- }
173
-
174
- /**
175
- * Import first provider from file
176
- * @param {String} file import file name
177
- */
178
- export async function importFirstSocialProviderFromFile(file) {
179
- fs.readFile(file, 'utf8', async (err, data) => {
180
- if (err) throw err;
181
- const fileData = JSON.parse(data);
182
- if (validateImport(fileData.meta)) {
183
- createProgressIndicator(1, 'Importing provider...');
184
- for (const idpId in fileData.idp) {
185
- if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
186
- updateProgressIndicator(`Importing ${fileData.idp[idpId]._id}`);
187
- const scriptId = fileData.idp[idpId].transform;
188
- const scriptData = fileData.script[scriptId];
189
- if (scriptId && scriptData) {
190
- scriptData.script = convertTextArrayToBase64(scriptData.script);
191
- // eslint-disable-next-line no-await-in-loop
192
- await createOrUpdateScript(fileData.idp[idpId].transform, fileData.script[fileData.idp[idpId].transform]);
193
- }
194
- putProviderByTypeAndId(fileData.idp[idpId]._type._id, idpId, fileData.idp[idpId]).then(result => {
195
- if (result == null) {
196
- stopProgressIndicator(`Error importing provider ${fileData.idp[idpId]._id}`);
197
- printMessage(`Error importing provider ${fileData.idp[idpId]._id}`, 'error');
198
- } else {
199
- stopProgressIndicator(`Successfully imported provider ${fileData.idp[idpId]._id}.`);
200
- }
201
- });
202
- break;
203
- }
204
- }
205
- } else {
206
- printMessage('Import validation failed...', 'error');
207
- }
208
- });
155
+ }
156
+ return false;
209
157
  }
210
158
 
211
159
  /**
212
- * Import all providers from file
213
- * @param {String} file import file name
160
+ * Import first provider
161
+ * @param {SocialProviderExportInterface} importData import data
214
162
  */
215
- export async function importSocialProvidersFromFile(file) {
216
- fs.readFile(file, 'utf8', async (err, data) => {
217
- if (err) throw err;
218
- const fileData = JSON.parse(data);
219
- if (validateImport(fileData.meta)) {
220
- createProgressIndicator(Object.keys(fileData.idp).length, 'Importing providers...');
221
- for (const idpId in fileData.idp) {
222
- if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
223
- const scriptId = fileData.idp[idpId].transform;
224
- const scriptData = fileData.script[scriptId];
225
- if (scriptId && scriptData) {
226
- scriptData.script = convertTextArrayToBase64(scriptData.script);
227
- // eslint-disable-next-line no-await-in-loop
228
- await createOrUpdateScript(fileData.idp[idpId].transform, fileData.script[fileData.idp[idpId].transform]);
229
- }
230
- // eslint-disable-next-line no-await-in-loop
231
- const result = await putProviderByTypeAndId(fileData.idp[idpId]._type._id, idpId, fileData.idp[idpId]);
232
- if (!result) {
233
- updateProgressIndicator(`Successfully imported ${fileData.idp[idpId].name}`);
234
- }
235
- }
236
- }
237
- stopProgressIndicator(`Providers imported.`);
238
- } else {
239
- printMessage('Import validation failed...', 'error');
163
+ export async function importFirstSocialProvider(importData) {
164
+ for (const idpId of Object.keys(importData.idp)) {
165
+ const scriptId = importData.idp[idpId].transform;
166
+ const scriptData = importData.script[scriptId];
167
+ if (scriptId && scriptData) {
168
+ scriptData.script = convertTextArrayToBase64(scriptData.script);
169
+ await putScript(scriptId, scriptData);
240
170
  }
241
- });
171
+ await putProviderByTypeAndId(importData.idp[idpId]._type._id, idpId, importData.idp[idpId]);
172
+ return true;
173
+ }
174
+ return false;
242
175
  }
243
176
 
244
177
  /**
245
- * Import providers from *.idp.json files in current working directory
178
+ * Import all providers
179
+ * @param {SocialProviderExportInterface} importData import data
246
180
  */
247
- export async function importSocialProvidersFromFiles() {
248
- const names = fs.readdirSync('.');
249
- const jsonFiles = names.filter(name => name.toLowerCase().endsWith('.idp.json'));
250
- createProgressIndicator(jsonFiles.length, 'Importing providers...');
251
- let total = 0;
252
- for (const file of jsonFiles) {
253
- const data = fs.readFileSync(file, 'utf8');
254
- const fileData = JSON.parse(data);
255
- if (validateImport(fileData.meta)) {
256
- const count = Object.keys(fileData.idp).length;
257
- total += count;
258
- for (const idpId in fileData.idp) {
259
- if ({}.hasOwnProperty.call(fileData.idp, idpId)) {
260
- // eslint-disable-next-line no-await-in-loop
261
- const result = await putProviderByTypeAndId(fileData.idp[idpId]._type._id, idpId, fileData.idp[idpId]);
262
- if (result == null) {
263
- printMessage(`Error importing ${count} providers from ${file}`, 'error');
264
- }
265
- }
181
+ export async function importSocialProviders(importData) {
182
+ let outcome = true;
183
+ for (const idpId of Object.keys(importData.idp)) {
184
+ try {
185
+ const scriptId = importData.idp[idpId].transform;
186
+ const scriptData = {
187
+ ...importData.script[scriptId]
188
+ };
189
+ if (scriptId && scriptData) {
190
+ scriptData.script = convertTextArrayToBase64(scriptData.script);
191
+ await putScript(scriptId, scriptData);
266
192
  }
267
- updateProgressIndicator(`Imported ${count} provider(s) from ${file}`);
268
- } else {
269
- printMessage(`Validation of ${file} failed!`, 'error');
193
+ await putProviderByTypeAndId(importData.idp[idpId]._type._id, idpId, importData.idp[idpId]);
194
+ } catch (error) {
195
+ var _error$response;
196
+ printMessage(((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.data) || error, 'error');
197
+ printMessage(`\nError importing provider ${idpId}`, 'error');
198
+ outcome = false;
270
199
  }
271
200
  }
272
- stopProgressIndicator(`Finished importing ${total} provider(s) from ${jsonFiles.length} file(s).`);
201
+ return outcome;
273
202
  }
274
203
  //# sourceMappingURL=IdpOps.js.map