@contentstack/cli-cm-export-to-csv 1.4.3 → 1.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/package.json +3 -3
- package/src/commands/cm/export-to-csv.js +45 -16
- package/src/util/config.js +4 -3
- package/src/util/index.js +287 -14
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-export-to-csv",
|
|
3
3
|
"description": "Export entities to csv",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"author": "Abhinav Gupta @abhinav-from-contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "~1.2.
|
|
9
|
-
"@contentstack/cli-utilities": "~1.5.
|
|
8
|
+
"@contentstack/cli-command": "~1.2.15",
|
|
9
|
+
"@contentstack/cli-utilities": "~1.5.5",
|
|
10
10
|
"chalk": "^4.1.0",
|
|
11
11
|
"fast-csv": "^4.3.6",
|
|
12
12
|
"inquirer": "8.2.4",
|
|
@@ -15,8 +15,8 @@ class ExportToCsvCommand extends Command {
|
|
|
15
15
|
action: flags.string({
|
|
16
16
|
required: false,
|
|
17
17
|
multiple: false,
|
|
18
|
-
options: ['entries', 'users'],
|
|
19
|
-
description: `Option to export data (entries, users)`,
|
|
18
|
+
options: ['entries', 'users', 'teams'],
|
|
19
|
+
description: `Option to export data (entries, users, teams)`,
|
|
20
20
|
}),
|
|
21
21
|
alias: flags.string({
|
|
22
22
|
char: 'a',
|
|
@@ -59,6 +59,9 @@ class ExportToCsvCommand extends Command {
|
|
|
59
59
|
multiple: false,
|
|
60
60
|
required: false,
|
|
61
61
|
}),
|
|
62
|
+
"team-uid": flags.string({
|
|
63
|
+
description: 'Uid of the team whose user data and stack roles are required'
|
|
64
|
+
})
|
|
62
65
|
};
|
|
63
66
|
|
|
64
67
|
async run() {
|
|
@@ -75,11 +78,18 @@ class ExportToCsvCommand extends Command {
|
|
|
75
78
|
'content-type': contentTypesFlag,
|
|
76
79
|
alias: managementTokenAlias,
|
|
77
80
|
branch: branchUid,
|
|
81
|
+
"team-uid": teamUid
|
|
78
82
|
},
|
|
79
83
|
} = await this.parse(ExportToCsvCommand);
|
|
80
84
|
|
|
81
85
|
if (!managementTokenAlias) {
|
|
82
86
|
managementAPIClient = await managementSDKClient({ host: this.cmaHost });
|
|
87
|
+
if (!isAuthenticated()) {
|
|
88
|
+
this.error(config.CLI_EXPORT_CSV_ENTRIES_ERROR, {
|
|
89
|
+
exit: 2,
|
|
90
|
+
suggestions: ['https://www.contentstack.com/docs/developers/cli/authentication/'],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
if (actionFlag) {
|
|
@@ -113,14 +123,6 @@ class ExportToCsvCommand extends Command {
|
|
|
113
123
|
this.error('Provided management token alias not found in your config.!');
|
|
114
124
|
} else {
|
|
115
125
|
let organization;
|
|
116
|
-
|
|
117
|
-
if (!isAuthenticated()) {
|
|
118
|
-
this.error(config.CLI_EXPORT_CSV_ENTRIES_ERROR, {
|
|
119
|
-
exit: 2,
|
|
120
|
-
suggestions: ['https://www.contentstack.com/docs/developers/cli/authentication/'],
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
126
|
if (org) {
|
|
125
127
|
organization = { uid: org };
|
|
126
128
|
} else {
|
|
@@ -227,12 +229,6 @@ class ExportToCsvCommand extends Command {
|
|
|
227
229
|
case config.exportUsers:
|
|
228
230
|
case 'users': {
|
|
229
231
|
try {
|
|
230
|
-
if (!isAuthenticated()) {
|
|
231
|
-
this.error(config.CLI_EXPORT_CSV_LOGIN_FAILED, {
|
|
232
|
-
exit: 2,
|
|
233
|
-
suggestions: ['https://www.contentstack.com/docs/developers/cli/authentication/'],
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
232
|
let organization;
|
|
237
233
|
|
|
238
234
|
if (org) {
|
|
@@ -258,6 +254,24 @@ class ExportToCsvCommand extends Command {
|
|
|
258
254
|
}
|
|
259
255
|
break;
|
|
260
256
|
}
|
|
257
|
+
case config.exportTeams:
|
|
258
|
+
case 'teams': {
|
|
259
|
+
try{
|
|
260
|
+
let organization;
|
|
261
|
+
if (org) {
|
|
262
|
+
organization = { uid: org, name: orgName || org };
|
|
263
|
+
} else {
|
|
264
|
+
organization = await util.chooseOrganization(managementAPIClient, action); // prompt for organization
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
await util.exportTeams(managementAPIClient,organization,teamUid);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
if (error.message || error.errorMessage) {
|
|
270
|
+
cliux.error(util.formatError(error));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
261
275
|
}
|
|
262
276
|
} catch (error) {
|
|
263
277
|
if (error.message || error.errorMessage) {
|
|
@@ -310,6 +324,21 @@ ExportToCsvCommand.examples = [
|
|
|
310
324
|
'',
|
|
311
325
|
'Exporting organization users to csv with organization name provided',
|
|
312
326
|
'csdx cm:export-to-csv --action <users> --org <org-uid> --org-name <org-name>',
|
|
327
|
+
'',
|
|
328
|
+
'Exporting Organizations Teams to CSV',
|
|
329
|
+
'csdx cm:export-to-csv --action <teams>',
|
|
330
|
+
'',
|
|
331
|
+
'Exporting Organizations Teams to CSV with org-uid',
|
|
332
|
+
'csdx cm:export-to-csv --action <teams> --org <org-uid>',
|
|
333
|
+
'',
|
|
334
|
+
'Exporting Organizations Teams to CSV with team uid',
|
|
335
|
+
'csdx cm:export-to-csv --action <teams> --team-uid <team-uid>',
|
|
336
|
+
'',
|
|
337
|
+
'Exporting Organizations Teams to CSV with org-uid and team uid',
|
|
338
|
+
'csdx cm:export-to-csv --action <teams> --org <org-uid> --team-uid <team-uid>',
|
|
339
|
+
'',
|
|
340
|
+
'Exporting Organizations Teams to CSV with org-uid and team uid',
|
|
341
|
+
'csdx cm:export-to-csv --action <teams> --org <org-uid> --team-uid <team-uid> --org-name <org-name>',
|
|
313
342
|
];
|
|
314
343
|
|
|
315
344
|
module.exports = ExportToCsvCommand;
|
package/src/util/config.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
cancelString: 'Cancel and Exit',
|
|
3
3
|
exportEntries: 'Export entries to a .CSV file',
|
|
4
|
-
exportUsers: "Export organization
|
|
4
|
+
exportUsers: "Export organization user's data to a .CSV file",
|
|
5
|
+
exportTeams: "Export organization team's data to a .csv file",
|
|
5
6
|
adminError: "Unable to export data. Make sure you're an admin or owner of this organization",
|
|
6
7
|
organizationNameRegex: /\'/,
|
|
7
8
|
CLI_EXPORT_CSV_LOGIN_FAILED: "You need to login to execute this command. See: auth:login --help",
|
|
8
|
-
CLI_EXPORT_CSV_ENTRIES_ERROR: "You need to either login or provide a management token to execute this command"
|
|
9
|
-
|
|
9
|
+
CLI_EXPORT_CSV_ENTRIES_ERROR: "You need to either login or provide a management token to execute this command",
|
|
10
|
+
CLI_EXPORT_CSV_API_FAILED: 'Something went wrong. Please try again!'
|
|
10
11
|
};
|
package/src/util/index.js
CHANGED
|
@@ -2,14 +2,14 @@ const os = require('os');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const mkdirp = require('mkdirp');
|
|
4
4
|
const find = require('lodash/find');
|
|
5
|
+
const cloneDeep = require('lodash/cloneDeep');
|
|
6
|
+
const omit = require('lodash/omit');
|
|
5
7
|
const fastcsv = require('fast-csv');
|
|
6
8
|
const inquirer = require('inquirer');
|
|
7
9
|
const debug = require('debug')('export-to-csv');
|
|
8
10
|
const checkboxPlus = require('inquirer-checkbox-plus-prompt');
|
|
9
|
-
|
|
10
11
|
const config = require('./config.js');
|
|
11
|
-
const { cliux, configHandler } = require('@contentstack/cli-utilities');
|
|
12
|
-
|
|
12
|
+
const { cliux, configHandler, HttpClient } = require('@contentstack/cli-utilities');
|
|
13
13
|
const directory = './data';
|
|
14
14
|
const delimeter = os.platform() === 'win32' ? '\\' : '/';
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@ function chooseOrganization(managementAPIClient, action) {
|
|
|
20
20
|
return new Promise(async (resolve, reject) => {
|
|
21
21
|
try {
|
|
22
22
|
let organizations;
|
|
23
|
-
if (action === config.exportUsers) {
|
|
23
|
+
if (action === config.exportUsers || action === config.exportTeams || action === 'teams') {
|
|
24
24
|
organizations = await getOrganizationsWhereUserIsAdmin(managementAPIClient);
|
|
25
25
|
} else {
|
|
26
26
|
organizations = await getOrganizations(managementAPIClient);
|
|
@@ -105,7 +105,7 @@ async function getOrganizationsWhereUserIsAdmin(managementAPIClient) {
|
|
|
105
105
|
organizations.forEach((org) => {
|
|
106
106
|
result[org.name] = org.uid;
|
|
107
107
|
});
|
|
108
|
-
|
|
108
|
+
}
|
|
109
109
|
|
|
110
110
|
return result;
|
|
111
111
|
} catch (error) {
|
|
@@ -321,7 +321,13 @@ function getEntries(stackAPIClient, contentType, language, skip, limit) {
|
|
|
321
321
|
stackAPIClient
|
|
322
322
|
.contentType(contentType)
|
|
323
323
|
.entry()
|
|
324
|
-
.query({
|
|
324
|
+
.query({
|
|
325
|
+
include_publish_details: true,
|
|
326
|
+
locale: language,
|
|
327
|
+
skip: skip * 100,
|
|
328
|
+
limit: limit,
|
|
329
|
+
include_workflow: true,
|
|
330
|
+
})
|
|
325
331
|
.find()
|
|
326
332
|
.then((entries) => resolve(entries))
|
|
327
333
|
.catch((error) => reject(error));
|
|
@@ -373,11 +379,11 @@ function exitProgram() {
|
|
|
373
379
|
|
|
374
380
|
function sanitizeEntries(flatEntry) {
|
|
375
381
|
// sanitize against CSV Injections
|
|
376
|
-
const CSVRegex = /^[\\+\\=@\\-]
|
|
382
|
+
const CSVRegex = /^[\\+\\=@\\-]/;
|
|
377
383
|
for (key in flatEntry) {
|
|
378
384
|
if (typeof flatEntry[key] === 'string' && flatEntry[key].match(CSVRegex)) {
|
|
379
385
|
flatEntry[key] = flatEntry[key].replace(/\"/g, "\"\"");
|
|
380
|
-
flatEntry[key] = `"'${flatEntry[key]}"
|
|
386
|
+
flatEntry[key] = `"'${flatEntry[key]}"`;
|
|
381
387
|
} else if (typeof flatEntry[key] === 'object') {
|
|
382
388
|
// convert any objects or arrays to string
|
|
383
389
|
// to store this data correctly in csv
|
|
@@ -394,7 +400,7 @@ function cleanEntries(entries, language, environments, contentTypeUid) {
|
|
|
394
400
|
return filteredEntries.map((entry) => {
|
|
395
401
|
let workflow = '';
|
|
396
402
|
const envArr = [];
|
|
397
|
-
if(entry.publish_details.length) {
|
|
403
|
+
if (entry.publish_details.length) {
|
|
398
404
|
entry.publish_details.forEach((env) => {
|
|
399
405
|
envArr.push(JSON.stringify([environments[env['environment']], env['locale'], env['time']]));
|
|
400
406
|
});
|
|
@@ -403,10 +409,10 @@ function cleanEntries(entries, language, environments, contentTypeUid) {
|
|
|
403
409
|
delete entry.publish_details;
|
|
404
410
|
delete entry.setWorkflowStage;
|
|
405
411
|
if ('_workflow' in entry) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
412
|
+
if (entry._workflow?.name) {
|
|
413
|
+
workflow = entry['_workflow']['name'];
|
|
414
|
+
delete entry['_workflow'];
|
|
415
|
+
}
|
|
410
416
|
}
|
|
411
417
|
entry = flatten(entry);
|
|
412
418
|
entry = sanitizeEntries(entry);
|
|
@@ -459,7 +465,7 @@ function startupQuestions() {
|
|
|
459
465
|
type: 'list',
|
|
460
466
|
name: 'action',
|
|
461
467
|
message: 'Choose Action',
|
|
462
|
-
choices: [config.exportEntries, config.exportUsers, 'Exit'],
|
|
468
|
+
choices: [config.exportEntries, config.exportUsers, config.exportTeams, 'Exit'],
|
|
463
469
|
},
|
|
464
470
|
];
|
|
465
471
|
inquirer
|
|
@@ -678,6 +684,271 @@ function wait(time) {
|
|
|
678
684
|
});
|
|
679
685
|
}
|
|
680
686
|
|
|
687
|
+
function handleErrorMsg(err) {
|
|
688
|
+
cliux.print(`Error: ${(err?.errorMessage || err?.message) ? err?.errorMessage || err?.message : messageHandler.parse('CLI_EXPORT_CSV_API_FAILED')}`, { color: 'red' })
|
|
689
|
+
process.exit(1);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
async function apiRequestHandler(org, queryParam = {}) {
|
|
693
|
+
const headers = {
|
|
694
|
+
authtoken: configHandler.get('authtoken'),
|
|
695
|
+
organization_uid: org.uid,
|
|
696
|
+
'Content-Type': 'application/json',
|
|
697
|
+
api_version: 1.1,
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
return await new HttpClient()
|
|
701
|
+
.headers(headers)
|
|
702
|
+
.queryParams(queryParam)
|
|
703
|
+
.get(`${configHandler.get('region')?.cma}/organizations/${org?.uid}/teams`)
|
|
704
|
+
.then((res) => {
|
|
705
|
+
const { status, data } = res;
|
|
706
|
+
if (status === 200) {
|
|
707
|
+
return data;
|
|
708
|
+
} else {
|
|
709
|
+
cliux.print(`${data?.error_message || data?.message || data?.errorMessage}`, { color: 'red' });
|
|
710
|
+
process.exit(1);
|
|
711
|
+
}
|
|
712
|
+
})
|
|
713
|
+
.catch((error) => {
|
|
714
|
+
handleErrorMsg(error);
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
async function exportOrgTeams(managementAPIClient, org) {
|
|
719
|
+
let teamsObjectArray = [];
|
|
720
|
+
let skip = 0;
|
|
721
|
+
let limit = config?.limit || 100;
|
|
722
|
+
do {
|
|
723
|
+
const data = await apiRequestHandler(org, { skip: skip, limit: limit, includeUserDetails: true });
|
|
724
|
+
skip += limit;
|
|
725
|
+
teamsObjectArray.push(...data?.teams);
|
|
726
|
+
if (skip >= data?.count) break;
|
|
727
|
+
} while (1);
|
|
728
|
+
teamsObjectArray = await cleanTeamsData(teamsObjectArray, managementAPIClient, org);
|
|
729
|
+
return teamsObjectArray;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
async function getOrgRolesForTeams(managementAPIClient, org) {
|
|
733
|
+
let roleMap = {}; // for org level there are two roles only admin and member
|
|
734
|
+
|
|
735
|
+
// SDK call to get the role uids
|
|
736
|
+
await managementAPIClient
|
|
737
|
+
.organization(org.uid)
|
|
738
|
+
.roles()
|
|
739
|
+
.then((roles) => {
|
|
740
|
+
roles.items.forEach((item) => {
|
|
741
|
+
if (item.name === 'member' || item.name === 'admin') {
|
|
742
|
+
roleMap[item.name] = item.uid;
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
})
|
|
746
|
+
.catch((err) => {
|
|
747
|
+
handleErrorMsg(err);
|
|
748
|
+
});
|
|
749
|
+
return roleMap;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
async function cleanTeamsData(data, managementAPIClient, org) {
|
|
753
|
+
const roleMap = await getOrgRolesForTeams(managementAPIClient, org);
|
|
754
|
+
const fieldToBeDeleted = [
|
|
755
|
+
'_id',
|
|
756
|
+
'createdAt',
|
|
757
|
+
'createdBy',
|
|
758
|
+
'updatedAt',
|
|
759
|
+
'updatedBy',
|
|
760
|
+
'__v',
|
|
761
|
+
'createdByUserName',
|
|
762
|
+
'updatedByUserName',
|
|
763
|
+
'organizationUid',
|
|
764
|
+
];
|
|
765
|
+
if (data?.length) {
|
|
766
|
+
return data.map((team) => {
|
|
767
|
+
team = omit(team, fieldToBeDeleted);
|
|
768
|
+
|
|
769
|
+
team.organizationRole = (team.organizationRole === roleMap["member"]) ? "member" : "admin";
|
|
770
|
+
|
|
771
|
+
if (!team.hasOwnProperty("description")) {
|
|
772
|
+
team.description = "";
|
|
773
|
+
}
|
|
774
|
+
team.Total_Members = team?.users?.length || 0;
|
|
775
|
+
|
|
776
|
+
return team;
|
|
777
|
+
});
|
|
778
|
+
} else {
|
|
779
|
+
return [];
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
async function exportTeams(managementAPIClient, organization, teamUid) {
|
|
784
|
+
cliux.print(
|
|
785
|
+
`info: Exporting the ${
|
|
786
|
+
teamUid && organization?.name
|
|
787
|
+
? `team with uid ${teamUid} in Organisation ${organization?.name} `
|
|
788
|
+
: `teams of Organisation ` + organization?.name
|
|
789
|
+
}`,
|
|
790
|
+
{ color: 'blue' },
|
|
791
|
+
);
|
|
792
|
+
const allTeamsData = await exportOrgTeams(managementAPIClient, organization);
|
|
793
|
+
if (!allTeamsData?.length) {
|
|
794
|
+
cliux.print(`info: The organization ${organization?.name} does not have any teams associated with it. Please verify and provide the correct organization name.`);
|
|
795
|
+
} else {
|
|
796
|
+
const modifiedTeam = cloneDeep(allTeamsData);
|
|
797
|
+
modifiedTeam.forEach((team) => {
|
|
798
|
+
delete team['users'];
|
|
799
|
+
delete team['stackRoleMapping'];
|
|
800
|
+
});
|
|
801
|
+
const fileName = `${kebabize(organization.name.replace(config.organizationNameRegex, ''))}_teams_export.csv`;
|
|
802
|
+
write(this, modifiedTeam, fileName, ' organization Team details');
|
|
803
|
+
// exporting teams user data or a single team user data
|
|
804
|
+
cliux.print(
|
|
805
|
+
`info: Exporting the teams user data for ${teamUid ? `team ` + teamUid : `organisation ` + organization?.name}`,
|
|
806
|
+
{ color: 'blue' },
|
|
807
|
+
);
|
|
808
|
+
await getTeamsDetail(allTeamsData, organization, teamUid);
|
|
809
|
+
cliux.print(
|
|
810
|
+
`info: Exporting the stack role details for ${
|
|
811
|
+
teamUid ? `team ` + teamUid : `organisation ` + organization?.name
|
|
812
|
+
}`,
|
|
813
|
+
{ color: 'blue' },
|
|
814
|
+
);
|
|
815
|
+
// Exporting the stack Role data for all the teams or exporting stack role data for a single team
|
|
816
|
+
await exportRoleMappings(managementAPIClient, allTeamsData, teamUid);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
async function getTeamsDetail(allTeamsData, organization, teamUid) {
|
|
821
|
+
if (!teamUid) {
|
|
822
|
+
const userData = await getTeamsUserDetails(allTeamsData);
|
|
823
|
+
const fileName = `${kebabize(
|
|
824
|
+
organization.name.replace(config.organizationNameRegex, ''),
|
|
825
|
+
)}_team_User_Details_export.csv`;
|
|
826
|
+
|
|
827
|
+
write(this, userData, fileName, 'Team User details');
|
|
828
|
+
} else {
|
|
829
|
+
const team = allTeamsData.filter((team) => team.uid === teamUid)[0];
|
|
830
|
+
|
|
831
|
+
team.users.forEach((user) => {
|
|
832
|
+
user['team-name'] = team.name;
|
|
833
|
+
user['team-uid'] = team.uid;
|
|
834
|
+
delete user['active'];
|
|
835
|
+
delete user['orgInvitationStatus'];
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
const fileName = `${kebabize(
|
|
839
|
+
organization.name.replace(config.organizationNameRegex, ''),
|
|
840
|
+
)}_team_${teamUid}_User_Details_export.csv`;
|
|
841
|
+
|
|
842
|
+
write(this, team.users, fileName, 'Team User details');
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
async function exportRoleMappings(managementAPIClient, allTeamsData, teamUid) {
|
|
847
|
+
let stackRoleWithTeamData = [];
|
|
848
|
+
let flag = false;
|
|
849
|
+
const stackNotAdmin = [];
|
|
850
|
+
if (teamUid) {
|
|
851
|
+
const team = find(allTeamsData,function(teamObject) { return teamObject?.uid===teamUid });
|
|
852
|
+
for (const stack of team?.stackRoleMapping) {
|
|
853
|
+
const roleData = await mapRoleWithTeams(managementAPIClient, stack, team?.name, team?.uid);
|
|
854
|
+
stackRoleWithTeamData.push(...roleData);
|
|
855
|
+
if(roleData[0]['Stack Name']==='') {
|
|
856
|
+
flag = true;
|
|
857
|
+
stackNotAdmin.push(stack.stackApiKey);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
} else {
|
|
861
|
+
for (const team of allTeamsData ?? []) {
|
|
862
|
+
for (const stack of team?.stackRoleMapping ?? []) {
|
|
863
|
+
const roleData = await mapRoleWithTeams(managementAPIClient, stack, team?.name, team?.uid);
|
|
864
|
+
stackRoleWithTeamData.push(...roleData);
|
|
865
|
+
if(roleData[0]['Stack Name']==='') {
|
|
866
|
+
flag = true;
|
|
867
|
+
stackNotAdmin.push(stack.stackApiKey);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if(stackNotAdmin?.length) {
|
|
873
|
+
cliux.print(`warning: Admin access denied to the following stacks using the provided API keys. Please get in touch with the stack owner to request access.`,{color:"yellow"});
|
|
874
|
+
cliux.print(`${stackNotAdmin.join(' , ')}`,{color:"yellow"});
|
|
875
|
+
}
|
|
876
|
+
if(flag) {
|
|
877
|
+
let export_stack_role = [
|
|
878
|
+
{
|
|
879
|
+
type: 'list',
|
|
880
|
+
name: 'chooseExport',
|
|
881
|
+
message: `Access denied: Please confirm if you still want to continue exporting the data without the { Stack Name, Stack Uid, Role Name } fields.`,
|
|
882
|
+
choices: ['yes', 'no'],
|
|
883
|
+
loop: false,
|
|
884
|
+
}]
|
|
885
|
+
const exportStackRole = await inquirer
|
|
886
|
+
.prompt(export_stack_role)
|
|
887
|
+
.then(( chosenOrg ) => {
|
|
888
|
+
return chosenOrg
|
|
889
|
+
})
|
|
890
|
+
.catch((error) => {
|
|
891
|
+
cliux.print(error, {color:'red'});
|
|
892
|
+
process.exit(1);
|
|
893
|
+
});
|
|
894
|
+
if(exportStackRole.chooseExport === 'no') {
|
|
895
|
+
process.exit(1);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
const fileName = `${kebabize('Stack_Role_Mapping'.replace(config.organizationNameRegex, ''))}${
|
|
900
|
+
teamUid ? `_${teamUid}` : ''
|
|
901
|
+
}.csv`;
|
|
902
|
+
|
|
903
|
+
write(this, stackRoleWithTeamData, fileName, 'Team Stack Role details');
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
async function mapRoleWithTeams(managementAPIClient, stackRoleMapping, teamName, teamUid) {
|
|
907
|
+
const roles = await getRoleData(managementAPIClient, stackRoleMapping.stackApiKey);
|
|
908
|
+
const stackRole = {};
|
|
909
|
+
roles?.items?.forEach((role) => {
|
|
910
|
+
if (!stackRole.hasOwnProperty(role?.uid)) {
|
|
911
|
+
stackRole[role?.uid] = role?.name;
|
|
912
|
+
stackRole[role?.stack?.api_key] = {name: role?.stack?.name, uid: role?.stack?.uid }
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
const stackRoleMapOfTeam = stackRoleMapping?.roles.map((role) => {
|
|
916
|
+
return {
|
|
917
|
+
'Team Name': teamName,
|
|
918
|
+
'Team Uid': teamUid,
|
|
919
|
+
'Stack Name': stackRole[stackRoleMapping?.stackApiKey]?.name || '',
|
|
920
|
+
'Stack Uid': stackRole[stackRoleMapping?.stackApiKey]?.uid || '',
|
|
921
|
+
'Role Name': stackRole[role] || '',
|
|
922
|
+
'Role Uid': role || '',
|
|
923
|
+
};
|
|
924
|
+
});
|
|
925
|
+
return stackRoleMapOfTeam;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
async function getRoleData(managementAPIClient, stackApiKey) {
|
|
929
|
+
try {
|
|
930
|
+
return await managementAPIClient.stack({ api_key: stackApiKey }).role().fetchAll();
|
|
931
|
+
} catch (error) {
|
|
932
|
+
return {}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
async function getTeamsUserDetails(teamsObject) {
|
|
937
|
+
const allTeamUsers = [];
|
|
938
|
+
teamsObject.forEach((team) => {
|
|
939
|
+
if (team?.users?.length) {
|
|
940
|
+
team.users.forEach((user) => {
|
|
941
|
+
user['team-name'] = team.name;
|
|
942
|
+
user['team-uid'] = team.uid;
|
|
943
|
+
delete user['active'];
|
|
944
|
+
delete user['orgInvitationStatus'];
|
|
945
|
+
allTeamUsers.push(user);
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
return allTeamUsers;
|
|
950
|
+
}
|
|
951
|
+
|
|
681
952
|
module.exports = {
|
|
682
953
|
chooseOrganization: chooseOrganization,
|
|
683
954
|
chooseStack: chooseStack,
|
|
@@ -704,4 +975,6 @@ module.exports = {
|
|
|
704
975
|
chooseInMemContentTypes: chooseInMemContentTypes,
|
|
705
976
|
getEntriesCount: getEntriesCount,
|
|
706
977
|
formatError: formatError,
|
|
978
|
+
exportOrgTeams: exportOrgTeams,
|
|
979
|
+
exportTeams: exportTeams,
|
|
707
980
|
};
|