@credibledata/cred-cli 0.1.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 +33 -0
- package/.github/workflows/build.yml +23 -0
- package/.mocharc.json +10 -0
- package/.prettierignore +1 -0
- package/.prettierrc +4 -0
- package/README.md +40 -0
- package/bun.lock +1259 -0
- package/dist/client/api.js +7022 -0
- package/dist/client/api.js.map +1 -0
- package/dist/client/base.js +69 -0
- package/dist/client/base.js.map +1 -0
- package/dist/client/common.js +162 -0
- package/dist/client/common.js.map +1 -0
- package/dist/client/configuration.js +44 -0
- package/dist/client/configuration.js.map +1 -0
- package/dist/client/index.js +32 -0
- package/dist/client/index.js.map +1 -0
- package/dist/clientconfiguration.js +163 -0
- package/dist/clientconfiguration.js.map +1 -0
- package/dist/clientconfiguration.spec.js +92 -0
- package/dist/clientconfiguration.spec.js.map +1 -0
- package/dist/commands/add.js +61 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/connection/createconnections.js +62 -0
- package/dist/commands/connection/createconnections.js.map +1 -0
- package/dist/commands/connection/deleteconnection.js +52 -0
- package/dist/commands/connection/deleteconnection.js.map +1 -0
- package/dist/commands/connection/listconnections.js +44 -0
- package/dist/commands/connection/listconnections.js.map +1 -0
- package/dist/commands/get.js +28 -0
- package/dist/commands/get.js.map +1 -0
- package/dist/commands/group/addmember.js +73 -0
- package/dist/commands/group/addmember.js.map +1 -0
- package/dist/commands/group/creategroup.js +55 -0
- package/dist/commands/group/creategroup.js.map +1 -0
- package/dist/commands/group/deletegroup.js +48 -0
- package/dist/commands/group/deletegroup.js.map +1 -0
- package/dist/commands/group/getgroup.js +50 -0
- package/dist/commands/group/getgroup.js.map +1 -0
- package/dist/commands/group/listgroups.js +56 -0
- package/dist/commands/group/listgroups.js.map +1 -0
- package/dist/commands/group/removemember.js +68 -0
- package/dist/commands/group/removemember.js.map +1 -0
- package/dist/commands/groupaccesstoken/createToken.js +49 -0
- package/dist/commands/groupaccesstoken/createToken.js.map +1 -0
- package/dist/commands/groupaccesstoken/deleteToken.js +24 -0
- package/dist/commands/groupaccesstoken/deleteToken.js.map +1 -0
- package/dist/commands/groupaccesstoken/groupContainer.js +71 -0
- package/dist/commands/groupaccesstoken/groupContainer.js.map +1 -0
- package/dist/commands/groupaccesstoken/listTokens.js +25 -0
- package/dist/commands/groupaccesstoken/listTokens.js.map +1 -0
- package/dist/commands/list.js +68 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/misc/login.js +166 -0
- package/dist/commands/misc/login.js.map +1 -0
- package/dist/commands/misc/login.spec.js +138 -0
- package/dist/commands/misc/login.spec.js.map +1 -0
- package/dist/commands/misc/logout.js +11 -0
- package/dist/commands/misc/logout.js.map +1 -0
- package/dist/commands/misc/set-access-token.js +27 -0
- package/dist/commands/misc/set-access-token.js.map +1 -0
- package/dist/commands/package/deletepackage.js +54 -0
- package/dist/commands/package/deletepackage.js.map +1 -0
- package/dist/commands/package/listpackages.js +52 -0
- package/dist/commands/package/listpackages.js.map +1 -0
- package/dist/commands/package/publish.js +134 -0
- package/dist/commands/package/publish.js.map +1 -0
- package/dist/commands/package/updatepackage.js +75 -0
- package/dist/commands/package/updatepackage.js.map +1 -0
- package/dist/commands/package/updatepackage.spec.js +139 -0
- package/dist/commands/package/updatepackage.spec.js.map +1 -0
- package/dist/commands/project/createproject.js +65 -0
- package/dist/commands/project/createproject.js.map +1 -0
- package/dist/commands/project/deleteproject.js +49 -0
- package/dist/commands/project/deleteproject.js.map +1 -0
- package/dist/commands/project/getproject.js +44 -0
- package/dist/commands/project/getproject.js.map +1 -0
- package/dist/commands/project/listprojects.js +46 -0
- package/dist/commands/project/listprojects.js.map +1 -0
- package/dist/commands/project/setproject.js +26 -0
- package/dist/commands/project/setproject.js.map +1 -0
- package/dist/commands/rm.js +68 -0
- package/dist/commands/rm.js.map +1 -0
- package/dist/commands/set.js +17 -0
- package/dist/commands/set.js.map +1 -0
- package/dist/commands/update.js +29 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/version/archive-unarchive-version.js +79 -0
- package/dist/commands/version/archive-unarchive-version.js.map +1 -0
- package/dist/commands/version/archive-unarchive-version.spec.js +244 -0
- package/dist/commands/version/archive-unarchive-version.spec.js.map +1 -0
- package/dist/commands/version/listversions.js +46 -0
- package/dist/commands/version/listversions.js.map +1 -0
- package/dist/common/UserGroupId.js +112 -0
- package/dist/common/UserGroupId.js.map +1 -0
- package/dist/constants.js +54 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.js +77 -0
- package/dist/logger.js.map +1 -0
- package/dist/polyfills/file.polyfill.js +6 -0
- package/dist/polyfills/file.polyfill.js.map +1 -0
- package/dist/utils.js +51 -0
- package/dist/utils.js.map +1 -0
- package/dist/validator.js +53 -0
- package/dist/validator.js.map +1 -0
- package/dist/validator.spec.js +41 -0
- package/dist/validator.spec.js.map +1 -0
- package/docker/Dockerfile.ci +10 -0
- package/docker-compose.yml +18 -0
- package/mocha.setup.ts +4 -0
- package/openapitools.json +7 -0
- package/package.json +67 -0
- package/src/client/.openapi-generator/FILES +8 -0
- package/src/client/.openapi-generator/VERSION +1 -0
- package/src/client/.openapi-generator-ignore +23 -0
- package/src/client/api.ts +8408 -0
- package/src/client/base.ts +86 -0
- package/src/client/common.ts +150 -0
- package/src/client/configuration.ts +110 -0
- package/src/client/git_push.sh +57 -0
- package/src/client/index.ts +18 -0
- package/src/clientconfiguration.spec.ts +116 -0
- package/src/clientconfiguration.ts +204 -0
- package/src/commands/add.ts +106 -0
- package/src/commands/connection/createconnections.ts +67 -0
- package/src/commands/connection/deleteconnection.ts +57 -0
- package/src/commands/connection/listconnections.ts +39 -0
- package/src/commands/get.ts +31 -0
- package/src/commands/group/addmember.ts +83 -0
- package/src/commands/group/creategroup.ts +54 -0
- package/src/commands/group/deletegroup.ts +45 -0
- package/src/commands/group/getgroup.ts +47 -0
- package/src/commands/group/listgroups.ts +45 -0
- package/src/commands/group/removemember.ts +74 -0
- package/src/commands/groupaccesstoken/createToken.ts +68 -0
- package/src/commands/groupaccesstoken/deleteToken.ts +24 -0
- package/src/commands/groupaccesstoken/groupContainer.ts +83 -0
- package/src/commands/groupaccesstoken/listTokens.ts +24 -0
- package/src/commands/list.ts +90 -0
- package/src/commands/misc/login.spec.ts +128 -0
- package/src/commands/misc/login.ts +142 -0
- package/src/commands/misc/logout.ts +9 -0
- package/src/commands/misc/set-access-token.ts +32 -0
- package/src/commands/package/deletepackage.ts +58 -0
- package/src/commands/package/listpackages.ts +44 -0
- package/src/commands/package/publish.ts +179 -0
- package/src/commands/package/updatepackage.spec.ts +221 -0
- package/src/commands/package/updatepackage.ts +95 -0
- package/src/commands/project/createproject.ts +59 -0
- package/src/commands/project/deleteproject.ts +48 -0
- package/src/commands/project/getproject.ts +43 -0
- package/src/commands/project/listprojects.ts +36 -0
- package/src/commands/project/setproject.ts +14 -0
- package/src/commands/rm.ts +106 -0
- package/src/commands/set.ts +16 -0
- package/src/commands/update.ts +41 -0
- package/src/commands/version/archive-unarchive-version.spec.ts +456 -0
- package/src/commands/version/archive-unarchive-version.ts +111 -0
- package/src/commands/version/listversions.ts +45 -0
- package/src/common/UserGroupId.ts +137 -0
- package/src/constants.ts +70 -0
- package/src/index.ts +183 -0
- package/src/logger.ts +86 -0
- package/src/polyfills/file.polyfill.ts +5 -0
- package/src/utils.ts +34 -0
- package/src/validator.spec.ts +51 -0
- package/src/validator.ts +44 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { GroupsApi } from "../../client/api";
|
|
2
|
+
import { Configuration } from "../../client/configuration";
|
|
3
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
4
|
+
import { logger } from "../../logger";
|
|
5
|
+
import { printOutError } from "../../utils";
|
|
6
|
+
|
|
7
|
+
const groupsApi = new GroupsApi(new Configuration());
|
|
8
|
+
|
|
9
|
+
export async function getGroup(
|
|
10
|
+
controlPlane: string,
|
|
11
|
+
groupName: string,
|
|
12
|
+
debug: boolean,
|
|
13
|
+
) {
|
|
14
|
+
const clientConfig = new ClientConfiguration();
|
|
15
|
+
|
|
16
|
+
if (!clientConfig.doesConfigExists()) {
|
|
17
|
+
logger.error("Please, make sure that you are logged in");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const organizationName = clientConfig.getOrganization();
|
|
22
|
+
if (!organizationName) {
|
|
23
|
+
logger.error("No organization set. Please login or set an organization.");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
logger.info(
|
|
28
|
+
`Getting group ${groupName} from organization ${organizationName}`,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const response = await groupsApi.getGroup(organizationName, groupName, {
|
|
33
|
+
baseURL: controlPlane,
|
|
34
|
+
headers: {
|
|
35
|
+
Authorization: clientConfig.getAuthenticationHeader(),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const jsonString = JSON.stringify(response.data, null, 2);
|
|
40
|
+
console.log(jsonString);
|
|
41
|
+
logger.info("Group retrieved successfully");
|
|
42
|
+
} catch (error) {
|
|
43
|
+
logger.error("Failed to get group");
|
|
44
|
+
printOutError(error, debug);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { GroupsApi } from "../../client/api";
|
|
2
|
+
import { Configuration } from "../../client/configuration";
|
|
3
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
4
|
+
import { logger } from "../../logger";
|
|
5
|
+
import { printOutError } from "../../utils";
|
|
6
|
+
|
|
7
|
+
const groupsApi = new GroupsApi(new Configuration());
|
|
8
|
+
|
|
9
|
+
export async function listGroups(controlPlane: string, debug: boolean) {
|
|
10
|
+
const clientConfig = new ClientConfiguration();
|
|
11
|
+
|
|
12
|
+
if (!clientConfig.doesConfigExists()) {
|
|
13
|
+
logger.error("Please, make sure that you are logged in");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const organizationName = clientConfig.getOrganization();
|
|
18
|
+
if (!organizationName) {
|
|
19
|
+
logger.error("No organization set. Please login or set an organization.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
logger.info(`Listing groups in organization ${organizationName}`);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const response = await groupsApi.listGroups(organizationName, {
|
|
27
|
+
baseURL: controlPlane,
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: clientConfig.getAuthenticationHeader(),
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const jsonString = JSON.stringify(response.data, null, 2);
|
|
34
|
+
console.log(jsonString);
|
|
35
|
+
logger.info("Groups listed successfully");
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error("Failed to list groups");
|
|
38
|
+
printOutError(error, debug);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function printOutGroups(controlPlane: string, debug: boolean) {
|
|
44
|
+
return listGroups(controlPlane, debug);
|
|
45
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GroupMember,
|
|
3
|
+
GroupsApi,
|
|
4
|
+
RemoveGroupMembersRequest,
|
|
5
|
+
} from "../../client/api";
|
|
6
|
+
import { Configuration } from "../../client/configuration";
|
|
7
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
8
|
+
import { UserGroupId } from "../../common/UserGroupId";
|
|
9
|
+
import { logger } from "../../logger";
|
|
10
|
+
import { printOutError } from "../../utils";
|
|
11
|
+
|
|
12
|
+
const groupsApi = new GroupsApi(new Configuration());
|
|
13
|
+
|
|
14
|
+
export async function removeMember(
|
|
15
|
+
controlPlane: string,
|
|
16
|
+
groupName: string,
|
|
17
|
+
memberType: string,
|
|
18
|
+
memberName: string,
|
|
19
|
+
debug: boolean,
|
|
20
|
+
) {
|
|
21
|
+
const clientConfig = new ClientConfiguration();
|
|
22
|
+
|
|
23
|
+
if (!clientConfig.doesConfigExists()) {
|
|
24
|
+
logger.error("Please, make sure that you are logged in");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const organizationName = clientConfig.getOrganization();
|
|
29
|
+
if (!organizationName) {
|
|
30
|
+
logger.error("No organization set. Please login or set an organization.");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
logger.info(
|
|
35
|
+
`Removing ${memberType} ${memberName} from group ${groupName} in organization ${organizationName}`,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Create UserGroupId based on member type
|
|
39
|
+
let userGroupId: UserGroupId;
|
|
40
|
+
if (memberType.toLowerCase() === "user") {
|
|
41
|
+
userGroupId = UserGroupId.forUser(memberName);
|
|
42
|
+
} else if (memberType.toLowerCase() === "group") {
|
|
43
|
+
userGroupId = UserGroupId.forGroup(memberName);
|
|
44
|
+
} else {
|
|
45
|
+
logger.error("Error: memberType must be either 'user' or 'group'");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const groupMember: GroupMember = {
|
|
50
|
+
userGroupId: userGroupId.getValue(),
|
|
51
|
+
// Note: status is not required for removal, only the member identifier
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const request: RemoveGroupMembersRequest = {
|
|
55
|
+
members: [groupMember],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
await groupsApi.removeGroupMembers(organizationName, groupName, request, {
|
|
60
|
+
baseURL: controlPlane,
|
|
61
|
+
headers: {
|
|
62
|
+
Authorization: clientConfig.getAuthenticationHeader(),
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
logger.info(
|
|
67
|
+
`Successfully removed ${memberType} ${memberName} from group ${groupName}`,
|
|
68
|
+
);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logger.error("Failed to remove member from group");
|
|
71
|
+
printOutError(error, debug);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import kleur from "kleur";
|
|
2
|
+
import { logger } from "../../logger";
|
|
3
|
+
import { withGroupContext } from "./groupContainer";
|
|
4
|
+
|
|
5
|
+
export async function createGroupAccessToken(
|
|
6
|
+
controlPlane: string,
|
|
7
|
+
groupName: string,
|
|
8
|
+
tokenName: string,
|
|
9
|
+
expiresAt: string | undefined,
|
|
10
|
+
debug: boolean,
|
|
11
|
+
) {
|
|
12
|
+
// Validate expiresAt format if provided
|
|
13
|
+
if (expiresAt) {
|
|
14
|
+
const expiresAtDate = new Date(expiresAt);
|
|
15
|
+
if (isNaN(expiresAtDate.getTime())) {
|
|
16
|
+
logger.error(
|
|
17
|
+
`Invalid expiration date format: ${expiresAt}. Please use ISO 8601 format (e.g., 2025-12-31T23:59:59Z)`,
|
|
18
|
+
);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
if (expiresAtDate <= new Date()) {
|
|
22
|
+
logger.error(
|
|
23
|
+
"Expiration date must be in the future",
|
|
24
|
+
);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const result = await withGroupContext(controlPlane, async (context) => {
|
|
30
|
+
const { organizationName, groupsApi, options } = context;
|
|
31
|
+
|
|
32
|
+
logger.info(
|
|
33
|
+
`Creating access token ${tokenName} for group ${groupName} in organization ${organizationName}${expiresAt ? ` (expires: ${expiresAt})` : ""}`,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const response = await groupsApi.createGroupAccessToken(
|
|
37
|
+
organizationName,
|
|
38
|
+
groupName,
|
|
39
|
+
tokenName,
|
|
40
|
+
expiresAt,
|
|
41
|
+
options,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return response.data;
|
|
45
|
+
}, undefined, debug);
|
|
46
|
+
|
|
47
|
+
// Display security warning after the response is printed
|
|
48
|
+
console.log("\n" + kleur.yellow().bold("⚠️ IMPORTANT SECURITY NOTICE ⚠️"));
|
|
49
|
+
console.log(
|
|
50
|
+
kleur.yellow(
|
|
51
|
+
"The token secret shown above will NOT be displayed again.",
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
console.log(
|
|
55
|
+
kleur.yellow(
|
|
56
|
+
"Please store it securely in a password manager or secure vault.",
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
console.log(
|
|
60
|
+
kleur.yellow(
|
|
61
|
+
"If you lose this token, you will need to create a new one.",
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
console.log("");
|
|
65
|
+
logger.info("Group access token created successfully");
|
|
66
|
+
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { logger } from "../../logger";
|
|
2
|
+
import { withGroupContext } from "./groupContainer";
|
|
3
|
+
|
|
4
|
+
export async function deleteGroupAccessToken(
|
|
5
|
+
controlPlane: string,
|
|
6
|
+
groupName: string,
|
|
7
|
+
tokenName: string,
|
|
8
|
+
debug: boolean,
|
|
9
|
+
) {
|
|
10
|
+
return withGroupContext(controlPlane, async (context) => {
|
|
11
|
+
const { organizationName, groupsApi, options } = context;
|
|
12
|
+
|
|
13
|
+
logger.info(
|
|
14
|
+
`Deleting access token ${tokenName} from group ${groupName} in organization ${organizationName}`,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
await groupsApi.deleteGroupAccessToken(
|
|
18
|
+
organizationName,
|
|
19
|
+
groupName,
|
|
20
|
+
tokenName,
|
|
21
|
+
options,
|
|
22
|
+
);
|
|
23
|
+
}, `Successfully deleted access token ${tokenName}. This token has been immediately revoked.`, debug);
|
|
24
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { GroupsApi } from "../../client/api";
|
|
2
|
+
import { Configuration } from "../../client/configuration";
|
|
3
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
4
|
+
import { logger } from "../../logger";
|
|
5
|
+
import { printOutError } from "../../utils";
|
|
6
|
+
|
|
7
|
+
export interface ApiOptions {
|
|
8
|
+
baseURL: string;
|
|
9
|
+
headers: {
|
|
10
|
+
Authorization: string;
|
|
11
|
+
};
|
|
12
|
+
params?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface GroupContext {
|
|
16
|
+
organizationName: string;
|
|
17
|
+
groupsApi: GroupsApi;
|
|
18
|
+
options: ApiOptions;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Container function that handles common ClientConfiguration checks, setup,
|
|
23
|
+
* error handling, and response printing for group access token operations.
|
|
24
|
+
*
|
|
25
|
+
* @param controlPlane The control plane URL
|
|
26
|
+
* @param handler The handler function to execute with the configured context
|
|
27
|
+
* @param successMessage Optional success message to display after the operation
|
|
28
|
+
* @param debug Whether to enable debug mode for error output
|
|
29
|
+
* @returns The result of the handler function, or void if validation fails
|
|
30
|
+
*/
|
|
31
|
+
export async function withGroupContext<T>(
|
|
32
|
+
controlPlane: string,
|
|
33
|
+
handler: (context: GroupContext) => Promise<T>,
|
|
34
|
+
successMessage?: string,
|
|
35
|
+
debug: boolean = false,
|
|
36
|
+
): Promise<T | void> {
|
|
37
|
+
const clientConfig = new ClientConfiguration();
|
|
38
|
+
|
|
39
|
+
if (!clientConfig.doesConfigExists()) {
|
|
40
|
+
logger.error("Please, make sure that you are logged in");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const organizationName = clientConfig.getOrganization();
|
|
45
|
+
if (!organizationName) {
|
|
46
|
+
logger.error("No organization set. Please login or set an organization.");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const options: ApiOptions = {
|
|
51
|
+
baseURL: controlPlane,
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: clientConfig.getAuthenticationHeader(),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const context: GroupContext = {
|
|
58
|
+
organizationName,
|
|
59
|
+
groupsApi: new GroupsApi(new Configuration()),
|
|
60
|
+
options,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const result = await handler(context);
|
|
65
|
+
|
|
66
|
+
// Print response if it exists
|
|
67
|
+
if (result !== undefined && result !== null) {
|
|
68
|
+
const jsonString = JSON.stringify(result, null, 2);
|
|
69
|
+
console.log(jsonString);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Print success message if provided
|
|
73
|
+
if (successMessage) {
|
|
74
|
+
logger.info(successMessage);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return result;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
logger.error("Operation failed");
|
|
80
|
+
printOutError(error, debug);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { logger } from "../../logger";
|
|
2
|
+
import { withGroupContext } from "./groupContainer";
|
|
3
|
+
|
|
4
|
+
export async function listGroupAccessTokens(
|
|
5
|
+
controlPlane: string,
|
|
6
|
+
groupName: string,
|
|
7
|
+
debug: boolean,
|
|
8
|
+
) {
|
|
9
|
+
return withGroupContext(controlPlane, async (context) => {
|
|
10
|
+
const { organizationName, groupsApi, options } = context;
|
|
11
|
+
|
|
12
|
+
logger.info(
|
|
13
|
+
`Listing access tokens for group ${groupName} in organization ${organizationName}`,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const response = await groupsApi.listGroupAccessTokens(
|
|
17
|
+
organizationName,
|
|
18
|
+
groupName,
|
|
19
|
+
options,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return response.data;
|
|
23
|
+
}, "Group access tokens listed successfully", debug);
|
|
24
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { controlPlanesByEnv, Environment } from "../constants";
|
|
3
|
+
import { listConnections } from "./connection/listconnections";
|
|
4
|
+
import { printOutGroups } from "./group/listgroups";
|
|
5
|
+
import { listGroupAccessTokens } from "./groupaccesstoken/listTokens";
|
|
6
|
+
import { printOutPackages } from "./package/listpackages";
|
|
7
|
+
import { printOutProjects } from "./project/listprojects";
|
|
8
|
+
import { listVersions } from "./version/listversions";
|
|
9
|
+
|
|
10
|
+
export const registerListCommands = (
|
|
11
|
+
cli: Command,
|
|
12
|
+
environment: Environment,
|
|
13
|
+
) => {
|
|
14
|
+
const list = cli
|
|
15
|
+
.command("ls")
|
|
16
|
+
.description("List resources of a given type")
|
|
17
|
+
.argument("<resource>", "The resource to list");
|
|
18
|
+
|
|
19
|
+
list
|
|
20
|
+
.command("project")
|
|
21
|
+
.alias("projects")
|
|
22
|
+
.description("List all projects.")
|
|
23
|
+
.option("--debug")
|
|
24
|
+
.action((options) => {
|
|
25
|
+
printOutProjects(controlPlanesByEnv[environment], options.debug);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
list
|
|
29
|
+
.command("connection")
|
|
30
|
+
.alias("connections")
|
|
31
|
+
.description("List all connections.")
|
|
32
|
+
.option("--debug")
|
|
33
|
+
.action((options) => {
|
|
34
|
+
listConnections(controlPlanesByEnv[environment], options.debug);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
list
|
|
38
|
+
.command("package")
|
|
39
|
+
.alias("packages")
|
|
40
|
+
.description("List the packages in the active project.")
|
|
41
|
+
.option("--debug")
|
|
42
|
+
.action((options) => {
|
|
43
|
+
printOutPackages(controlPlanesByEnv[environment], options.debug);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
list
|
|
47
|
+
.command("version")
|
|
48
|
+
.alias("versions")
|
|
49
|
+
.description("List the versions of a package.")
|
|
50
|
+
.argument(
|
|
51
|
+
"<packageName>",
|
|
52
|
+
"The name of the package to list the versions of.",
|
|
53
|
+
)
|
|
54
|
+
.option("--debug")
|
|
55
|
+
.action((packageName, options) => {
|
|
56
|
+
listVersions(
|
|
57
|
+
controlPlanesByEnv[environment],
|
|
58
|
+
packageName,
|
|
59
|
+
options.debug,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
list
|
|
64
|
+
.command("group")
|
|
65
|
+
.alias("groups")
|
|
66
|
+
.description("List all groups in the organization.")
|
|
67
|
+
.option("--debug")
|
|
68
|
+
.action((options) => {
|
|
69
|
+
printOutGroups(controlPlanesByEnv[environment], options.debug);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
list
|
|
74
|
+
.command("group-access-token")
|
|
75
|
+
.alias("group-access-tokens")
|
|
76
|
+
.description("List all access tokens for a group.")
|
|
77
|
+
.argument(
|
|
78
|
+
"<groupName>",
|
|
79
|
+
"The name of the group",
|
|
80
|
+
)
|
|
81
|
+
.option("--debug")
|
|
82
|
+
.action((groupName, options) => {
|
|
83
|
+
listGroupAccessTokens(
|
|
84
|
+
controlPlanesByEnv[environment],
|
|
85
|
+
groupName,
|
|
86
|
+
options.debug,
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { expect } from "chai";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import sinon from "sinon";
|
|
7
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
8
|
+
import { login } from "./login";
|
|
9
|
+
|
|
10
|
+
function createFakeIdToken(payload: Record<string, unknown>): string {
|
|
11
|
+
const header = Buffer.from(
|
|
12
|
+
JSON.stringify({ alg: "none", typ: "JWT" }),
|
|
13
|
+
).toString("base64url");
|
|
14
|
+
const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
15
|
+
return `${header}.${body}.`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe("login", () => {
|
|
19
|
+
let tmpConfigFilePath: string;
|
|
20
|
+
let axiosStub: sinon.SinonStub;
|
|
21
|
+
const mockDeviceCodeResponse = {
|
|
22
|
+
data: {
|
|
23
|
+
verification_uri_complete: "https://example.com",
|
|
24
|
+
user_code: "123456",
|
|
25
|
+
device_code: "device-code-123",
|
|
26
|
+
interval: 1,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const fakeJwtPayload = {
|
|
31
|
+
name: "Test User",
|
|
32
|
+
email: "test@example.com",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const mockedAccessTokenResponse = {
|
|
36
|
+
data: {
|
|
37
|
+
id_token: createFakeIdToken(fakeJwtPayload),
|
|
38
|
+
access_token: "mock-access-token",
|
|
39
|
+
refresh_token: "mock-refresh-token",
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
tmpConfigFilePath = join(os.tmpdir(), "cred.json");
|
|
45
|
+
fs.writeFileSync(tmpConfigFilePath, "{}");
|
|
46
|
+
axiosStub = sinon.stub(axios, "request");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
fs.rmSync(tmpConfigFilePath);
|
|
51
|
+
axiosStub.restore();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should not delete config properties on login", async function () {
|
|
55
|
+
this.timeout(2000);
|
|
56
|
+
const config = new ClientConfiguration(tmpConfigFilePath);
|
|
57
|
+
config.setEnvironment("localhost");
|
|
58
|
+
config.setOrganization("foo");
|
|
59
|
+
config.setProject("bar");
|
|
60
|
+
axiosStub
|
|
61
|
+
.onFirstCall()
|
|
62
|
+
.resolves(mockDeviceCodeResponse)
|
|
63
|
+
.onSecondCall()
|
|
64
|
+
.resolves(mockedAccessTokenResponse);
|
|
65
|
+
await login("foo", tmpConfigFilePath);
|
|
66
|
+
expect(config.getOrganization()).to.equal("foo");
|
|
67
|
+
expect(config.getProject()).to.equal("bar");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should change the active organization when login succeeds", async function () {
|
|
71
|
+
this.timeout(2000);
|
|
72
|
+
axiosStub
|
|
73
|
+
.onFirstCall()
|
|
74
|
+
.resolves(mockDeviceCodeResponse)
|
|
75
|
+
.onSecondCall()
|
|
76
|
+
.resolves(mockedAccessTokenResponse);
|
|
77
|
+
const config = new ClientConfiguration(tmpConfigFilePath);
|
|
78
|
+
config.setEnvironment("localhost");
|
|
79
|
+
config.setOrganization("foo");
|
|
80
|
+
config.setProject("bar");
|
|
81
|
+
await login("test", tmpConfigFilePath);
|
|
82
|
+
expect(config.getOrganization()).to.equal("test");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should set an access token when login succeeds", async function () {
|
|
86
|
+
this.timeout(2000);
|
|
87
|
+
axiosStub
|
|
88
|
+
.onFirstCall()
|
|
89
|
+
.resolves(mockDeviceCodeResponse)
|
|
90
|
+
.onSecondCall()
|
|
91
|
+
.resolves(mockedAccessTokenResponse);
|
|
92
|
+
const config = new ClientConfiguration(tmpConfigFilePath);
|
|
93
|
+
await login("test", tmpConfigFilePath);
|
|
94
|
+
expect(config.getAccessToken()).to.equal(
|
|
95
|
+
mockedAccessTokenResponse.data.access_token,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should unset the project field when switching organizations", async function () {
|
|
100
|
+
this.timeout(2000);
|
|
101
|
+
axiosStub
|
|
102
|
+
.onFirstCall()
|
|
103
|
+
.resolves(mockDeviceCodeResponse)
|
|
104
|
+
.onSecondCall()
|
|
105
|
+
.resolves(mockedAccessTokenResponse);
|
|
106
|
+
const config = new ClientConfiguration(tmpConfigFilePath);
|
|
107
|
+
config.setEnvironment("localhost");
|
|
108
|
+
config.setOrganization("foo");
|
|
109
|
+
config.setProject("bar");
|
|
110
|
+
await login("not-foo", tmpConfigFilePath);
|
|
111
|
+
expect(config.getProject()).to.equal(undefined);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should not unset the project field when logging in with the same organization", async function () {
|
|
115
|
+
this.timeout(2000);
|
|
116
|
+
axiosStub
|
|
117
|
+
.onFirstCall()
|
|
118
|
+
.resolves(mockDeviceCodeResponse)
|
|
119
|
+
.onSecondCall()
|
|
120
|
+
.resolves(mockedAccessTokenResponse);
|
|
121
|
+
const config = new ClientConfiguration(tmpConfigFilePath);
|
|
122
|
+
config.setEnvironment("localhost");
|
|
123
|
+
config.setOrganization("foo");
|
|
124
|
+
config.setProject("bar");
|
|
125
|
+
await login("foo", tmpConfigFilePath);
|
|
126
|
+
expect(config.getProject()).to.equal("bar");
|
|
127
|
+
});
|
|
128
|
+
});
|