@unito/integration-cli 0.56.0 → 0.56.2
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/dist/integrationGenerator/integrationBoilerplate/.nvmrc +1 -1
- package/dist/integrationGenerator/integrationBoilerplate/Dockerfile +2 -2
- package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.nvmrc +1 -1
- package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/Dockerfile +2 -2
- package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/package.json +2 -2
- package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts +1 -1
- package/dist/integrationGenerator/integrationBoilerplate/package.json +2 -2
- package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts +1 -1
- package/dist/src/commands/activity.js +13 -4
- package/dist/src/commands/dev.js +9 -3
- package/dist/src/commands/invite.js +13 -4
- package/dist/src/commands/oauth2.d.ts +6 -1
- package/dist/src/commands/oauth2.js +58 -55
- package/dist/src/commands/publish.js +13 -2
- package/dist/src/commands/test.js +9 -3
- package/dist/src/commands/upgrade.js +0 -12
- package/dist/src/errors.d.ts +2 -2
- package/dist/src/errors.js +11 -9
- package/dist/src/resources/configuration.d.ts +1 -1
- package/dist/src/resources/configuration.js +5 -2
- package/dist/src/resources/decryption.d.ts +10 -4
- package/dist/src/resources/decryption.js +13 -40
- package/dist/src/services/integrationsPlatform.d.ts +1 -1
- package/dist/src/services/integrationsPlatform.js +1 -8
- package/dist/test/commands/activity.test.js +3 -1
- package/dist/test/commands/invite.test.js +3 -1
- package/dist/test/commands/login.test.js +1 -1
- package/dist/test/commands/oauth2.test.js +155 -11
- package/dist/test/commands/publish.test.js +23 -23
- package/dist/test/commands/upgrade.test.js +1 -1
- package/dist/test/errors.test.js +1 -9
- package/dist/test/resources/decryption.test.js +28 -19
- package/dist/test/services/integrationsPlatform.test.js +0 -4
- package/oclif.manifest.json +36 -5
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
lts/
|
|
1
|
+
lts/iron
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Build
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
-
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/node:
|
|
7
|
+
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/node:20-alpine as build
|
|
8
8
|
|
|
9
9
|
WORKDIR /build
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ RUN npm run compile
|
|
|
19
19
|
# Runtime
|
|
20
20
|
#
|
|
21
21
|
|
|
22
|
-
FROM --platform=$TARGETPLATFORM public.ecr.aws/docker/library/node:
|
|
22
|
+
FROM --platform=$TARGETPLATFORM public.ecr.aws/docker/library/node:20-alpine as runtime
|
|
23
23
|
|
|
24
24
|
WORKDIR /app
|
|
25
25
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
lts/
|
|
1
|
+
lts/iron
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Build
|
|
5
5
|
#
|
|
6
6
|
|
|
7
|
-
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/node:
|
|
7
|
+
FROM --platform=$BUILDPLATFORM public.ecr.aws/docker/library/node:20-alpine as build
|
|
8
8
|
|
|
9
9
|
WORKDIR /build
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ RUN npm run compile
|
|
|
19
19
|
# Runtime
|
|
20
20
|
#
|
|
21
21
|
|
|
22
|
-
FROM --platform=$TARGETPLATFORM public.ecr.aws/docker/library/node:
|
|
22
|
+
FROM --platform=$TARGETPLATFORM public.ecr.aws/docker/library/node:20-alpine as runtime
|
|
23
23
|
|
|
24
24
|
WORKDIR /app
|
|
25
25
|
|
package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"email": "hello@unito.io"
|
|
18
18
|
},
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
20
|
+
"node": ">=20.0.0"
|
|
21
21
|
},
|
|
22
22
|
"license": "LicenseRef-LICENSE",
|
|
23
23
|
"dependencies": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/express": "4.x",
|
|
30
30
|
"@types/mocha": "10.x",
|
|
31
|
-
"@types/node": "
|
|
31
|
+
"@types/node": "20.x",
|
|
32
32
|
"@types/uuid": "9.x",
|
|
33
33
|
"@typescript-eslint/eslint-plugin": "5.x",
|
|
34
34
|
"@typescript-eslint/parser": "5.x",
|
|
@@ -10,7 +10,7 @@ export const extractAdditionalLoggingContext = (req: express.Request, res: expre
|
|
|
10
10
|
try {
|
|
11
11
|
additionalLoggingContext = JSON.parse(additionalLoggingContextHeader);
|
|
12
12
|
} catch (error) {
|
|
13
|
-
logger.warn(`Failed parsing header X-Unito-Additional-Logging-Context: ${
|
|
13
|
+
logger.warn(`Failed parsing header X-Unito-Additional-Logging-Context: ${additionalLoggingContextHeader}`);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"email": "hello@unito.io"
|
|
18
18
|
},
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
20
|
+
"node": ">=20.0.0"
|
|
21
21
|
},
|
|
22
22
|
"license": "LicenseRef-LICENSE",
|
|
23
23
|
"dependencies": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/express": "4.x",
|
|
30
30
|
"@types/mocha": "10.x",
|
|
31
|
-
"@types/node": "
|
|
31
|
+
"@types/node": "20.x",
|
|
32
32
|
"@types/uuid": "9.x",
|
|
33
33
|
"@typescript-eslint/eslint-plugin": "5.x",
|
|
34
34
|
"@typescript-eslint/parser": "5.x",
|
package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const extractAdditionalLoggingContext = (req: express.Request, res: expre
|
|
|
10
10
|
try {
|
|
11
11
|
additionalLoggingContext = JSON.parse(additionalLoggingContextHeader);
|
|
12
12
|
} catch (error) {
|
|
13
|
-
logger.warn(`Failed parsing header X-Unito-Additional-Logging-Context: ${
|
|
13
|
+
logger.warn(`Failed parsing header X-Unito-Additional-Logging-Context: ${additionalLoggingContextHeader}`);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -55,10 +55,19 @@ class Activity extends baseCommand_1.BaseCommand {
|
|
|
55
55
|
IntegrationsPlatform.setApiKey(apiKey);
|
|
56
56
|
IntegrationsPlatform.setEnvironment(environment);
|
|
57
57
|
core_1.ux.action.start('Finding the integration');
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
let integration;
|
|
59
|
+
try {
|
|
60
|
+
integration = await IntegrationsPlatform.getIntegrationByName(integrationConfiguration.name);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof IntegrationsPlatform.HttpError && error.status === 403) {
|
|
64
|
+
core_1.ux.log(chalk_1.default.redBright(`Access Denied! You do not have access to this integration.`));
|
|
65
|
+
this.exit(-1);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
core_1.ux.log(chalk_1.default.redBright(`Integration not found! You can only retrieve activity for existing integrations.`));
|
|
69
|
+
this.exit(-1);
|
|
70
|
+
}
|
|
62
71
|
}
|
|
63
72
|
core_1.ux.action.stop();
|
|
64
73
|
core_1.ux.action.start('Retrieving activity');
|
package/dist/src/commands/dev.js
CHANGED
|
@@ -63,15 +63,21 @@ class Dev extends baseCommand_1.BaseCommand {
|
|
|
63
63
|
// Resolve the configuration.
|
|
64
64
|
const environment = flags.environment ?? GlobalConfiguration.Environment.Production;
|
|
65
65
|
const configuration = await (0, configuration_1.getConfiguration)(environment, flags['config-path']);
|
|
66
|
-
|
|
66
|
+
let credentials = configuration.testAccounts?.[configuration_1.CredentialScope.DEVELOPMENT];
|
|
67
|
+
if (credentials) {
|
|
68
|
+
({ entries: credentials } = await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, credentials));
|
|
69
|
+
}
|
|
70
|
+
let secrets = {};
|
|
67
71
|
// Decrypt secrets, if necessary.
|
|
68
|
-
|
|
72
|
+
if (configuration.secrets) {
|
|
73
|
+
secrets = await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, configuration.secrets);
|
|
74
|
+
}
|
|
69
75
|
// Launch the debugger.
|
|
70
76
|
const commandArguments = [
|
|
71
77
|
`${process.env.NODE_MODULES_FOLDER}/@unito/integration-debugger/dist/src/index.js`,
|
|
72
78
|
'--integration-url=http://localhost:9200',
|
|
73
79
|
`--spawn-process=npm run dev`,
|
|
74
|
-
`--credential-payload=${JSON.stringify(
|
|
80
|
+
`--credential-payload=${JSON.stringify(credentials)}`,
|
|
75
81
|
`--secrets-payload=${JSON.stringify(secrets)}`,
|
|
76
82
|
];
|
|
77
83
|
if (configuration.graphRelativeUrl) {
|
|
@@ -56,10 +56,19 @@ class Invite extends baseCommand_1.BaseCommand {
|
|
|
56
56
|
},
|
|
57
57
|
]);
|
|
58
58
|
core_1.ux.action.start('Finding the integration');
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
let integration;
|
|
60
|
+
try {
|
|
61
|
+
integration = await IntegrationsPlatform.getIntegrationByName(integrationConfiguration.name);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (error instanceof IntegrationsPlatform.HttpError && error.status === 403) {
|
|
65
|
+
core_1.ux.log(chalk_1.default.redBright(`Access Denied! You do not have access to this integration.`));
|
|
66
|
+
this.exit(-1);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
core_1.ux.log(chalk_1.default.redBright(`Integration not found! You can only invite users to a published integration.`));
|
|
70
|
+
this.exit(-1);
|
|
71
|
+
}
|
|
63
72
|
}
|
|
64
73
|
core_1.ux.action.stop();
|
|
65
74
|
core_1.ux.action.start('Inviting user');
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { Environment } from '../resources/globalConfiguration';
|
|
2
3
|
export default class Oauth2 extends Command {
|
|
4
|
+
static summary: string;
|
|
3
5
|
static description: string;
|
|
4
6
|
static examples: string[];
|
|
5
7
|
static flags: {
|
|
6
|
-
|
|
8
|
+
'test-account': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
environment: import("@oclif/core/lib/interfaces").OptionFlag<Environment | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
reauth: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
'config-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
12
|
};
|
|
8
13
|
catch(error: Error): Promise<void>;
|
|
9
14
|
run(): Promise<void>;
|
|
@@ -2,18 +2,43 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
-
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
6
5
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
6
|
const configuration_1 = require("../resources/configuration");
|
|
8
7
|
const Oauth2Helper = tslib_1.__importStar(require("../services/oauth2Helper"));
|
|
8
|
+
const IntegrationsPlatform = tslib_1.__importStar(require("../services/integrationsPlatform"));
|
|
9
9
|
const configurationTypes_1 = require("../configurationTypes");
|
|
10
10
|
const errors_1 = require("../errors");
|
|
11
11
|
const globalConfiguration_1 = require("../resources/globalConfiguration");
|
|
12
|
+
const decryption_1 = require("../resources/decryption");
|
|
12
13
|
class Oauth2 extends core_1.Command {
|
|
13
|
-
static
|
|
14
|
+
static summary = 'Perform an OAuth2 workflow locally';
|
|
15
|
+
static description = 'The Oauth2 command allows you to perform an OAuth2 workflow locally, either to create a new test account or to refresh an existing one.';
|
|
14
16
|
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
15
17
|
static flags = {
|
|
16
|
-
|
|
18
|
+
'test-account': core_1.Flags.string({
|
|
19
|
+
description: 'Test account to use.',
|
|
20
|
+
options: Object.values(configuration_1.CredentialScope),
|
|
21
|
+
default: configuration_1.CredentialScope.DEVELOPMENT,
|
|
22
|
+
}),
|
|
23
|
+
environment: core_1.Flags.custom({
|
|
24
|
+
description: 'the environment of the platform',
|
|
25
|
+
options: Object.values(globalConfiguration_1.Environment),
|
|
26
|
+
default: globalConfiguration_1.Environment.Production,
|
|
27
|
+
})(),
|
|
28
|
+
reauth: core_1.Flags.boolean({
|
|
29
|
+
description: 'triggers a new oauth2 flow to collect credentials and overwrite the current one',
|
|
30
|
+
default: false,
|
|
31
|
+
}),
|
|
32
|
+
'config-path': core_1.Flags.string({
|
|
33
|
+
summary: 'relative path to a custom ".unito.json" file',
|
|
34
|
+
description: `Use a custom configuration file instead of the default '.unito.json' or other environment specific
|
|
35
|
+
ones.
|
|
36
|
+
|
|
37
|
+
If you want to force the CLI to use a specific configuration file, you can use this flag to specify the relative
|
|
38
|
+
path from your integration's root folder (with a leading '/').
|
|
39
|
+
|
|
40
|
+
Usage: <%= config.bin %> <%= command.id %> --config-path=/myCustomConfig.json`,
|
|
41
|
+
}),
|
|
17
42
|
};
|
|
18
43
|
async catch(error) {
|
|
19
44
|
/* istanbul ignore if */
|
|
@@ -24,74 +49,52 @@ class Oauth2 extends core_1.Command {
|
|
|
24
49
|
}
|
|
25
50
|
async run() {
|
|
26
51
|
const { flags } = await this.parse(Oauth2);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
const configuration = await (0, configuration_1.getConfiguration)(
|
|
30
|
-
|
|
52
|
+
const testAccount = flags['test-account'] ?? 'development';
|
|
53
|
+
const environment = flags.environment ?? globalConfiguration_1.Environment.Production;
|
|
54
|
+
const configuration = await (0, configuration_1.getConfiguration)(environment, flags['config-path']);
|
|
55
|
+
// First check for development oauth2 authorization scheme
|
|
56
|
+
let oauth2 = configuration.authorizations?.find(authorization => authorization.method === configurationTypes_1.Method.OAUTH2 && authorization.development)?.oauth2;
|
|
57
|
+
// Try for any oauth2 authorization scheme if there was no development one
|
|
31
58
|
if (!oauth2) {
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
name: 'oauth2Information',
|
|
35
|
-
type: 'editor',
|
|
36
|
-
message: `${chalk_1.default.yellowBright('OAuth2 credentials')} that will be used to authenticate to the API`,
|
|
37
|
-
validate: (value) => {
|
|
38
|
-
try {
|
|
39
|
-
JSON.parse(value);
|
|
40
|
-
}
|
|
41
|
-
catch (e) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
return true;
|
|
45
|
-
},
|
|
46
|
-
default: JSON.stringify({
|
|
47
|
-
clientId: '',
|
|
48
|
-
clientSecret: '',
|
|
49
|
-
tokenUrl: '',
|
|
50
|
-
authorizationUrl: '',
|
|
51
|
-
scopes: [{ name: '', help: '' }],
|
|
52
|
-
requestContentType: 'application/x-www-form-urlencoded',
|
|
53
|
-
responseContentType: 'application/json',
|
|
54
|
-
grantType: 'authorization_code',
|
|
55
|
-
}, null, 2),
|
|
56
|
-
},
|
|
57
|
-
]);
|
|
58
|
-
oauth2 = JSON.parse(oauth2Information);
|
|
59
|
-
if (!configuration.authorizations) {
|
|
60
|
-
configuration.authorizations = [];
|
|
61
|
-
}
|
|
62
|
-
configuration.authorizations.push({
|
|
63
|
-
name: 'development',
|
|
64
|
-
method: configurationTypes_1.Method.OAUTH2,
|
|
65
|
-
development: true,
|
|
66
|
-
oauth2,
|
|
67
|
-
});
|
|
68
|
-
core_1.ux.action.start('Saving configuration');
|
|
69
|
-
await (0, configuration_1.writeConfiguration)(configuration);
|
|
70
|
-
core_1.ux.action.stop();
|
|
59
|
+
oauth2 = configuration.authorizations?.find(authorization => authorization.method === configurationTypes_1.Method.OAUTH2)?.oauth2;
|
|
71
60
|
}
|
|
72
61
|
if (!oauth2) {
|
|
73
|
-
throw new
|
|
62
|
+
throw new errors_1.MissingAuth2AuthorizationError();
|
|
74
63
|
}
|
|
75
|
-
|
|
64
|
+
// Decrypt any encrypted oauth2 fields (mainly clientSecret)
|
|
65
|
+
oauth2 = (await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, oauth2)).entries;
|
|
66
|
+
const account = testAccount === 'development' ? configuration.testAccounts?.development : configuration.testAccounts?.compliance;
|
|
76
67
|
let credentials;
|
|
77
|
-
if (Object.
|
|
78
|
-
core_1.ux.action.start(`Starting Oauth2 flow for account: ${
|
|
68
|
+
if (!account || Object.entries(account).length === 0 || flags.reauth) {
|
|
69
|
+
core_1.ux.action.start(`Starting Oauth2 flow for account: ${testAccount}`);
|
|
79
70
|
credentials = await Oauth2Helper.performOAuth2Flow(oauth2);
|
|
80
71
|
core_1.ux.action.stop();
|
|
81
72
|
}
|
|
82
73
|
else {
|
|
83
74
|
if (!account?.refreshToken) {
|
|
84
|
-
core_1.ux.log('No refresh token found,
|
|
75
|
+
core_1.ux.log(chalk_1.default.redBright('No refresh token found, nothing to do.'));
|
|
76
|
+
return;
|
|
85
77
|
}
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
const decryptionResult = await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, account);
|
|
79
|
+
core_1.ux.action.start(`Refreshing test account ${testAccount}`);
|
|
80
|
+
credentials = await Oauth2Helper.updateToken({
|
|
81
|
+
...oauth2,
|
|
82
|
+
refreshToken: decryptionResult.entries?.refreshToken,
|
|
83
|
+
});
|
|
84
|
+
// If provider response doesn't contain a new refresh token, use the one we already have
|
|
88
85
|
if (!credentials.refreshToken) {
|
|
89
86
|
credentials.refreshToken = account?.refreshToken;
|
|
90
87
|
}
|
|
88
|
+
if (decryptionResult.decryptedKeys.includes('accessToken')) {
|
|
89
|
+
credentials.accessToken = (await IntegrationsPlatform.encryptData(configuration.name, credentials.accessToken)).encryptedData;
|
|
90
|
+
}
|
|
91
|
+
if (decryptionResult.decryptedKeys.includes('refreshToken')) {
|
|
92
|
+
credentials.refreshToken = (await IntegrationsPlatform.encryptData(configuration.name, credentials.refreshToken)).encryptedData;
|
|
93
|
+
}
|
|
91
94
|
core_1.ux.action.stop();
|
|
92
95
|
}
|
|
93
|
-
core_1.ux.action.start(`Saving credentials for account: ${
|
|
94
|
-
await (0, configuration_1.writeTestAccount)(configuration, credentials,
|
|
96
|
+
core_1.ux.action.start(`Saving credentials for account: ${testAccount}`);
|
|
97
|
+
await (0, configuration_1.writeTestAccount)(configuration, credentials, testAccount);
|
|
95
98
|
core_1.ux.action.stop();
|
|
96
99
|
return;
|
|
97
100
|
}
|
|
@@ -144,8 +144,19 @@ class Publish extends baseCommand_1.BaseCommand {
|
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
146
|
async updateRegistry(integrationConfiguration) {
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
let existing;
|
|
148
|
+
try {
|
|
149
|
+
existing = await IntegrationsPlatform.getIntegrationByName(integrationConfiguration.name);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error instanceof IntegrationsPlatform.HttpError && error.status === 403) {
|
|
153
|
+
core_1.ux.log(chalk_1.default.redBright(`Access Denied! You do not have access to this integration.`));
|
|
154
|
+
this.exit(-1);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
existing = undefined;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
149
160
|
// Create or update the integration.
|
|
150
161
|
let updated;
|
|
151
162
|
for (const authorization of integrationConfiguration.authorizations ?? []) {
|
|
@@ -92,14 +92,20 @@ class Test extends baseCommand_1.BaseCommand {
|
|
|
92
92
|
let credentialPayload = flags['credential-payload'];
|
|
93
93
|
// Default to test account's credentials if none are specifically provided
|
|
94
94
|
if (credentialPayload === null || credentialPayload === undefined) {
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
let credentials = configuration.testAccounts?.[flags['test-account']];
|
|
96
|
+
if (credentials) {
|
|
97
|
+
({ entries: credentials } = await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, credentials));
|
|
98
|
+
}
|
|
99
|
+
credentialPayload = JSON.stringify(credentials);
|
|
97
100
|
}
|
|
98
101
|
if (!credentialPayload || credentialPayload === '{}') {
|
|
99
102
|
throw new errors_1.MissingCredentialsError();
|
|
100
103
|
}
|
|
104
|
+
let secrets = {};
|
|
101
105
|
// Decrypt secrets, if necessary.
|
|
102
|
-
|
|
106
|
+
if (configuration.secrets) {
|
|
107
|
+
secrets = await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, configuration.secrets);
|
|
108
|
+
}
|
|
103
109
|
// Launch the tests.
|
|
104
110
|
const commandArguments = [
|
|
105
111
|
`${process.env.NODE_MODULES_FOLDER}/@unito/integration-debugger/dist/src/index.js`,
|
|
@@ -6,7 +6,6 @@ const child_process_1 = tslib_1.__importDefault(require("child_process"));
|
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const baseCommand_1 = require("../baseCommand");
|
|
8
8
|
const errors_1 = require("../errors");
|
|
9
|
-
const errors_2 = require("../errors");
|
|
10
9
|
class Upgrade extends baseCommand_1.BaseCommand {
|
|
11
10
|
static description = 'Upgrade the CLI';
|
|
12
11
|
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
@@ -18,17 +17,6 @@ class Upgrade extends baseCommand_1.BaseCommand {
|
|
|
18
17
|
throw error;
|
|
19
18
|
}
|
|
20
19
|
async run() {
|
|
21
|
-
//
|
|
22
|
-
// Check for the presence of UNITO_GITHUB_PKG_TOKEN.
|
|
23
|
-
//
|
|
24
|
-
// Necessary until we deploy to a public NPM repository.
|
|
25
|
-
//
|
|
26
|
-
core_1.ux.action.start('Checking for the presence of UNITO_GITHUB_PKG_TOKEN');
|
|
27
|
-
// istanbul ignore next
|
|
28
|
-
if (!process.env.UNITO_GITHUB_PKG_TOKEN) {
|
|
29
|
-
throw new errors_2.MissingEnvironmentVariableError('UNITO_GITHUB_PKG_TOKEN');
|
|
30
|
-
}
|
|
31
|
-
core_1.ux.action.stop('found');
|
|
32
20
|
//
|
|
33
21
|
// Global command options
|
|
34
22
|
//
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -5,8 +5,6 @@ export declare class NoConfigurationFileError extends Error {
|
|
|
5
5
|
}
|
|
6
6
|
export declare class ConfigurationMalformed extends Error {
|
|
7
7
|
}
|
|
8
|
-
export declare class MissingEnvironmentVariableError extends Error {
|
|
9
|
-
}
|
|
10
8
|
export declare class NoRefreshTokenError extends Error {
|
|
11
9
|
}
|
|
12
10
|
export declare class FailedToRetrieveAccessTokenError extends Error {
|
|
@@ -15,6 +13,8 @@ export declare class InvalidRequestContentTypeError extends Error {
|
|
|
15
13
|
}
|
|
16
14
|
export declare class MissingCredentialsError extends Error {
|
|
17
15
|
}
|
|
16
|
+
export declare class MissingAuth2AuthorizationError extends Error {
|
|
17
|
+
}
|
|
18
18
|
export declare class FileSizeExceeded extends Error {
|
|
19
19
|
}
|
|
20
20
|
export declare class MissingApiKey extends Error {
|
package/dist/src/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleError = exports.ConfigurationInvalid = exports.EntryDecryptionError = exports.DecryptionAuthenticationError = exports.AuthenticationFailed = exports.MissingApiKey = exports.FileSizeExceeded = exports.
|
|
3
|
+
exports.handleError = exports.ConfigurationInvalid = exports.EntryDecryptionError = exports.DecryptionAuthenticationError = exports.AuthenticationFailed = exports.MissingApiKey = exports.FileSizeExceeded = exports.MissingAuth2AuthorizationError = exports.MissingCredentialsError = exports.InvalidRequestContentTypeError = exports.FailedToRetrieveAccessTokenError = exports.NoRefreshTokenError = exports.ConfigurationMalformed = exports.NoConfigurationFileError = exports.NoIntegrationFoundError = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
@@ -17,9 +17,6 @@ exports.NoConfigurationFileError = NoConfigurationFileError;
|
|
|
17
17
|
class ConfigurationMalformed extends Error {
|
|
18
18
|
}
|
|
19
19
|
exports.ConfigurationMalformed = ConfigurationMalformed;
|
|
20
|
-
class MissingEnvironmentVariableError extends Error {
|
|
21
|
-
}
|
|
22
|
-
exports.MissingEnvironmentVariableError = MissingEnvironmentVariableError;
|
|
23
20
|
class NoRefreshTokenError extends Error {
|
|
24
21
|
}
|
|
25
22
|
exports.NoRefreshTokenError = NoRefreshTokenError;
|
|
@@ -32,6 +29,9 @@ exports.InvalidRequestContentTypeError = InvalidRequestContentTypeError;
|
|
|
32
29
|
class MissingCredentialsError extends Error {
|
|
33
30
|
}
|
|
34
31
|
exports.MissingCredentialsError = MissingCredentialsError;
|
|
32
|
+
class MissingAuth2AuthorizationError extends Error {
|
|
33
|
+
}
|
|
34
|
+
exports.MissingAuth2AuthorizationError = MissingAuth2AuthorizationError;
|
|
35
35
|
class FileSizeExceeded extends Error {
|
|
36
36
|
}
|
|
37
37
|
exports.FileSizeExceeded = FileSizeExceeded;
|
|
@@ -87,11 +87,6 @@ function handleError(command, error) {
|
|
|
87
87
|
command.logToStderr(`This file should be located at ${chalk_1.default.yellowBright(path_1.default.relative(process.cwd(), (0, configuration_1.getConfigurationPath)()))}.`);
|
|
88
88
|
handled = true;
|
|
89
89
|
}
|
|
90
|
-
else if (error instanceof MissingEnvironmentVariableError) {
|
|
91
|
-
command.logToStderr(chalk_1.default.redBright('This command requires a variable which is missing from your environment :('));
|
|
92
|
-
command.logToStderr(`Make sure the environment variable ${chalk_1.default.yellowBright(error.message)} is defined.`);
|
|
93
|
-
handled = true;
|
|
94
|
-
}
|
|
95
90
|
else if (error instanceof ConfigurationMalformed) {
|
|
96
91
|
command.logToStderr(chalk_1.default.redBright(`Your ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} was found but its not a valid JSON file!`));
|
|
97
92
|
handled = true;
|
|
@@ -154,6 +149,13 @@ function handleError(command, error) {
|
|
|
154
149
|
command.logToStderr(`Make sure they were encrypted by the same environement (Currently targeting: ${error.environment}).`);
|
|
155
150
|
handled = true;
|
|
156
151
|
}
|
|
152
|
+
else if (error instanceof MissingAuth2AuthorizationError) {
|
|
153
|
+
command.logToStderr();
|
|
154
|
+
command.logToStderr(chalk_1.default.redBright(`No Oauth2 authorization found in your configuration file`));
|
|
155
|
+
// TODO: Update link once the documentation is made available publicly
|
|
156
|
+
command.logToStderr('See https://staging-dev.unito.io/docs/integrations/configuration/authorizations#oauth-2 for more information on how to configure Oauth2');
|
|
157
|
+
handled = true;
|
|
158
|
+
}
|
|
157
159
|
return handled;
|
|
158
160
|
}
|
|
159
161
|
exports.handleError = handleError;
|
|
@@ -23,7 +23,7 @@ export declare function getConfiguration(environment: Environment, customConfigP
|
|
|
23
23
|
/**
|
|
24
24
|
* Write the configuration to the default configuration file.
|
|
25
25
|
*/
|
|
26
|
-
export declare function writeConfiguration(configuration: Configuration): Promise<void>;
|
|
26
|
+
export declare function writeConfiguration(configuration: Configuration, environment?: Environment, customConfigPath?: string): Promise<void>;
|
|
27
27
|
export declare function writeTestAccount(configuration: Configuration, account: {
|
|
28
28
|
accessToken: string;
|
|
29
29
|
refreshToken?: string;
|
|
@@ -88,10 +88,13 @@ exports.getConfiguration = getConfiguration;
|
|
|
88
88
|
/**
|
|
89
89
|
* Write the configuration to the default configuration file.
|
|
90
90
|
*/
|
|
91
|
-
async function writeConfiguration(configuration) {
|
|
91
|
+
async function writeConfiguration(configuration, environment = globalConfiguration_1.Environment.Production, customConfigPath) {
|
|
92
92
|
(0, integrations_1.validateIsIntegrationDirectory)();
|
|
93
93
|
await validateConfiguration(configuration);
|
|
94
|
-
|
|
94
|
+
const configurationPath = customConfigPath
|
|
95
|
+
? `${process.cwd()}${customConfigPath.startsWith('/') ? customConfigPath : `/${customConfigPath}`}`
|
|
96
|
+
: getConfigurationPath(environment);
|
|
97
|
+
await fs.promises.writeFile(configurationPath, JSON.stringify(configuration, null, 2));
|
|
95
98
|
}
|
|
96
99
|
exports.writeConfiguration = writeConfiguration;
|
|
97
100
|
async function writeTestAccount(configuration, account, accountName) {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import { Configuration } from '../configurationTypes';
|
|
2
1
|
import * as GlobalConfiguration from './globalConfiguration';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Object returned when decrypting
|
|
4
|
+
*
|
|
5
|
+
* Allows the caller to know which keys were decrypted to reencrypt them later as needed
|
|
6
|
+
*/
|
|
7
|
+
export type DecryptionResult = {
|
|
8
|
+
decryptedKeys: string[];
|
|
9
|
+
entries: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
export declare function decryptEntries(configurationName: string, environment: GlobalConfiguration.Environment, configDir: string, entries: Record<string, unknown>, fieldName?: string): Promise<DecryptionResult>;
|
|
@@ -1,62 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.decryptEntries = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const errors_1 = require("../errors");
|
|
6
6
|
const GlobalConfiguration = tslib_1.__importStar(require("./globalConfiguration"));
|
|
7
7
|
const integrationsPlatform_1 = require("./integrationsPlatform");
|
|
8
8
|
const configuration_1 = require("./configuration");
|
|
9
9
|
const integrationsPlatform_2 = require("../services/integrationsPlatform");
|
|
10
|
-
async function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return {};
|
|
14
|
-
}
|
|
15
|
-
// Get encrypted credential entries
|
|
16
|
-
const encryptedEntries = Object.entries(credentials).filter((entry) => typeof entry[1] === 'string' && entry[1].startsWith(configuration_1.ENCRYPTION_PREFIX));
|
|
10
|
+
async function decryptEntries(configurationName, environment, configDir, entries, fieldName = 'entries') {
|
|
11
|
+
// Get encrypted entries
|
|
12
|
+
const encryptedEntries = Object.entries(entries).filter((entry) => typeof entry[1] === 'string' && entry[1].startsWith(configuration_1.ENCRYPTION_PREFIX));
|
|
17
13
|
if (!encryptedEntries.length) {
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
// Copy credentials to avoid mutating the configuration.
|
|
21
|
-
const decryptedCredentials = structuredClone(credentials);
|
|
22
|
-
const globalConfiguration = await GlobalConfiguration.read(configDir);
|
|
23
|
-
try {
|
|
24
|
-
await (0, integrationsPlatform_1.validateAuthenticated)(globalConfiguration, environment);
|
|
25
|
-
}
|
|
26
|
-
catch (err) {
|
|
27
|
-
throw new errors_1.DecryptionAuthenticationError('credentials');
|
|
28
|
-
}
|
|
29
|
-
for (const [key, encryptedCredential] of encryptedEntries) {
|
|
30
|
-
try {
|
|
31
|
-
decryptedCredentials[key] = (await (0, integrationsPlatform_2.decryptData)(configuration.name, encryptedCredential)).decryptedData;
|
|
32
|
-
}
|
|
33
|
-
catch (err) {
|
|
34
|
-
throw new errors_1.EntryDecryptionError(key, encryptedCredential, environment);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return decryptedCredentials;
|
|
38
|
-
}
|
|
39
|
-
exports.decryptTestAccountCredentials = decryptTestAccountCredentials;
|
|
40
|
-
async function decryptSecrets(configuration, environment, configDir) {
|
|
41
|
-
if (!Object.entries(configuration.secrets ?? {}).length) {
|
|
42
|
-
return {};
|
|
14
|
+
return { decryptedKeys: [], entries };
|
|
43
15
|
}
|
|
44
16
|
const globalConfiguration = await GlobalConfiguration.read(configDir);
|
|
45
17
|
try {
|
|
46
18
|
await (0, integrationsPlatform_1.validateAuthenticated)(globalConfiguration, environment);
|
|
47
19
|
}
|
|
48
20
|
catch (err) {
|
|
49
|
-
throw new errors_1.DecryptionAuthenticationError(
|
|
21
|
+
throw new errors_1.DecryptionAuthenticationError(fieldName);
|
|
50
22
|
}
|
|
51
|
-
|
|
52
|
-
|
|
23
|
+
// Copy credentials to avoid mutating the configuration.
|
|
24
|
+
const decryptedEntries = structuredClone(entries);
|
|
25
|
+
for (const [key, encryptedEntry] of encryptedEntries) {
|
|
53
26
|
try {
|
|
54
|
-
|
|
27
|
+
decryptedEntries[key] = (await (0, integrationsPlatform_2.decryptData)(configurationName, encryptedEntry)).decryptedData;
|
|
55
28
|
}
|
|
56
29
|
catch (err) {
|
|
57
|
-
throw new errors_1.EntryDecryptionError(key,
|
|
30
|
+
throw new errors_1.EntryDecryptionError(key, encryptedEntry, environment);
|
|
58
31
|
}
|
|
59
32
|
}
|
|
60
|
-
return
|
|
33
|
+
return { decryptedKeys: encryptedEntries.map(([key]) => key), entries: decryptedEntries };
|
|
61
34
|
}
|
|
62
|
-
exports.
|
|
35
|
+
exports.decryptEntries = decryptEntries;
|
|
@@ -27,7 +27,7 @@ export declare function reencryptData(integrationName: string, encryptedData: st
|
|
|
27
27
|
encryptedData: string;
|
|
28
28
|
}>;
|
|
29
29
|
export declare function getIntegration(integrationId: number): Promise<Integration>;
|
|
30
|
-
export declare function getIntegrationByName(integrationName: string): Promise<Integration
|
|
30
|
+
export declare function getIntegrationByName(integrationName: string): Promise<Integration>;
|
|
31
31
|
export declare function getIntegrations(): Promise<IntegrationSummary[]>;
|
|
32
32
|
export declare function publishIntegration(archivePath: string): Promise<Integration>;
|
|
33
33
|
export declare function createIntegration(configuration: Configuration): Promise<Integration>;
|