@unito/integration-cli 0.55.5 → 0.56.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/integrationGenerator/integrationBoilerplate/.nvmrc +1 -1
  2. package/dist/integrationGenerator/integrationBoilerplate/Dockerfile +2 -2
  3. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.nvmrc +1 -1
  4. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/Dockerfile +2 -2
  5. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/package.json +2 -2
  6. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts +1 -1
  7. package/dist/integrationGenerator/integrationBoilerplate/package.json +2 -2
  8. package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts +1 -1
  9. package/dist/src/commands/activity.js +14 -5
  10. package/dist/src/commands/dev.js +10 -4
  11. package/dist/src/commands/encrypt.js +1 -1
  12. package/dist/src/commands/init.js +1 -1
  13. package/dist/src/commands/invite.js +14 -5
  14. package/dist/src/commands/login.js +1 -1
  15. package/dist/src/commands/oauth2.d.ts +6 -1
  16. package/dist/src/commands/oauth2.js +59 -56
  17. package/dist/src/commands/publish.js +14 -3
  18. package/dist/src/commands/test.js +10 -4
  19. package/dist/src/commands/upgrade.js +1 -1
  20. package/dist/src/errors.d.ts +4 -1
  21. package/dist/src/errors.js +47 -37
  22. package/dist/src/resources/configuration.d.ts +1 -1
  23. package/dist/src/resources/configuration.js +5 -2
  24. package/dist/src/resources/decryption.d.ts +10 -4
  25. package/dist/src/resources/decryption.js +13 -40
  26. package/dist/src/services/integrationsPlatform.d.ts +1 -1
  27. package/dist/src/services/integrationsPlatform.js +1 -8
  28. package/dist/test/commands/activity.test.js +3 -1
  29. package/dist/test/commands/encrypt.test.js +2 -2
  30. package/dist/test/commands/invite.test.js +3 -1
  31. package/dist/test/commands/oauth2.test.js +155 -11
  32. package/dist/test/commands/publish.test.js +25 -25
  33. package/dist/test/errors.test.js +45 -40
  34. package/dist/test/resources/decryption.test.js +28 -19
  35. package/dist/test/services/integrationsPlatform.test.js +0 -4
  36. package/oclif.manifest.json +36 -5
  37. package/package.json +3 -3
@@ -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.MissingCredentialsError = exports.InvalidRequestContentTypeError = exports.FailedToRetrieveAccessTokenError = exports.NoRefreshTokenError = exports.MissingEnvironmentVariableError = exports.ConfigurationMalformed = exports.NoConfigurationFileError = exports.NoIntegrationFoundError = void 0;
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.MissingEnvironmentVariableError = 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"));
@@ -32,6 +32,9 @@ exports.InvalidRequestContentTypeError = InvalidRequestContentTypeError;
32
32
  class MissingCredentialsError extends Error {
33
33
  }
34
34
  exports.MissingCredentialsError = MissingCredentialsError;
35
+ class MissingAuth2AuthorizationError extends Error {
36
+ }
37
+ exports.MissingAuth2AuthorizationError = MissingAuth2AuthorizationError;
35
38
  class FileSizeExceeded extends Error {
36
39
  }
37
40
  exports.FileSizeExceeded = FileSizeExceeded;
@@ -71,87 +74,94 @@ class ConfigurationInvalid extends Error {
71
74
  }
72
75
  }
73
76
  exports.ConfigurationInvalid = ConfigurationInvalid;
74
- function handleError(error) {
77
+ function handleError(command, error) {
75
78
  /* istanbul ignore if */
76
79
  if (core_1.ux.action.running) {
77
80
  core_1.ux.action.stop(chalk_1.default.redBright('failed'));
78
81
  }
79
82
  let handled = false;
80
83
  if (error instanceof NoIntegrationFoundError) {
81
- core_1.ux.log(chalk_1.default.redBright('Your directory does not seem to contain an integration :('));
82
- core_1.ux.log(`Make sure you are in the right directory and that you have a ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} file.`);
84
+ command.logToStderr(chalk_1.default.redBright('Your directory does not seem to contain an integration :('));
85
+ command.logToStderr(`Make sure you are in the right directory and that you have a ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} file.`);
83
86
  handled = true;
84
87
  }
85
88
  else if (error instanceof NoConfigurationFileError) {
86
- core_1.ux.log(chalk_1.default.redBright('This command requires a configuration file for your integration :('));
87
- core_1.ux.log(`This file should be located at ${chalk_1.default.yellowBright(path_1.default.relative(process.cwd(), (0, configuration_1.getConfigurationPath)()))}.`);
89
+ command.logToStderr(chalk_1.default.redBright('This command requires a configuration file for your integration :('));
90
+ command.logToStderr(`This file should be located at ${chalk_1.default.yellowBright(path_1.default.relative(process.cwd(), (0, configuration_1.getConfigurationPath)()))}.`);
88
91
  handled = true;
89
92
  }
90
93
  else if (error instanceof MissingEnvironmentVariableError) {
91
- core_1.ux.log(chalk_1.default.redBright('This command requires a variable which is missing from your environment :('));
92
- core_1.ux.log(`Make sure the environment variable ${chalk_1.default.yellowBright(error.message)} is defined.`);
94
+ command.logToStderr(chalk_1.default.redBright('This command requires a variable which is missing from your environment :('));
95
+ command.logToStderr(`Make sure the environment variable ${chalk_1.default.yellowBright(error.message)} is defined.`);
93
96
  handled = true;
94
97
  }
95
98
  else if (error instanceof ConfigurationMalformed) {
96
- core_1.ux.log(chalk_1.default.redBright(`Your ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} was found but its not a valid JSON file!`));
99
+ 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
100
  handled = true;
98
101
  }
99
102
  else if (error instanceof ConfigurationInvalid) {
100
- core_1.ux.log(chalk_1.default.redBright(`Your ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} is invalid!`));
101
- core_1.ux.log();
102
- core_1.ux.log(error.prettyDetails);
103
+ command.logToStderr(chalk_1.default.redBright(`Your ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} is invalid!`));
104
+ command.logToStderr();
105
+ command.logToStderr(error.prettyDetails);
103
106
  handled = true;
104
107
  }
105
108
  else if (error instanceof NoRefreshTokenError) {
106
- core_1.ux.log(chalk_1.default.redBright('No refresh token found in your configuration file'));
109
+ command.logToStderr(chalk_1.default.redBright('No refresh token found in your configuration file'));
107
110
  handled = true;
108
111
  }
109
112
  else if (error instanceof FailedToRetrieveAccessTokenError) {
110
- core_1.ux.log(chalk_1.default.redBright('Failed to retrieve access token'));
111
- core_1.ux.log();
112
- core_1.ux.log(error.message);
113
+ command.logToStderr(chalk_1.default.redBright('Failed to retrieve access token'));
114
+ command.logToStderr();
115
+ command.logToStderr(error.message);
113
116
  handled = true;
114
117
  }
115
118
  else if (error instanceof InvalidRequestContentTypeError) {
116
- core_1.ux.log(chalk_1.default.redBright('Invalid request content type'));
119
+ command.logToStderr(chalk_1.default.redBright('Invalid request content type'));
117
120
  handled = true;
118
- core_1.ux.log();
119
- core_1.ux.log(error.message);
121
+ command.logToStderr();
122
+ command.logToStderr(error.message);
120
123
  }
121
124
  else if (error instanceof integrationsPlatform_1.HttpError) {
122
125
  handled = true;
123
- core_1.ux.log();
124
- core_1.ux.log((0, json_colorizer_1.default)(JSON.stringify(error.data, null, 2)));
126
+ command.logToStderr();
127
+ command.logToStderr((0, json_colorizer_1.default)(JSON.stringify(error.data, null, 2)));
125
128
  }
126
129
  else if (error instanceof MissingCredentialsError) {
127
- core_1.ux.log();
128
- core_1.ux.log(chalk_1.default.redBright('The credentials are missing from your configuration file'));
130
+ command.logToStderr();
131
+ command.logToStderr(chalk_1.default.redBright('The credentials are missing from your configuration file'));
129
132
  handled = true;
130
133
  }
131
134
  else if (error instanceof MissingApiKey) {
132
- core_1.ux.log();
133
- core_1.ux.log(chalk_1.default.redBright('Your API key is not set!'));
134
- core_1.ux.log(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first`);
135
+ command.logToStderr();
136
+ command.logToStderr(chalk_1.default.redBright('Your API key is not set!'));
137
+ command.logToStderr(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first`);
135
138
  handled = true;
136
139
  }
137
140
  else if (error instanceof AuthenticationFailed) {
138
- core_1.ux.log();
139
- core_1.ux.log(chalk_1.default.redBright('This command requires that you are logged to Unito!'));
140
- core_1.ux.log(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first`);
141
+ command.logToStderr();
142
+ command.logToStderr(chalk_1.default.redBright('This command requires that you are logged to Unito!'));
143
+ command.logToStderr(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first`);
141
144
  handled = true;
142
145
  }
143
146
  else if (error instanceof DecryptionAuthenticationError) {
144
- core_1.ux.log();
145
- core_1.ux.log(chalk_1.default.yellowBright(`Your configuration contains encrypted ${error.encryptedEntityName}.`));
146
- core_1.ux.log('To use them locally, you must be authenticated to Unito.');
147
+ command.logToStderr();
148
+ command.logToStderr(chalk_1.default.yellowBright(`Your configuration contains encrypted ${error.encryptedEntityName}.`));
149
+ command.logToStderr('To use them locally, you must be authenticated to Unito.');
147
150
  handled = true;
148
151
  }
149
152
  else if (error instanceof EntryDecryptionError) {
150
- core_1.ux.log();
151
- core_1.ux.log(chalk_1.default.yellowBright(`Error decrypting entry:`));
152
- core_1.ux.log(chalk_1.default.redBright(`${error.key}: ${error.value}`));
153
- core_1.ux.log();
154
- core_1.ux.log(`Make sure they were encrypted by the same environement (Currently targeting: ${error.environment}).`);
153
+ command.logToStderr();
154
+ command.logToStderr(chalk_1.default.yellowBright(`Error decrypting entry:`));
155
+ command.logToStderr(chalk_1.default.redBright(`${error.key}: ${error.value}`));
156
+ command.logToStderr();
157
+ command.logToStderr(`Make sure they were encrypted by the same environement (Currently targeting: ${error.environment}).`);
158
+ handled = true;
159
+ }
160
+ else if (error instanceof MissingAuth2AuthorizationError) {
161
+ command.logToStderr();
162
+ command.logToStderr(chalk_1.default.redBright(`No Oauth2 authorization found in your configuration file`));
163
+ // TODO: Update link once the documentation is made available publicly
164
+ command.logToStderr('See https://staging-dev.unito.io/docs/integrations/configuration/authorizations#oauth-2 for more information on how to configure Oauth2');
155
165
  handled = true;
156
166
  }
157
167
  return handled;
@@ -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
- await fs.promises.writeFile(getConfigurationPath(globalConfiguration_1.Environment.Production), JSON.stringify(configuration, null, 2));
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
- import { CredentialScope } from './configuration';
4
- export declare function decryptTestAccountCredentials(configuration: Configuration, environment: GlobalConfiguration.Environment, testAccount: CredentialScope, configDir: string): Promise<Record<string, unknown>>;
5
- export declare function decryptSecrets(configuration: Configuration, environment: GlobalConfiguration.Environment, configDir: string): Promise<Record<string, unknown>>;
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.decryptSecrets = exports.decryptTestAccountCredentials = void 0;
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 decryptTestAccountCredentials(configuration, environment, testAccount, configDir) {
11
- const credentials = configuration.testAccounts?.[testAccount];
12
- if (!credentials) {
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 credentials;
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('secrets');
21
+ throw new errors_1.DecryptionAuthenticationError(fieldName);
50
22
  }
51
- const decryptedSecrets = {};
52
- for (const [key, encryptedSecret] of Object.entries(configuration.secrets ?? {})) {
23
+ // Copy credentials to avoid mutating the configuration.
24
+ const decryptedEntries = structuredClone(entries);
25
+ for (const [key, encryptedEntry] of encryptedEntries) {
53
26
  try {
54
- decryptedSecrets[key] = (await (0, integrationsPlatform_2.decryptData)(configuration.name, encryptedSecret)).decryptedData;
27
+ decryptedEntries[key] = (await (0, integrationsPlatform_2.decryptData)(configurationName, encryptedEntry)).decryptedData;
55
28
  }
56
29
  catch (err) {
57
- throw new errors_1.EntryDecryptionError(key, encryptedSecret, environment);
30
+ throw new errors_1.EntryDecryptionError(key, encryptedEntry, environment);
58
31
  }
59
32
  }
60
- return decryptedSecrets;
33
+ return { decryptedKeys: encryptedEntries.map(([key]) => key), entries: decryptedEntries };
61
34
  }
62
- exports.decryptSecrets = decryptSecrets;
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 | null>;
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>;
@@ -62,14 +62,7 @@ async function getIntegration(integrationId) {
62
62
  }
63
63
  exports.getIntegration = getIntegration;
64
64
  async function getIntegrationByName(integrationName) {
65
- let integration;
66
- try {
67
- integration = await integrations_platform_client_1.default.getIntegrationByName(integrationName);
68
- }
69
- catch {
70
- return null;
71
- }
72
- return integration;
65
+ return integrations_platform_client_1.default.getIntegrationByName(integrationName);
73
66
  }
74
67
  exports.getIntegrationByName = getIntegrationByName;
75
68
  async function getIntegrations() {
@@ -53,7 +53,9 @@ describe('activity', () => {
53
53
  });
54
54
  test_1.test
55
55
  .stdout()
56
- .stub(IntegrationsPlatform, 'getIntegrationByName', () => undefined)
56
+ .stub(IntegrationsPlatform, 'getIntegrationByName', () => {
57
+ throw new Error();
58
+ })
57
59
  .command(['activity'])
58
60
  .catch(error => {
59
61
  (0, test_1.expect)(error.message).to.equal('EEXIT: -1');
@@ -53,12 +53,12 @@ describe('encrypt', () => {
53
53
  (0, test_1.expect)(ctx.stdout).to.contains('Encrypted Data:');
54
54
  });
55
55
  test_1.test
56
- .stdout()
56
+ .stderr()
57
57
  .stub(GlobalConfiguration, 'read', () => ({}))
58
58
  .command(['encrypt'])
59
59
  .exit(-1)
60
60
  .it('missing api key', ctx => {
61
- (0, test_1.expect)(ctx.stdout).to.contain('Your API key is not set!\nMake sure to run the login command first');
61
+ (0, test_1.expect)(ctx.stderr).to.contain('Your API key is not set!\nMake sure to run the login command first');
62
62
  });
63
63
  test_1.test
64
64
  .stdout()
@@ -47,7 +47,9 @@ describe('invite', () => {
47
47
  test_1.test
48
48
  .stdout()
49
49
  .stub(GlobalConfiguration, 'read', () => ({ email: 'foo@bar.com' }))
50
- .stub(IntegrationsPlatform, 'getIntegrationByName', () => undefined)
50
+ .stub(IntegrationsPlatform, 'getIntegrationByName', () => {
51
+ throw new Error();
52
+ })
51
53
  .command(['invite'])
52
54
  .catch(error => {
53
55
  (0, test_1.expect)(error.message).to.equal('EEXIT: -1');
@@ -7,12 +7,13 @@ const sinon = tslib_1.__importStar(require("sinon"));
7
7
  const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
8
8
  const Configuration = tslib_1.__importStar(require("../../src/resources/configuration"));
9
9
  const oauth2Service = tslib_1.__importStar(require("../../src/services/oauth2Helper"));
10
+ const IntegrationsPlatform = tslib_1.__importStar(require("../../src/services/integrationsPlatform"));
11
+ const decryptionResource = tslib_1.__importStar(require("../../src/resources/decryption"));
10
12
  const configurationTypes_1 = require("../../src/configurationTypes");
11
13
  describe('oauth2', () => {
12
14
  const INTEGRATION_NAME = 'myintegration';
13
15
  const sandbox = sinon.createSandbox();
14
16
  let getConfigurationsStub;
15
- let writeConfigurationStub;
16
17
  let writeTestAccountStub;
17
18
  let performOAuth2FlowStub;
18
19
  let updateTokenStub;
@@ -30,7 +31,7 @@ describe('oauth2', () => {
30
31
  name: INTEGRATION_NAME,
31
32
  authorizations: [
32
33
  {
33
- name: 'development',
34
+ name: 'MyAuthorization',
34
35
  method: configurationTypes_1.Method.OAUTH2,
35
36
  oauth2: oauth2Information,
36
37
  },
@@ -48,7 +49,6 @@ describe('oauth2', () => {
48
49
  sandbox.stub(inquirer_1.default, 'prompt').resolves({
49
50
  oauth2Information: JSON.stringify(oauth2Information),
50
51
  });
51
- writeConfigurationStub = sandbox.stub(Configuration, 'writeConfiguration');
52
52
  writeTestAccountStub = sandbox.stub(Configuration, 'writeTestAccount');
53
53
  performOAuth2FlowStub = sandbox.stub(oauth2Service, 'performOAuth2Flow');
54
54
  performOAuth2FlowStub.resolves(credentials);
@@ -63,16 +63,48 @@ describe('oauth2', () => {
63
63
  ...baseConfiguration,
64
64
  authorizations: [],
65
65
  }))
66
- .command(['oauth2', '--accountName', 'development'])
67
- .it("asks for authentication information when it's not setup in the configuration file", () => {
68
- (0, test_1.expect)(writeConfigurationStub.getCall(0)?.firstArg).to.deep.equal({
69
- ...baseConfiguration,
70
- authorizations: [{ oauth2: oauth2Information, name: 'development', method: 'oauth2', development: true }],
71
- });
66
+ .command(['oauth2', '--test-account', 'development'])
67
+ .exit(-1)
68
+ .it("Errors out if no oauth2 authorization scheme is found in the integration's configuration");
69
+ test_1.test
70
+ .stdout()
71
+ .do(() => getConfigurationsStub.returns({
72
+ ...baseConfiguration,
73
+ authorizations: [
74
+ ...(baseConfiguration.authorizations ?? []),
75
+ {
76
+ name: 'Development Authorization',
77
+ method: configurationTypes_1.Method.OAUTH2,
78
+ oauth2: { ...oauth2Information, clientId: 'devClientID' },
79
+ development: true,
80
+ },
81
+ ],
82
+ }))
83
+ .command(['oauth2', '--test-account', 'development'])
84
+ .it('prioritize development authorization', () => {
85
+ (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(1);
86
+ (0, test_1.expect)(performOAuth2FlowStub.getCall(0).args).to.deep.equal([{ ...oauth2Information, clientId: 'devClientID' }]);
87
+ (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(0);
88
+ (0, test_1.expect)(writeTestAccountStub.getCall(0).args).to.deep.equal([
89
+ {
90
+ ...baseConfiguration,
91
+ authorizations: [
92
+ ...(baseConfiguration.authorizations ?? []),
93
+ {
94
+ name: 'Development Authorization',
95
+ method: configurationTypes_1.Method.OAUTH2,
96
+ oauth2: { ...oauth2Information, clientId: 'devClientID' },
97
+ development: true,
98
+ },
99
+ ],
100
+ },
101
+ credentials,
102
+ 'development',
103
+ ]);
72
104
  });
73
105
  test_1.test
74
106
  .stdout()
75
- .command(['oauth2', '--accountName', 'development'])
107
+ .command(['oauth2', '--test-account', 'development'])
76
108
  .it('performs the oauth flow when there is no test accounts and the auth information are setup', () => {
77
109
  (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(1);
78
110
  (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(0);
@@ -86,7 +118,53 @@ describe('oauth2', () => {
86
118
  development: credentials,
87
119
  },
88
120
  }))
89
- .command(['oauth2', '--accountName', 'development'])
121
+ .command(['oauth2', '--test-account', 'development', '--reauth'])
122
+ .it('performs the oauth flow when there is a test accounts, the auth information are setup and --reauth flag is present', () => {
123
+ (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(1);
124
+ (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(0);
125
+ (0, test_1.expect)(writeTestAccountStub.getCall(0).args).to.deep.equal([
126
+ {
127
+ ...baseConfiguration,
128
+ testAccounts: {
129
+ development: credentials,
130
+ },
131
+ },
132
+ credentials,
133
+ 'development',
134
+ ]);
135
+ });
136
+ test_1.test
137
+ .stdout()
138
+ .do(() => getConfigurationsStub.returns({
139
+ ...baseConfiguration,
140
+ testAccounts: {
141
+ development: { something: 'something' },
142
+ },
143
+ }))
144
+ .command(['oauth2', '--test-account', 'compliance'])
145
+ .it('performs the oauth flow when the requested test account is not setup', () => {
146
+ (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(1);
147
+ (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(0);
148
+ (0, test_1.expect)(writeTestAccountStub.getCall(0).args).to.deep.equal([
149
+ {
150
+ ...baseConfiguration,
151
+ testAccounts: {
152
+ development: { something: 'something' },
153
+ },
154
+ },
155
+ credentials,
156
+ 'compliance',
157
+ ]);
158
+ });
159
+ test_1.test
160
+ .stdout()
161
+ .do(() => getConfigurationsStub.returns({
162
+ ...baseConfiguration,
163
+ testAccounts: {
164
+ development: credentials,
165
+ },
166
+ }))
167
+ .command(['oauth2', '--test-account', 'development'])
90
168
  .it('refresh the token when there is an existing test accounts and the auth information are setup', () => {
91
169
  (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(0);
92
170
  (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(1);
@@ -101,4 +179,70 @@ describe('oauth2', () => {
101
179
  'development',
102
180
  ]);
103
181
  });
182
+ test_1.test
183
+ .stdout()
184
+ .do(() => {
185
+ getConfigurationsStub.returns({
186
+ ...baseConfiguration,
187
+ authorizations: [
188
+ {
189
+ name: 'Authorization',
190
+ method: configurationTypes_1.Method.OAUTH2,
191
+ oauth2: { ...oauth2Information, clientSecret: `${Configuration.ENCRYPTION_PREFIX}devClientID` },
192
+ },
193
+ ],
194
+ testAccounts: {
195
+ development: {
196
+ accessToken: `${Configuration.ENCRYPTION_PREFIX}devAccessToken`,
197
+ refreshToken: `${Configuration.ENCRYPTION_PREFIX}devRefreshToken`,
198
+ },
199
+ },
200
+ });
201
+ sandbox
202
+ .stub(decryptionResource, 'decryptEntries')
203
+ .onFirstCall()
204
+ .resolves({ decryptedKeys: ['clientSecret'], entries: { ...oauth2Information, clientSecret: 'devClientID' } })
205
+ .onSecondCall()
206
+ .resolves({
207
+ decryptedKeys: ['accessToken', 'refreshToken'],
208
+ entries: {
209
+ accessToken: 'devAccessToken',
210
+ refreshToken: 'devRefreshToken',
211
+ },
212
+ });
213
+ sandbox
214
+ .stub(IntegrationsPlatform, 'encryptData')
215
+ .onFirstCall()
216
+ .resolves({ encryptedData: `${Configuration.ENCRYPTION_PREFIX}encryptedAccessToken` })
217
+ .onSecondCall()
218
+ .resolves({ encryptedData: `${Configuration.ENCRYPTION_PREFIX}encryptedRefreshToken` });
219
+ })
220
+ .command(['oauth2', '--test-account', 'development'])
221
+ .it('decrypt oauth2 authorization entries and test-account', () => {
222
+ (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(0);
223
+ (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(1);
224
+ (0, test_1.expect)(writeTestAccountStub.getCall(0).args).to.deep.equal([
225
+ {
226
+ ...baseConfiguration,
227
+ authorizations: [
228
+ {
229
+ name: 'Authorization',
230
+ method: configurationTypes_1.Method.OAUTH2,
231
+ oauth2: { ...oauth2Information, clientSecret: `${Configuration.ENCRYPTION_PREFIX}devClientID` },
232
+ },
233
+ ],
234
+ testAccounts: {
235
+ development: {
236
+ accessToken: `${Configuration.ENCRYPTION_PREFIX}devAccessToken`,
237
+ refreshToken: `${Configuration.ENCRYPTION_PREFIX}devRefreshToken`,
238
+ },
239
+ },
240
+ },
241
+ {
242
+ accessToken: `${Configuration.ENCRYPTION_PREFIX}encryptedAccessToken`,
243
+ refreshToken: `${Configuration.ENCRYPTION_PREFIX}encryptedRefreshToken`,
244
+ },
245
+ 'development',
246
+ ]);
247
+ });
104
248
  });