@credibledata/cred-cli 0.0.6
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/.github/workflows/build.yml +23 -0
- package/.mocharc.json +10 -0
- package/.prettierignore +2 -0
- package/.prettierrc +4 -0
- package/README-DEV.md +40 -0
- package/README.md +11 -0
- package/bun.lock +1158 -0
- package/dist/client/api.js +7715 -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 +205 -0
- package/dist/clientconfiguration.js.map +1 -0
- package/dist/clientconfiguration.spec.js +381 -0
- package/dist/clientconfiguration.spec.js.map +1 -0
- package/dist/commands/add.js +66 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/connection/createconnections.js +89 -0
- package/dist/commands/connection/createconnections.js.map +1 -0
- package/dist/commands/connection/createconnections.spec.js +219 -0
- package/dist/commands/connection/createconnections.spec.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/deleteconnection.spec.js +130 -0
- package/dist/commands/connection/deleteconnection.spec.js.map +1 -0
- package/dist/commands/connection/listconnections.js +50 -0
- package/dist/commands/connection/listconnections.js.map +1 -0
- package/dist/commands/connection/listconnections.spec.js +117 -0
- package/dist/commands/connection/listconnections.spec.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 +75 -0
- package/dist/commands/group/addmember.js.map +1 -0
- package/dist/commands/group/addmember.spec.js +148 -0
- package/dist/commands/group/addmember.spec.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/creategroup.spec.js +122 -0
- package/dist/commands/group/creategroup.spec.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/deletegroup.spec.js +104 -0
- package/dist/commands/group/deletegroup.spec.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/getgroup.spec.js +111 -0
- package/dist/commands/group/getgroup.spec.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/listgroups.spec.js +118 -0
- package/dist/commands/group/listgroups.spec.js.map +1 -0
- package/dist/commands/group/removemember.js +69 -0
- package/dist/commands/group/removemember.js.map +1 -0
- package/dist/commands/group/removemember.spec.js +138 -0
- package/dist/commands/group/removemember.spec.js.map +1 -0
- package/dist/commands/groupaccesstoken/createToken.js +53 -0
- package/dist/commands/groupaccesstoken/createToken.js.map +1 -0
- package/dist/commands/groupaccesstoken/createToken.spec.js +127 -0
- package/dist/commands/groupaccesstoken/createToken.spec.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/deleteToken.spec.js +103 -0
- package/dist/commands/groupaccesstoken/deleteToken.spec.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/groupaccesstoken/listTokens.spec.js +115 -0
- package/dist/commands/groupaccesstoken/listTokens.spec.js.map +1 -0
- package/dist/commands/list.js +75 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/misc/login.js +290 -0
- package/dist/commands/misc/login.js.map +1 -0
- package/dist/commands/misc/login.spec.js +243 -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/logout.spec.js +30 -0
- package/dist/commands/misc/logout.spec.js.map +1 -0
- package/dist/commands/misc/loopbackOAuth.js +110 -0
- package/dist/commands/misc/loopbackOAuth.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/misc/set-access-token.spec.js +65 -0
- package/dist/commands/misc/set-access-token.spec.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/deletepackage.spec.js +136 -0
- package/dist/commands/package/deletepackage.spec.js.map +1 -0
- package/dist/commands/package/listpackages.js +57 -0
- package/dist/commands/package/listpackages.js.map +1 -0
- package/dist/commands/package/listpackages.spec.js +129 -0
- package/dist/commands/package/listpackages.spec.js.map +1 -0
- package/dist/commands/package/publish.js +157 -0
- package/dist/commands/package/publish.js.map +1 -0
- package/dist/commands/package/publish.spec.js +511 -0
- package/dist/commands/package/publish.spec.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 +189 -0
- package/dist/commands/package/updatepackage.spec.js.map +1 -0
- package/dist/commands/project/createproject.js +75 -0
- package/dist/commands/project/createproject.js.map +1 -0
- package/dist/commands/project/createproject.spec.js +154 -0
- package/dist/commands/project/createproject.spec.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/deleteproject.spec.js +106 -0
- package/dist/commands/project/deleteproject.spec.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/getproject.spec.js +99 -0
- package/dist/commands/project/getproject.spec.js.map +1 -0
- package/dist/commands/project/listprojects.js +52 -0
- package/dist/commands/project/listprojects.js.map +1 -0
- package/dist/commands/project/listprojects.spec.js +111 -0
- package/dist/commands/project/listprojects.spec.js.map +1 -0
- package/dist/commands/project/setproject.js +26 -0
- package/dist/commands/project/setproject.js.map +1 -0
- package/dist/commands/project/setproject.spec.js +58 -0
- package/dist/commands/project/setproject.spec.js.map +1 -0
- package/dist/commands/project/updateproject.js +68 -0
- package/dist/commands/project/updateproject.js.map +1 -0
- package/dist/commands/project/updateproject.spec.js +129 -0
- package/dist/commands/project/updateproject.spec.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 +42 -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/commands/version/listversions.spec.js +121 -0
- package/dist/commands/version/listversions.spec.js.map +1 -0
- package/dist/common/UserGroupId.js +112 -0
- package/dist/common/UserGroupId.js.map +1 -0
- package/dist/common/UserGroupId.spec.js +92 -0
- package/dist/common/UserGroupId.spec.js.map +1 -0
- package/dist/constants.js +90 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.js +159 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.js +77 -0
- package/dist/logger.js.map +1 -0
- package/dist/logger.spec.js +125 -0
- package/dist/logger.spec.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 +110 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.spec.js +158 -0
- package/dist/utils.spec.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 +18 -0
- package/docker-compose.yml +18 -0
- package/eslint.config.mjs +45 -0
- package/generate-client.sh +27 -0
- package/mocha.setup.ts +4 -0
- package/openapitools.json +7 -0
- package/package.json +75 -0
- package/src/client/.openapi-generator/FILES +9 -0
- package/src/client/.openapi-generator/VERSION +1 -0
- package/src/client/.openapi-generator-ignore +23 -0
- package/src/client/api.ts +9729 -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 +490 -0
- package/src/clientconfiguration.ts +263 -0
- package/src/commands/add.ts +125 -0
- package/src/commands/connection/createconnections.spec.ts +403 -0
- package/src/commands/connection/createconnections.ts +109 -0
- package/src/commands/connection/deleteconnection.spec.ts +189 -0
- package/src/commands/connection/deleteconnection.ts +57 -0
- package/src/commands/connection/listconnections.spec.ts +132 -0
- package/src/commands/connection/listconnections.ts +58 -0
- package/src/commands/get.ts +31 -0
- package/src/commands/group/addmember.spec.ts +257 -0
- package/src/commands/group/addmember.ts +85 -0
- package/src/commands/group/creategroup.spec.ts +146 -0
- package/src/commands/group/creategroup.ts +54 -0
- package/src/commands/group/deletegroup.spec.ts +120 -0
- package/src/commands/group/deletegroup.ts +45 -0
- package/src/commands/group/getgroup.spec.ts +129 -0
- package/src/commands/group/getgroup.ts +47 -0
- package/src/commands/group/listgroups.spec.ts +137 -0
- package/src/commands/group/listgroups.ts +45 -0
- package/src/commands/group/removemember.spec.ts +224 -0
- package/src/commands/group/removemember.ts +75 -0
- package/src/commands/groupaccesstoken/createToken.spec.ts +211 -0
- package/src/commands/groupaccesstoken/createToken.ts +72 -0
- package/src/commands/groupaccesstoken/deleteToken.spec.ts +147 -0
- package/src/commands/groupaccesstoken/deleteToken.ts +29 -0
- package/src/commands/groupaccesstoken/groupContainer.ts +83 -0
- package/src/commands/groupaccesstoken/listTokens.spec.ts +147 -0
- package/src/commands/groupaccesstoken/listTokens.ts +29 -0
- package/src/commands/list.ts +131 -0
- package/src/commands/misc/login.spec.ts +213 -0
- package/src/commands/misc/login.ts +325 -0
- package/src/commands/misc/logout.spec.ts +32 -0
- package/src/commands/misc/logout.ts +9 -0
- package/src/commands/misc/loopbackOAuth.ts +127 -0
- package/src/commands/misc/set-access-token.spec.ts +95 -0
- package/src/commands/misc/set-access-token.ts +32 -0
- package/src/commands/package/deletepackage.spec.ts +164 -0
- package/src/commands/package/deletepackage.ts +58 -0
- package/src/commands/package/listpackages.spec.ts +147 -0
- package/src/commands/package/listpackages.ts +67 -0
- package/src/commands/package/publish.spec.ts +597 -0
- package/src/commands/package/publish.ts +211 -0
- package/src/commands/package/updatepackage.spec.ts +319 -0
- package/src/commands/package/updatepackage.ts +95 -0
- package/src/commands/project/createproject.spec.ts +247 -0
- package/src/commands/project/createproject.ts +70 -0
- package/src/commands/project/deleteproject.spec.ts +123 -0
- package/src/commands/project/deleteproject.ts +48 -0
- package/src/commands/project/getproject.spec.ts +109 -0
- package/src/commands/project/getproject.ts +43 -0
- package/src/commands/project/listprojects.spec.ts +121 -0
- package/src/commands/project/listprojects.ts +62 -0
- package/src/commands/project/setproject.spec.ts +63 -0
- package/src/commands/project/setproject.ts +14 -0
- package/src/commands/project/updateproject.spec.ts +217 -0
- package/src/commands/project/updateproject.ts +82 -0
- package/src/commands/rm.ts +101 -0
- package/src/commands/set.ts +16 -0
- package/src/commands/update.ts +64 -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.spec.ts +138 -0
- package/src/commands/version/listversions.ts +45 -0
- package/src/common/UserGroupId.spec.ts +117 -0
- package/src/common/UserGroupId.ts +137 -0
- package/src/constants.ts +116 -0
- package/src/index.ts +209 -0
- package/src/logger.spec.ts +158 -0
- package/src/logger.ts +86 -0
- package/src/polyfills/file.polyfill.ts +6 -0
- package/src/utils.spec.ts +135 -0
- package/src/utils.ts +115 -0
- package/src/validator.spec.ts +51 -0
- package/src/validator.ts +44 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import sinon from "sinon";
|
|
3
|
+
import { VersionsApi } from "../../client/api";
|
|
4
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
5
|
+
import { logger } from "../../logger";
|
|
6
|
+
import { prettifyJson } from "../../utils";
|
|
7
|
+
import { listVersions } from "./listversions";
|
|
8
|
+
|
|
9
|
+
describe("list-versions", () => {
|
|
10
|
+
let sandbox: sinon.SinonSandbox;
|
|
11
|
+
let listVersionsStub: sinon.SinonStub;
|
|
12
|
+
let loggerStub: sinon.SinonStubbedInstance<typeof logger>;
|
|
13
|
+
let consoleLogStub: sinon.SinonStub;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
sandbox = sinon.createSandbox();
|
|
17
|
+
listVersionsStub = sandbox.stub();
|
|
18
|
+
loggerStub = sandbox.stub(logger);
|
|
19
|
+
consoleLogStub = sandbox.stub(console, "log");
|
|
20
|
+
|
|
21
|
+
sandbox
|
|
22
|
+
.stub(ClientConfiguration.prototype, "getOrganization")
|
|
23
|
+
.returns("test-org");
|
|
24
|
+
sandbox
|
|
25
|
+
.stub(ClientConfiguration.prototype, "getProject")
|
|
26
|
+
.returns("test-project");
|
|
27
|
+
sandbox
|
|
28
|
+
.stub(ClientConfiguration.prototype, "doesConfigExists")
|
|
29
|
+
.returns(true);
|
|
30
|
+
sandbox
|
|
31
|
+
.stub(ClientConfiguration.prototype, "getHeaders")
|
|
32
|
+
.returns({ Authorization: "Bearer test-token" });
|
|
33
|
+
|
|
34
|
+
sandbox
|
|
35
|
+
.stub(VersionsApi.prototype, "listVersions")
|
|
36
|
+
.callsFake(listVersionsStub);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
sandbox.restore();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should list versions successfully", async () => {
|
|
44
|
+
const mockVersions = [
|
|
45
|
+
{ id: "1.0.0", archiveStatus: "active" },
|
|
46
|
+
{ id: "2.0.0", archiveStatus: "active" },
|
|
47
|
+
];
|
|
48
|
+
const mockResponse = {
|
|
49
|
+
data: mockVersions,
|
|
50
|
+
};
|
|
51
|
+
listVersionsStub.resolves(mockResponse);
|
|
52
|
+
|
|
53
|
+
await listVersions("http://test-server", "/test-package", false);
|
|
54
|
+
|
|
55
|
+
expect(listVersionsStub.calledOnce).to.be.true;
|
|
56
|
+
expect(listVersionsStub.firstCall.args[0]).to.equal("test-org");
|
|
57
|
+
expect(listVersionsStub.firstCall.args[1]).to.equal("test-project");
|
|
58
|
+
expect(listVersionsStub.firstCall.args[2]).to.equal("test-package");
|
|
59
|
+
expect(listVersionsStub.firstCall.args[3]).to.deep.include({
|
|
60
|
+
baseURL: "http://test-server",
|
|
61
|
+
headers: { Authorization: "Bearer test-token" },
|
|
62
|
+
});
|
|
63
|
+
expect(consoleLogStub.calledWith(prettifyJson(mockVersions))).to.be.true;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should handle package path without leading slash", async () => {
|
|
67
|
+
const mockVersions = [{ id: "1.0.0" }];
|
|
68
|
+
const mockResponse = {
|
|
69
|
+
data: mockVersions,
|
|
70
|
+
};
|
|
71
|
+
listVersionsStub.resolves(mockResponse);
|
|
72
|
+
|
|
73
|
+
await listVersions("http://test-server", "test-package", false);
|
|
74
|
+
|
|
75
|
+
expect(listVersionsStub.firstCall.args[2]).to.equal("test-package");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should handle missing config", async () => {
|
|
79
|
+
sandbox.restore();
|
|
80
|
+
sandbox = sinon.createSandbox();
|
|
81
|
+
listVersionsStub = sandbox.stub();
|
|
82
|
+
loggerStub = sandbox.stub(logger);
|
|
83
|
+
consoleLogStub = sandbox.stub(console, "log");
|
|
84
|
+
|
|
85
|
+
sandbox
|
|
86
|
+
.stub(ClientConfiguration.prototype, "doesConfigExists")
|
|
87
|
+
.returns(false);
|
|
88
|
+
sandbox
|
|
89
|
+
.stub(VersionsApi.prototype, "listVersions")
|
|
90
|
+
.callsFake(listVersionsStub);
|
|
91
|
+
|
|
92
|
+
await listVersions("http://test-server", "/test-package", false);
|
|
93
|
+
|
|
94
|
+
expect(listVersionsStub.called).to.be.false;
|
|
95
|
+
expect(
|
|
96
|
+
loggerStub.error.calledWith(
|
|
97
|
+
sinon.match("Please, make sure that you are logged in"),
|
|
98
|
+
),
|
|
99
|
+
).to.be.true;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("should handle missing project", async () => {
|
|
103
|
+
sandbox.restore();
|
|
104
|
+
sandbox = sinon.createSandbox();
|
|
105
|
+
listVersionsStub = sandbox.stub();
|
|
106
|
+
loggerStub = sandbox.stub(logger);
|
|
107
|
+
consoleLogStub = sandbox.stub(console, "log");
|
|
108
|
+
|
|
109
|
+
sandbox
|
|
110
|
+
.stub(ClientConfiguration.prototype, "doesConfigExists")
|
|
111
|
+
.returns(true);
|
|
112
|
+
sandbox.stub(ClientConfiguration.prototype, "getProject").returns("");
|
|
113
|
+
sandbox
|
|
114
|
+
.stub(VersionsApi.prototype, "listVersions")
|
|
115
|
+
.callsFake(listVersionsStub);
|
|
116
|
+
|
|
117
|
+
await listVersions("http://test-server", "/test-package", false);
|
|
118
|
+
|
|
119
|
+
expect(listVersionsStub.called).to.be.false;
|
|
120
|
+
expect(
|
|
121
|
+
loggerStub.error.calledWith(
|
|
122
|
+
sinon.match("Please, make sure to set a project"),
|
|
123
|
+
),
|
|
124
|
+
).to.be.true;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should handle API errors", async () => {
|
|
128
|
+
const mockError = new Error("API Error");
|
|
129
|
+
listVersionsStub.rejects(mockError);
|
|
130
|
+
|
|
131
|
+
await listVersions("http://test-server", "/test-package", true);
|
|
132
|
+
|
|
133
|
+
expect(listVersionsStub.calledOnce).to.be.true;
|
|
134
|
+
expect(
|
|
135
|
+
loggerStub.error.calledWith(sinon.match("Failed to list versions")),
|
|
136
|
+
).to.be.true;
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { VersionsApi } from "../../client/api";
|
|
2
|
+
import { Configuration } from "../../client/configuration";
|
|
3
|
+
import { ClientConfiguration } from "../../clientconfiguration";
|
|
4
|
+
import { logger } from "../../logger";
|
|
5
|
+
import { prettifyJson, printOutError } from "../../utils";
|
|
6
|
+
|
|
7
|
+
const versionsApi = new VersionsApi(new Configuration());
|
|
8
|
+
|
|
9
|
+
export async function listVersions(
|
|
10
|
+
controlPlane: string,
|
|
11
|
+
packagePath: string,
|
|
12
|
+
debug: boolean,
|
|
13
|
+
) {
|
|
14
|
+
const clientConfig = new ClientConfiguration();
|
|
15
|
+
const organizationName = clientConfig.getOrganization();
|
|
16
|
+
const projectName = clientConfig.getProject();
|
|
17
|
+
|
|
18
|
+
if (!clientConfig.doesConfigExists()) {
|
|
19
|
+
logger.error("Please, make sure that you are logged in");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!projectName) {
|
|
24
|
+
logger.error("Please, make sure to set a project");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const packageName = packagePath.replace("/", "");
|
|
30
|
+
const response = await versionsApi.listVersions(
|
|
31
|
+
organizationName,
|
|
32
|
+
projectName,
|
|
33
|
+
packageName,
|
|
34
|
+
{
|
|
35
|
+
baseURL: controlPlane,
|
|
36
|
+
headers: clientConfig.getHeaders(),
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
console.log(prettifyJson(response.data));
|
|
41
|
+
} catch (e) {
|
|
42
|
+
logger.error("Failed to list versions");
|
|
43
|
+
printOutError(e, debug);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import { ResourceType, UserGroupId } from "./UserGroupId";
|
|
3
|
+
|
|
4
|
+
describe("UserGroupId", () => {
|
|
5
|
+
describe("constructor", () => {
|
|
6
|
+
it("should parse a valid user id", () => {
|
|
7
|
+
const id = new UserGroupId("user:john");
|
|
8
|
+
expect(id.getResourceType()).to.equal(ResourceType.USER);
|
|
9
|
+
expect(id.getResourceName()).to.equal("john");
|
|
10
|
+
expect(id.getValue()).to.equal("user:john");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should parse a valid group id", () => {
|
|
14
|
+
const id = new UserGroupId("group:admins");
|
|
15
|
+
expect(id.getResourceType()).to.equal(ResourceType.GROUP);
|
|
16
|
+
expect(id.getResourceName()).to.equal("admins");
|
|
17
|
+
expect(id.getValue()).to.equal("group:admins");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should trim whitespace from input", () => {
|
|
21
|
+
const id = new UserGroupId(" user:john ");
|
|
22
|
+
expect(id.getValue()).to.equal("user:john");
|
|
23
|
+
expect(id.getResourceName()).to.equal("john");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should throw for null or empty input", () => {
|
|
27
|
+
expect(() => new UserGroupId("")).to.throw("cannot be null or empty");
|
|
28
|
+
expect(() => new UserGroupId(" ")).to.throw(
|
|
29
|
+
"cannot be null or empty",
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should throw for invalid format", () => {
|
|
34
|
+
expect(() => new UserGroupId("invalid")).to.throw(
|
|
35
|
+
"Invalid UserGroupId format",
|
|
36
|
+
);
|
|
37
|
+
expect(() => new UserGroupId("user:")).to.throw(
|
|
38
|
+
"Invalid UserGroupId format",
|
|
39
|
+
);
|
|
40
|
+
expect(() => new UserGroupId("foo:bar")).to.throw(
|
|
41
|
+
"Invalid UserGroupId format",
|
|
42
|
+
);
|
|
43
|
+
expect(() => new UserGroupId("user:a:b")).to.throw(
|
|
44
|
+
"Invalid UserGroupId format",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("static factory methods", () => {
|
|
50
|
+
it("forPublicAccess should create user:* id", () => {
|
|
51
|
+
const id = UserGroupId.forPublicAccess();
|
|
52
|
+
expect(id.getResourceType()).to.equal(ResourceType.USER);
|
|
53
|
+
expect(id.getResourceName()).to.equal("*");
|
|
54
|
+
expect(id.getValue()).to.equal("user:*");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("forUser should create a user id", () => {
|
|
58
|
+
const id = UserGroupId.forUser("alice");
|
|
59
|
+
expect(id.getResourceType()).to.equal(ResourceType.USER);
|
|
60
|
+
expect(id.getResourceName()).to.equal("alice");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("forUser should throw for undefined user name", () => {
|
|
64
|
+
expect(() => UserGroupId.forUser(undefined)).to.throw(
|
|
65
|
+
"cannot be undefined",
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("forGroup should create a group id", () => {
|
|
70
|
+
const id = UserGroupId.forGroup("developers");
|
|
71
|
+
expect(id.getResourceType()).to.equal(ResourceType.GROUP);
|
|
72
|
+
expect(id.getResourceName()).to.equal("developers");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("create should build from ResourceType and name", () => {
|
|
76
|
+
const userId = UserGroupId.create(ResourceType.USER, "bob");
|
|
77
|
+
expect(userId.getResourceType()).to.equal(ResourceType.USER);
|
|
78
|
+
expect(userId.getResourceName()).to.equal("bob");
|
|
79
|
+
|
|
80
|
+
const groupId = UserGroupId.create(ResourceType.GROUP, "team");
|
|
81
|
+
expect(groupId.getResourceType()).to.equal(ResourceType.GROUP);
|
|
82
|
+
expect(groupId.getResourceName()).to.equal("team");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("serialization", () => {
|
|
87
|
+
it("toString should return original value", () => {
|
|
88
|
+
const id = new UserGroupId("user:john");
|
|
89
|
+
expect(id.toString()).to.equal("user:john");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("toJSON should return original value for JSON serialization", () => {
|
|
93
|
+
const id = new UserGroupId("group:admins");
|
|
94
|
+
expect(id.toJSON()).to.equal("group:admins");
|
|
95
|
+
expect(JSON.stringify(id)).to.equal('"group:admins"');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("isPublicAccess", () => {
|
|
100
|
+
it("should return false for regular user ids", () => {
|
|
101
|
+
const id = new UserGroupId("user:john");
|
|
102
|
+
expect(id.isPublicAccess()).to.be.false;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should return false for group ids", () => {
|
|
106
|
+
const id = new UserGroupId("group:admins");
|
|
107
|
+
expect(id.isPublicAccess()).to.be.false;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should return false for user:* (checks originalValue not resourceName)", () => {
|
|
111
|
+
// isPublicAccess checks this.originalValue === "*" which is never true
|
|
112
|
+
// since originalValue is the full string "user:*"
|
|
113
|
+
const id = UserGroupId.forPublicAccess();
|
|
114
|
+
expect(id.isPublicAccess()).to.be.false;
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum representing the different types of user/group resources.
|
|
3
|
+
*/
|
|
4
|
+
export enum ResourceType {
|
|
5
|
+
USER = "USER",
|
|
6
|
+
GROUP = "GROUP",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Represents a user or group identifier in the format 'user:userId' or 'group:groupId'.
|
|
11
|
+
* This class parses the input string and provides methods to extract the
|
|
12
|
+
* resource type and name.
|
|
13
|
+
*/
|
|
14
|
+
export class UserGroupId {
|
|
15
|
+
private readonly resourceType: ResourceType;
|
|
16
|
+
private readonly resourceName: string;
|
|
17
|
+
private readonly originalValue: string;
|
|
18
|
+
|
|
19
|
+
static forPublicAccess(): UserGroupId {
|
|
20
|
+
return new UserGroupId(`user:*`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static forUser(userName: string | undefined): UserGroupId {
|
|
24
|
+
if (!userName) {
|
|
25
|
+
throw new Error("User name cannot be undefined");
|
|
26
|
+
}
|
|
27
|
+
return new UserGroupId(`user:${userName}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static forGroup(groupName: string): UserGroupId {
|
|
31
|
+
return new UserGroupId(`group:${groupName}`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates a UserGroupId from a string in the format 'user:userId' or 'group:groupId'.
|
|
35
|
+
*
|
|
36
|
+
* @param value the string to parse
|
|
37
|
+
* @throws BadRequestException if the format is invalid
|
|
38
|
+
*/
|
|
39
|
+
constructor(value: string) {
|
|
40
|
+
if (!value || value.trim().length === 0) {
|
|
41
|
+
throw new Error("UserGroupId cannot be null or empty");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.originalValue = value.trim();
|
|
45
|
+
|
|
46
|
+
if (!this.originalValue.match(/^(user:[^:]+|group:[^:]+)$/)) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Invalid UserGroupId format. Expected 'user:userId' or 'group:groupId', got: ${this.originalValue}`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const parts = this.originalValue.split(":", 2);
|
|
53
|
+
const typeStr = parts[0];
|
|
54
|
+
const name = parts[1];
|
|
55
|
+
|
|
56
|
+
if (!name || name.length === 0) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`UserGroupId name cannot be empty. Expected 'user:userId' or 'group:groupId', got: ${this.originalValue}`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
switch (typeStr) {
|
|
63
|
+
case "user":
|
|
64
|
+
this.resourceType = ResourceType.USER;
|
|
65
|
+
break;
|
|
66
|
+
case "group":
|
|
67
|
+
this.resourceType = ResourceType.GROUP;
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Invalid UserGroupId type. Expected 'user' or 'group', got: ${typeStr}`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.resourceName = name;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Creates a UserGroupId from resource type and name.
|
|
80
|
+
*
|
|
81
|
+
* @param resourceType the resource type
|
|
82
|
+
* @param userName the user or group name
|
|
83
|
+
*/
|
|
84
|
+
public static create(
|
|
85
|
+
resourceType: ResourceType,
|
|
86
|
+
userName: string,
|
|
87
|
+
): UserGroupId {
|
|
88
|
+
return new UserGroupId(`${resourceType.toLowerCase()}:${userName}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Returns the resource type (USER or GROUP).
|
|
93
|
+
*
|
|
94
|
+
* @return the resource type
|
|
95
|
+
*/
|
|
96
|
+
public getResourceType(): ResourceType {
|
|
97
|
+
return this.resourceType;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns the resource name (the part after the colon).
|
|
102
|
+
*
|
|
103
|
+
* @return the resource name
|
|
104
|
+
*/
|
|
105
|
+
public getResourceName(): string {
|
|
106
|
+
return this.resourceName;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Returns the original string value.
|
|
111
|
+
*
|
|
112
|
+
* @return the original string value
|
|
113
|
+
*/
|
|
114
|
+
public getValue(): string {
|
|
115
|
+
return this.originalValue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public toString(): string {
|
|
119
|
+
return this.originalValue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Custom JSON serialization method for axios/openapi.
|
|
124
|
+
* This ensures UserGroupId is serialized as a string (originalValue) instead of an object.
|
|
125
|
+
*
|
|
126
|
+
* @return the original string value for JSON serialization
|
|
127
|
+
*/
|
|
128
|
+
public toJSON(): string {
|
|
129
|
+
return this.originalValue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public isPublicAccess(): boolean {
|
|
133
|
+
return (
|
|
134
|
+
this.resourceType === ResourceType.USER && this.originalValue === "*"
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export type Environment =
|
|
2
|
+
| "production"
|
|
3
|
+
| "staging"
|
|
4
|
+
| "dev"
|
|
5
|
+
| "localhost"
|
|
6
|
+
| "e2e-test"
|
|
7
|
+
| "videoamp";
|
|
8
|
+
|
|
9
|
+
export const controlPlanesByEnv: Record<Environment, string> = {
|
|
10
|
+
production: "https://admin.credibledata.com/api/v0",
|
|
11
|
+
dev: "https://dev-admin.credibledata.com/api/v0",
|
|
12
|
+
staging: "https://staging-admin.credibledata.com/api/v0",
|
|
13
|
+
localhost: "http://admin.ms2.localhost/api/v0",
|
|
14
|
+
"e2e-test": "http://admin.ms2.localhost/api/v0",
|
|
15
|
+
videoamp: "https://admin.videoamp-aws-us-east-1.credibledata.com/api/v0",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/** Environments that must have an object in `~/.cred` `configPerEnvironment` (avoids undefined on write). */
|
|
19
|
+
export const ALL_ENVIRONMENTS = Object.keys(
|
|
20
|
+
controlPlanesByEnv,
|
|
21
|
+
) as Environment[];
|
|
22
|
+
|
|
23
|
+
export const auth0ConfigsByEnv: Record<
|
|
24
|
+
Environment,
|
|
25
|
+
{
|
|
26
|
+
domain: string;
|
|
27
|
+
clientId: string;
|
|
28
|
+
clientSecret?: string;
|
|
29
|
+
audience: string;
|
|
30
|
+
}
|
|
31
|
+
> = {
|
|
32
|
+
production: {
|
|
33
|
+
domain: "https://auth.credibledata.com",
|
|
34
|
+
clientId: "ge8JL5TJNwqy7bygAaJkD92KdluqEZgO",
|
|
35
|
+
audience: "https://ms2data.us.auth0.com/api/v2/",
|
|
36
|
+
},
|
|
37
|
+
dev: {
|
|
38
|
+
domain: "https://dev-auth.credibledata.com",
|
|
39
|
+
clientId: "rr6mzJNj9b104MjCc9xWKPPehq1MJx0L",
|
|
40
|
+
audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
|
|
41
|
+
},
|
|
42
|
+
staging: {
|
|
43
|
+
domain: "https://dev-auth.credibledata.com",
|
|
44
|
+
clientId: "rr6mzJNj9b104MjCc9xWKPPehq1MJx0L",
|
|
45
|
+
audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
|
|
46
|
+
},
|
|
47
|
+
localhost: {
|
|
48
|
+
domain: "https://dev-auth.credibledata.com",
|
|
49
|
+
clientId: "rr6mzJNj9b104MjCc9xWKPPehq1MJx0L",
|
|
50
|
+
audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
|
|
51
|
+
},
|
|
52
|
+
"e2e-test": {
|
|
53
|
+
domain: "https://dev-auth.credibledata.com",
|
|
54
|
+
clientId: "atd8n8dEiGUiNRM7Geuvg41fi5s8ZKqY",
|
|
55
|
+
clientSecret:
|
|
56
|
+
"ZrEvs86WLqKO9EPp4y_cOvUn3NQT1qc3XC8111f6DBt9oyaclV5sWHz6Nkyo_bEF",
|
|
57
|
+
audience: "https://dev-ohaafogw5p8uyx1m.us.auth0.com/api/v2/",
|
|
58
|
+
},
|
|
59
|
+
videoamp: {
|
|
60
|
+
domain: "https://auth.credibledata.com",
|
|
61
|
+
clientId: "ge8JL5TJNwqy7bygAaJkD92KdluqEZgO",
|
|
62
|
+
audience: "https://ms2data.us.auth0.com/api/v2/",
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `cred login <organizationName>` → Auth0 Organization ID for org-branded Universal Login.
|
|
68
|
+
*
|
|
69
|
+
* Auth0 documents the `organization` parameter on `/authorize` for Organizations
|
|
70
|
+
* (https://auth0.com/docs/manage-users/organizations/configure-organizations/use-org-name-authentication-api).
|
|
71
|
+
* The Device Authorization Flow documents only `client_id`, `scope`, and `audience` on
|
|
72
|
+
* `POST /oauth/device/code` — not `organization`
|
|
73
|
+
* (https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow/call-your-api-using-the-device-authorization-flow#device-code-parameters),
|
|
74
|
+
* so mapped orgs use Authorization Code + PKCE with `organization` on `/authorize` and
|
|
75
|
+
* {@link AUTH_CLI_LOOPBACK_REDIRECT_URI}.
|
|
76
|
+
*
|
|
77
|
+
* Align with app `ORGANIZATION_HOST_ORG_ID_MAP` / `getAuth0OrganizationAuthorizationParams`.
|
|
78
|
+
*
|
|
79
|
+
* Entries are added when PKCE + Auth0 org id is ready for that CLI name; until then the map may
|
|
80
|
+
* stay empty and `login.spec` stubs {@link getAuth0OrganizationIdForCliLogin} for PKCE coverage.
|
|
81
|
+
*/
|
|
82
|
+
export const AUTH0_ORGANIZATION_IDS_BY_CLI_ORG_NAME: Record<string, string> = {
|
|
83
|
+
// videoamp: "org_nMRKafeSuxOiuJeG",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Allowlisted on the Auth0 Native application (CLI) as an Allowed Callback URL for PKCE logins
|
|
88
|
+
* that pass `organization` on `/authorize` (see Auth0 Organizations + Authentication API docs above).
|
|
89
|
+
*/
|
|
90
|
+
export const AUTH_CLI_LOOPBACK_REDIRECT_URI = "http://127.0.0.1:18240/callback";
|
|
91
|
+
|
|
92
|
+
export function getAuth0OrganizationIdForCliLogin(
|
|
93
|
+
organizationName: string,
|
|
94
|
+
): string | undefined {
|
|
95
|
+
return AUTH0_ORGANIZATION_IDS_BY_CLI_ORG_NAME[
|
|
96
|
+
organizationName.toLowerCase()
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Time constants in ms
|
|
101
|
+
export const SECOND = 1000;
|
|
102
|
+
export const MINUTE = SECOND * 60;
|
|
103
|
+
export const HOUR = MINUTE * 60;
|
|
104
|
+
export const DAY = HOUR * 24;
|
|
105
|
+
|
|
106
|
+
// Login related
|
|
107
|
+
export const LOGIN_TIMEOUT_MS = MINUTE * 5;
|
|
108
|
+
|
|
109
|
+
export const ASCII_TITLE = `
|
|
110
|
+
_____ _ _ _ _ _____ _ _____
|
|
111
|
+
/ ____| | (_) | | | / ____| | |_ _|
|
|
112
|
+
| | _ __ ___ __| |_| |__ | | ___ | | | | | |
|
|
113
|
+
| | | '__/ _ \\/ _\` | | '_ \\| |/ _ \\ | | | | | |
|
|
114
|
+
| |____| | | __/ (_| | | |_) | | __/ | |____| |____ _| |_
|
|
115
|
+
\\_____|_| \\___|\\__,_|_|_.__/|_|\\___| \\_____|______|_____|
|
|
116
|
+
`;
|