@unito/integration-cli 0.63.3 → 0.64.3

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.
@@ -8,7 +8,7 @@ export default class Dev extends BaseCommand<typeof Dev> {
8
8
  environment: import("@oclif/core/lib/interfaces").OptionFlag<GlobalConfiguration.Environment, import("@oclif/core/lib/interfaces").CustomOptions>;
9
9
  verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
10
  'credential-payload': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
- 'credential-id': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'credential-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
12
  'test-account': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
13
13
  'read-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
14
  timeout: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -16,6 +16,7 @@ export default class Dev extends BaseCommand<typeof Dev> {
16
16
  checks: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
17
17
  'config-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
18
  'skip-install': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ port: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
19
20
  };
20
21
  run(): Promise<void>;
21
22
  }
@@ -35,7 +35,7 @@ class Dev extends baseCommand_1.BaseCommand {
35
35
  description: '(advanced) credential payload to use.',
36
36
  exclusive: ['credential-id'],
37
37
  }),
38
- 'credential-id': core_1.Flags.integer({
38
+ 'credential-id': core_1.Flags.string({
39
39
  description: '(advanced) credential to use.',
40
40
  exclusive: ['credential-payload'],
41
41
  }),
@@ -77,6 +77,10 @@ class Dev extends baseCommand_1.BaseCommand {
77
77
  allowNo: true,
78
78
  default: false,
79
79
  }),
80
+ port: core_1.Flags.integer({
81
+ description: 'port to run the integration on',
82
+ default: 9200,
83
+ }),
80
84
  };
81
85
  async run() {
82
86
  (0, integrations_1.validateIsIntegrationDirectory)();
@@ -141,7 +145,7 @@ class Dev extends baseCommand_1.BaseCommand {
141
145
  // Launch the debugger.
142
146
  const commandArguments = [
143
147
  `${process.env.NODE_MODULES_FOLDER}/@unito/integration-debugger/dist/src/index.js`,
144
- '--integration-url=http://localhost:9200',
148
+ `--integration-url=http://localhost:${flags.port}`,
145
149
  `--spawn-process=npm run dev`,
146
150
  `--credential-payload=${credentialPayload}`,
147
151
  `--secrets-payload=${JSON.stringify(secrets)}`,
@@ -185,7 +189,7 @@ class Dev extends baseCommand_1.BaseCommand {
185
189
  const child = child_process_1.default.spawn('node', commandArguments, {
186
190
  detached: true,
187
191
  stdio: 'inherit',
188
- env: { ...process.env, ...environmentVariables, NODE_ENV: 'development', PORT: '9200' },
192
+ env: { ...process.env, ...environmentVariables, NODE_ENV: 'development', PORT: `${flags.port}` },
189
193
  });
190
194
  // istanbul ignore next
191
195
  child.on('exit', (code) => {
@@ -26,15 +26,15 @@ class Init extends baseCommand_1.BaseCommand {
26
26
  const name = nameFromFlag ??
27
27
  (await inquirer_1.default.prompt([
28
28
  {
29
+ type: 'input',
29
30
  name: 'name',
30
- prefix: [
31
+ message: [
31
32
  chalk_1.default.gray('Choose a name for your integration.'),
32
33
  chalk_1.default.gray('A folder will be created with the value provided.'),
33
34
  chalk_1.default.gray('Note that "My Integration" will become "my_integration".'),
34
- chalk_1.default.greenBright('?'),
35
+ chalk_1.default.yellowBright('What is the name of your integration?'),
35
36
  ].join('\n'),
36
- message: chalk_1.default.yellowBright('What is the name of your integration?'),
37
- filter: name => name
37
+ filter: (name) => name
38
38
  .toLowerCase()
39
39
  .replace(/ /g, '_')
40
40
  .replace(/[^a-z0-9_-]*/g, ''),
@@ -36,6 +36,7 @@ class Login extends baseCommand_1.BaseCommand {
36
36
  try {
37
37
  apiKey = (await inquirer_1.default.prompt([
38
38
  {
39
+ type: 'input',
39
40
  name: 'apiKey',
40
41
  message: 'Enter your API key:',
41
42
  },
@@ -102,7 +102,7 @@ class Oauth2 extends core_1.Command {
102
102
  }
103
103
  const refreshToken = decryptionResult?.successful.refreshToken;
104
104
  core_1.ux.action.start(`Refreshing test account ${testAccount}`, undefined, { stdout: true });
105
- credentials = await Oauth2Resource.updateToken(oauth2, refreshToken);
105
+ credentials = await Oauth2Resource.updateToken(oauth2, refreshToken, decryptionResult?.successful, environment);
106
106
  // If provider response doesn't contain a new refresh token, use the existing one
107
107
  credentials.refreshToken = credentials.refreshToken ?? refreshToken;
108
108
  core_1.ux.action.stop();
@@ -41,7 +41,7 @@ class Test extends baseCommand_1.BaseCommand {
41
41
  description: '(advanced) credential payload to use.',
42
42
  exclusive: ['credential-id'],
43
43
  }),
44
- 'credential-id': core_1.Flags.integer({
44
+ 'credential-id': core_1.Flags.string({
45
45
  description: '(advanced) credential to use.',
46
46
  exclusive: ['credential-payload'],
47
47
  }),
package/dist/src/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Public re-exports
3
4
  var core_1 = require("@oclif/core");
4
5
  Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
@@ -1,3 +1,3 @@
1
1
  import * as GlobalConfiguration from './globalConfiguration';
2
2
  import { Credential } from '../services/integrationsPlatform';
3
- export declare function fetchCredential(environment: GlobalConfiguration.Environment, configDir: string, credentialId: number): Promise<Credential>;
3
+ export declare function fetchCredential(environment: GlobalConfiguration.Environment, configDir: string, credentialId: string): Promise<Credential>;
@@ -1,4 +1,4 @@
1
1
  import { Oauth2Response, Oauth2Payload } from '../services/oauth2';
2
2
  import { Environment } from './globalConfiguration';
3
3
  export declare function performOAuth2Flow(applicationCredentials: Oauth2Payload, environment?: Environment, credentialPayload?: Record<string, unknown>): Promise<Oauth2Response>;
4
- export declare function updateToken(applicationCredentials: Oauth2Payload, refreshToken: string): Promise<Oauth2Response>;
4
+ export declare function updateToken(applicationCredentials: Oauth2Payload, refreshToken: string, credentialPayload?: Record<string, unknown>, environment?: Environment): Promise<Oauth2Response>;
@@ -22,7 +22,7 @@ async function performOAuth2Flow(applicationCredentials, environment = globalCon
22
22
  }
23
23
  return oauth2Response;
24
24
  }
25
- async function updateToken(applicationCredentials, refreshToken) {
26
- const oauthHelper = new oauth2_1.default(applicationCredentials);
25
+ async function updateToken(applicationCredentials, refreshToken, credentialPayload, environment = globalConfiguration_1.Environment.Production) {
26
+ const oauthHelper = new oauth2_1.default(applicationCredentials, environment, credentialPayload);
27
27
  return oauthHelper.updateToken(refreshToken);
28
28
  }
@@ -40,4 +40,4 @@ export declare function getIntegrationEvents(integrationId: number, options?: {
40
40
  export declare function updateIntegration(integrationId: number, configuration: Configuration & {
41
41
  archived?: boolean;
42
42
  }): Promise<Integration>;
43
- export declare function getCredential(credentialId: number): Promise<Credential>;
43
+ export declare function getCredential(credentialId: string): Promise<Credential>;
@@ -66,7 +66,7 @@ export type Error = {
66
66
  stack?: string[];
67
67
  };
68
68
  export type AuthorizationMethod = 'custom' | 'oauth2';
69
- export type AuthorizationGrantType = 'authorization_code' | 'password' | 'client_credentials';
69
+ export type AuthorizationGrantType = 'authorization_code' | 'password' | 'client_credentials' | 'urn:ietf:params:oauth:grant-type:jwt-bearer';
70
70
  export type AuthorizationScope = {
71
71
  /** The name of the scope. */
72
72
  name: string;
@@ -93,6 +93,8 @@ export type AuthorizationOAuth2 = {
93
93
  authorizationUrl?: string;
94
94
  /** The URL to obtain or refresh an access token. */
95
95
  tokenUrl: string;
96
+ /** The callback URL which the provider will redirect the user after granting or denying access. */
97
+ legacyRedirectUrl?: string;
96
98
  grantType: AuthorizationGrantType;
97
99
  scopes: AuthorizationScope[];
98
100
  requestContentType: AuthorizationOAuth2ContentType;
@@ -143,7 +145,7 @@ export type IntegrationEvent = {
143
145
  };
144
146
  export type Credential = Base & {
145
147
  /** The id of the credential. */
146
- id: number;
148
+ id: string;
147
149
  /** The id of the integration. */
148
150
  integrationId: number;
149
151
  /** The name of the integration. */
@@ -319,7 +321,7 @@ export declare function getCredentials({ pagination, filters, }?: {
319
321
  /** The integration id of the credential. */
320
322
  integrationId?: number;
321
323
  /** List of credential ids. */
322
- id?: number[];
324
+ id?: string[];
323
325
  /** The scope of the credential. */
324
326
  credentialScope?: 'development' | 'compliance' | 'production' | 'service';
325
327
  /** The id of the Unito User for which this credential belongs to. */
@@ -350,11 +352,11 @@ export declare function createCredential(body?: {
350
352
  /**
351
353
  * Get a credential
352
354
  */
353
- export declare function getCredentialById(credentialId: number, opts?: Oazapfts.RequestOpts): Promise<Credential>;
355
+ export declare function getCredentialById(credentialId: string, opts?: Oazapfts.RequestOpts): Promise<Credential>;
354
356
  /**
355
357
  * Update a credential
356
358
  */
357
- export declare function updateCredential(credentialId: number, body?: {
359
+ export declare function updateCredential(credentialId: string, body?: {
358
360
  payload?: {
359
361
  [key: string]: any;
360
362
  };
@@ -366,7 +368,7 @@ export declare function updateCredential(credentialId: number, body?: {
366
368
  /**
367
369
  * Delete a credential
368
370
  */
369
- export declare function deleteCredential(credentialId: number, opts?: Oazapfts.RequestOpts): Promise<unknown>;
371
+ export declare function deleteCredential(credentialId: string, opts?: Oazapfts.RequestOpts): Promise<unknown>;
370
372
  /**
371
373
  * Returns the credentialAccount either from the integration's /me endpoint, if available, or the credential's latestCredentialAccount
372
374
  */
@@ -444,33 +446,47 @@ export declare function updateWebhookSubscription(xUnitoCredentialId: string, bo
444
446
  /**
445
447
  * Call an integration's graph
446
448
  */
447
- export declare function getProxyGraph(xUnitoCredentialId: string, path: string, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, accept, }?: {
449
+ export declare function getProxyGraph(xUnitoCredentialId: string, path: string, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, accept, xUnitoOperationDeadline, }?: {
448
450
  xUnitoCorrelationId?: string;
449
451
  xUnitoAdditionalLoggingContext?: string;
450
452
  accept?: string;
453
+ xUnitoOperationDeadline?: string;
451
454
  }, opts?: Oazapfts.RequestOpts): Promise<any>;
452
455
  /**
453
456
  * Call an integration's graph
454
457
  */
455
- export declare function patchProxyGraph(xUnitoCredentialId: string, path: string, body?: object, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, }?: {
458
+ export declare function patchProxyGraph(xUnitoCredentialId: string, path: string, body?: object, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, xUnitoOperationDeadline, }?: {
456
459
  xUnitoCorrelationId?: string;
457
460
  xUnitoAdditionalLoggingContext?: string;
458
461
  contentType?: string;
462
+ xUnitoOperationDeadline?: string;
459
463
  }, opts?: Oazapfts.RequestOpts): Promise<any>;
460
464
  /**
461
465
  * Call an integration's graph
462
466
  */
463
- export declare function postProxyGraph(xUnitoCredentialId: string, path: string, body?: object, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, }?: {
467
+ export declare function postProxyGraph(xUnitoCredentialId: string, path: string, body?: object, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, xUnitoOperationDeadline, }?: {
464
468
  xUnitoCorrelationId?: string;
465
469
  xUnitoAdditionalLoggingContext?: string;
466
470
  contentType?: string;
471
+ xUnitoOperationDeadline?: string;
467
472
  }, opts?: Oazapfts.RequestOpts): Promise<any>;
468
473
  /**
469
474
  * Call an integration's graph
470
475
  */
471
- export declare function deleteProxyGraph(xUnitoCredentialId: string, path: string, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, }?: {
476
+ export declare function deleteProxyGraph(xUnitoCredentialId: string, path: string, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, xUnitoOperationDeadline, }?: {
477
+ xUnitoCorrelationId?: string;
478
+ xUnitoAdditionalLoggingContext?: string;
479
+ xUnitoOperationDeadline?: string;
480
+ }, opts?: Oazapfts.RequestOpts): Promise<any>;
481
+ /**
482
+ * Call an integration's graph with multipart/form-data
483
+ */
484
+ export declare function postProxyGraphMultipart(xUnitoCredentialId: string, path: string, body?: {
485
+ [key: string]: any;
486
+ }, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, xUnitoOperationDeadline, }?: {
472
487
  xUnitoCorrelationId?: string;
473
488
  xUnitoAdditionalLoggingContext?: string;
489
+ xUnitoOperationDeadline?: string;
474
490
  }, opts?: Oazapfts.RequestOpts): Promise<any>;
475
491
  /**
476
492
  * Get all the users
@@ -30,6 +30,7 @@ exports.getProxyGraph = getProxyGraph;
30
30
  exports.patchProxyGraph = patchProxyGraph;
31
31
  exports.postProxyGraph = postProxyGraph;
32
32
  exports.deleteProxyGraph = deleteProxyGraph;
33
+ exports.postProxyGraphMultipart = postProxyGraphMultipart;
33
34
  exports.getUsers = getUsers;
34
35
  exports.createUser = createUser;
35
36
  exports.getUserById = getUserById;
@@ -314,7 +315,7 @@ function updateWebhookSubscription(xUnitoCredentialId, body, { xUnitoCorrelation
314
315
  /**
315
316
  * Call an integration's graph
316
317
  */
317
- function getProxyGraph(xUnitoCredentialId, path, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, accept, } = {}, opts) {
318
+ function getProxyGraph(xUnitoCredentialId, path, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, accept, xUnitoOperationDeadline, } = {}, opts) {
318
319
  return oazapfts.ok(oazapfts.fetchJson(`/proxy/graph${QS.query(QS.explode({
319
320
  path,
320
321
  }))}`, {
@@ -324,13 +325,14 @@ function getProxyGraph(xUnitoCredentialId, path, { xUnitoCorrelationId, xUnitoAd
324
325
  'X-Unito-Correlation-Id': xUnitoCorrelationId,
325
326
  'X-Unito-Additional-Logging-Context': xUnitoAdditionalLoggingContext,
326
327
  Accept: accept,
328
+ 'X-Unito-Operation-Deadline': xUnitoOperationDeadline,
327
329
  }),
328
330
  }));
329
331
  }
330
332
  /**
331
333
  * Call an integration's graph
332
334
  */
333
- function patchProxyGraph(xUnitoCredentialId, path, body, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, } = {}, opts) {
335
+ function patchProxyGraph(xUnitoCredentialId, path, body, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, xUnitoOperationDeadline, } = {}, opts) {
334
336
  return oazapfts.ok(oazapfts.fetchJson(`/proxy/graph${QS.query(QS.explode({
335
337
  path,
336
338
  }))}`, oazapfts.json({
@@ -342,13 +344,14 @@ function patchProxyGraph(xUnitoCredentialId, path, body, { xUnitoCorrelationId,
342
344
  'X-Unito-Correlation-Id': xUnitoCorrelationId,
343
345
  'X-Unito-Additional-Logging-Context': xUnitoAdditionalLoggingContext,
344
346
  'Content-Type': contentType,
347
+ 'X-Unito-Operation-Deadline': xUnitoOperationDeadline,
345
348
  }),
346
349
  })));
347
350
  }
348
351
  /**
349
352
  * Call an integration's graph
350
353
  */
351
- function postProxyGraph(xUnitoCredentialId, path, body, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, } = {}, opts) {
354
+ function postProxyGraph(xUnitoCredentialId, path, body, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, contentType, xUnitoOperationDeadline, } = {}, opts) {
352
355
  return oazapfts.ok(oazapfts.fetchJson(`/proxy/graph${QS.query(QS.explode({
353
356
  path,
354
357
  }))}`, oazapfts.json({
@@ -360,13 +363,14 @@ function postProxyGraph(xUnitoCredentialId, path, body, { xUnitoCorrelationId, x
360
363
  'X-Unito-Correlation-Id': xUnitoCorrelationId,
361
364
  'X-Unito-Additional-Logging-Context': xUnitoAdditionalLoggingContext,
362
365
  'Content-Type': contentType,
366
+ 'X-Unito-Operation-Deadline': xUnitoOperationDeadline,
363
367
  }),
364
368
  })));
365
369
  }
366
370
  /**
367
371
  * Call an integration's graph
368
372
  */
369
- function deleteProxyGraph(xUnitoCredentialId, path, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, } = {}, opts) {
373
+ function deleteProxyGraph(xUnitoCredentialId, path, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, xUnitoOperationDeadline, } = {}, opts) {
370
374
  return oazapfts.ok(oazapfts.fetchJson(`/proxy/graph${QS.query(QS.explode({
371
375
  path,
372
376
  }))}`, {
@@ -376,9 +380,28 @@ function deleteProxyGraph(xUnitoCredentialId, path, { xUnitoCorrelationId, xUnit
376
380
  'X-Unito-Credential-Id': xUnitoCredentialId,
377
381
  'X-Unito-Correlation-Id': xUnitoCorrelationId,
378
382
  'X-Unito-Additional-Logging-Context': xUnitoAdditionalLoggingContext,
383
+ 'X-Unito-Operation-Deadline': xUnitoOperationDeadline,
379
384
  }),
380
385
  }));
381
386
  }
387
+ /**
388
+ * Call an integration's graph with multipart/form-data
389
+ */
390
+ function postProxyGraphMultipart(xUnitoCredentialId, path, body, { xUnitoCorrelationId, xUnitoAdditionalLoggingContext, xUnitoOperationDeadline, } = {}, opts) {
391
+ return oazapfts.ok(oazapfts.fetchJson(`/proxy/graph/multipart${QS.query(QS.explode({
392
+ path,
393
+ }))}`, oazapfts.multipart({
394
+ ...opts,
395
+ method: 'POST',
396
+ body,
397
+ headers: oazapfts.mergeHeaders(opts?.headers, {
398
+ 'X-Unito-Credential-Id': xUnitoCredentialId,
399
+ 'X-Unito-Correlation-Id': xUnitoCorrelationId,
400
+ 'X-Unito-Additional-Logging-Context': xUnitoAdditionalLoggingContext,
401
+ 'X-Unito-Operation-Deadline': xUnitoOperationDeadline,
402
+ }),
403
+ })));
404
+ }
382
405
  /**
383
406
  * Get all the users
384
407
  */
@@ -250,7 +250,7 @@ class OAuth2Service {
250
250
  });
251
251
  }
252
252
  try {
253
- const tokenResponse = await fetch(this.tokenUrl, {
253
+ const tokenResponse = await fetch((0, template_1.expandTemplate)(this.tokenUrl, templateVariables, { urlEncodeVariables: true }), {
254
254
  headers: {
255
255
  'Content-Type': this.requestContentType,
256
256
  ...(tokenRequestHeaders ?? {}),
@@ -303,4 +303,70 @@ describe('oauth2', () => {
303
303
  .it('must successfully decrypt all secrets', ctx => {
304
304
  (0, test_1.expect)(ctx.stderr).to.contain((0, styles_1.uncolorize)('The secret boom! could not be decrypted.'));
305
305
  });
306
+ test_1.test
307
+ .stdout()
308
+ .do(() => {
309
+ getConfigurationsStub.returns({
310
+ ...baseConfiguration,
311
+ testAccounts: {
312
+ development: credentials,
313
+ },
314
+ });
315
+ sinon
316
+ .stub(IntegrationsPlatform, 'encryptData')
317
+ .onFirstCall()
318
+ .resolves({ encryptedData: `${Configuration.ENCRYPTION_PREFIX}encryptedAccessToken` })
319
+ .onSecondCall()
320
+ .resolves({ encryptedData: `${Configuration.ENCRYPTION_PREFIX}encryptedRefreshToken` });
321
+ })
322
+ .stub(DecryptionResource, 'decryptEntries', stub => stub
323
+ .onFirstCall()
324
+ .resolves({ successful: { ...oauth2Information }, failed: [] })
325
+ .onSecondCall()
326
+ .resolves({ successful: { refreshToken: 'test-refresh-token' }, failed: [] }))
327
+ .command(['oauth2', '--test-account', 'development', '--environment', 'staging'])
328
+ .it('passes the staging environment to updateToken when specified', () => {
329
+ (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(0);
330
+ (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(1);
331
+ // Verify that updateToken was called with the correct environment parameter
332
+ const updateTokenCall = updateTokenStub.getCall(0);
333
+ (0, test_1.expect)(updateTokenCall.args).to.have.lengthOf(4);
334
+ (0, test_1.expect)(updateTokenCall.args[0]).to.deep.equal(oauth2Information); // oauth2 config
335
+ (0, test_1.expect)(updateTokenCall.args[1]).to.equal('test-refresh-token'); // refresh token
336
+ (0, test_1.expect)(updateTokenCall.args[2]).to.deep.equal({ refreshToken: 'test-refresh-token' }); // credential payload
337
+ (0, test_1.expect)(updateTokenCall.args[3]).to.equal('staging'); // environment
338
+ });
339
+ test_1.test
340
+ .stdout()
341
+ .do(() => {
342
+ getConfigurationsStub.returns({
343
+ ...baseConfiguration,
344
+ testAccounts: {
345
+ development: credentials,
346
+ },
347
+ });
348
+ sinon
349
+ .stub(IntegrationsPlatform, 'encryptData')
350
+ .onFirstCall()
351
+ .resolves({ encryptedData: `${Configuration.ENCRYPTION_PREFIX}encryptedAccessToken` })
352
+ .onSecondCall()
353
+ .resolves({ encryptedData: `${Configuration.ENCRYPTION_PREFIX}encryptedRefreshToken` });
354
+ })
355
+ .stub(DecryptionResource, 'decryptEntries', stub => stub
356
+ .onFirstCall()
357
+ .resolves({ successful: { ...oauth2Information }, failed: [] })
358
+ .onSecondCall()
359
+ .resolves({ successful: { refreshToken: 'test-refresh-token' }, failed: [] }))
360
+ .command(['oauth2', '--test-account', 'development'])
361
+ .it('defaults to production environment when no environment flag is specified', () => {
362
+ (0, test_1.expect)(performOAuth2FlowStub.getCalls().length).to.equal(0);
363
+ (0, test_1.expect)(updateTokenStub.getCalls().length).to.equal(1);
364
+ // Verify that updateToken was called with the default production environment
365
+ const updateTokenCall = updateTokenStub.getCall(0);
366
+ (0, test_1.expect)(updateTokenCall.args).to.have.lengthOf(4);
367
+ (0, test_1.expect)(updateTokenCall.args[0]).to.deep.equal(oauth2Information); // oauth2 config
368
+ (0, test_1.expect)(updateTokenCall.args[1]).to.equal('test-refresh-token'); // refresh token
369
+ (0, test_1.expect)(updateTokenCall.args[2]).to.deep.equal({ refreshToken: 'test-refresh-token' }); // credential payload
370
+ (0, test_1.expect)(updateTokenCall.args[3]).to.equal('production'); // environment (default)
371
+ });
306
372
  });
@@ -52,4 +52,32 @@ describe('OAuth2Helper', () => {
52
52
  await strict_1.default.rejects(response, errors_1.FailedToRetrieveAccessTokenError);
53
53
  });
54
54
  });
55
+ describe('updateToken', () => {
56
+ let updateTokenStub;
57
+ beforeEach(() => {
58
+ updateTokenStub = sinon_1.default.stub(oauth2_1.default.prototype, 'updateToken');
59
+ });
60
+ it('should create OAuth2Service with credential payload and call updateToken', async () => {
61
+ const mockResponse = { accessToken: 'new-token', refreshToken: 'new-refresh-token' };
62
+ updateTokenStub.resolves(mockResponse);
63
+ const credentialPayload = { domain: 'test-domain', customVar: 'test-value' };
64
+ const refreshToken = 'test-refresh-token';
65
+ const result = await oauth2HelperResource.updateToken(authorizationInfo, refreshToken, credentialPayload);
66
+ // Assert that the OAuth2Service was instantiated with the credential payload
67
+ // and that updateToken was called with the refresh token
68
+ sinon_1.default.assert.calledOnce(updateTokenStub);
69
+ sinon_1.default.assert.calledWith(updateTokenStub, refreshToken);
70
+ strict_1.default.deepEqual(result, mockResponse);
71
+ });
72
+ it('should work without credential payload', async () => {
73
+ const mockResponse = { accessToken: 'new-token', refreshToken: 'new-refresh-token' };
74
+ updateTokenStub.resolves(mockResponse);
75
+ const refreshToken = 'test-refresh-token';
76
+ const result = await oauth2HelperResource.updateToken(authorizationInfo, refreshToken);
77
+ // Should still work when no credential payload is provided
78
+ sinon_1.default.assert.calledOnce(updateTokenStub);
79
+ sinon_1.default.assert.calledWith(updateTokenStub, refreshToken);
80
+ strict_1.default.deepEqual(result, mockResponse);
81
+ });
82
+ });
55
83
  });
@@ -422,6 +422,43 @@ describe('OAuth2Helper', () => {
422
422
  const response = oauth2Helper.updateToken(refreshToken);
423
423
  await strict_1.default.rejects(response, errors_1.InvalidRequestContentTypeError);
424
424
  });
425
+ describe('token URL template expansion', () => {
426
+ it('expands template variables in token URL during refresh', async () => {
427
+ const credentialPayload = { domain: 'test-domain' };
428
+ oauth2Helper = new oauth2_1.default({
429
+ clientId: 'test-client-id',
430
+ clientSecret: 'test-client-secret',
431
+ authorizationUrl: 'https://provider.com/oauth/authorize',
432
+ scopes: [{ name: 'scope1' }],
433
+ tokenUrl: 'https://{+domain}.provider.com/oauth/token', // Template URL
434
+ grantType: configurationTypes_1.GrantType.AUTHORIZATION_CODE,
435
+ requestContentType: configurationTypes_1.RequestContentType.URL_ENCODED,
436
+ }, globalConfiguration_1.Environment.Production, credentialPayload);
437
+ const { refreshToken } = setupSuccessfulRefreshResponse();
438
+ await oauth2Helper.updateToken(refreshToken);
439
+ // Assert that the token URL was expanded with the domain
440
+ sinon_1.default.assert.calledWith(fetchStub, 'https://test-domain.provider.com/oauth/token', sinon_1.default.match.object);
441
+ });
442
+ it('expands multiple template variables in token URL', async () => {
443
+ const credentialPayload = {
444
+ domain: 'my-company',
445
+ environment: 'staging',
446
+ };
447
+ oauth2Helper = new oauth2_1.default({
448
+ clientId: 'test-client-id',
449
+ clientSecret: 'test-client-secret',
450
+ authorizationUrl: 'https://provider.com/oauth/authorize',
451
+ scopes: [{ name: 'scope1' }],
452
+ tokenUrl: 'https://{+domain}.{+environment}.provider.com/oauth/token',
453
+ grantType: configurationTypes_1.GrantType.AUTHORIZATION_CODE,
454
+ requestContentType: configurationTypes_1.RequestContentType.URL_ENCODED,
455
+ }, globalConfiguration_1.Environment.Production, credentialPayload);
456
+ const { refreshToken } = setupSuccessfulRefreshResponse();
457
+ await oauth2Helper.updateToken(refreshToken);
458
+ // Assert that both template variables were expanded
459
+ sinon_1.default.assert.calledWith(fetchStub, 'https://my-company.staging.provider.com/oauth/token', sinon_1.default.match.object);
460
+ });
461
+ });
425
462
  });
426
463
  describe('encodeBody', () => {
427
464
  it('encodes body data as URL-encoded when content type is URL_ENCODED', () => {
@@ -1 +1 @@
1
- {"root":["../src/baseCommand.ts","../src/configurationTypes.ts","../src/errors.ts","../src/index.ts","../src/commands/activity.ts","../src/commands/dev.ts","../src/commands/encrypt.ts","../src/commands/init.ts","../src/commands/invite.ts","../src/commands/login.ts","../src/commands/oauth2.ts","../src/commands/publish.ts","../src/commands/test.ts","../src/commands/upgrade.ts","../src/hooks/init/displayLogo.ts","../src/resources/configuration.ts","../src/resources/credentials.ts","../src/resources/decryption.ts","../src/resources/fileSystem.ts","../src/resources/globalConfiguration.ts","../src/resources/integrations.ts","../src/resources/integrationsPlatform.ts","../src/resources/oauth2.ts","../src/resources/template.ts","../src/services/integrationsPlatform.ts","../src/services/integrationsPlatformClient.ts","../src/services/oauth2.ts","../test/errors.test.ts","../test/commands/activity.test.ts","../test/commands/dev.test.ts","../test/commands/encrypt.test.ts","../test/commands/init.test.ts","../test/commands/invite.test.ts","../test/commands/login.test.ts","../test/commands/oauth2.test.ts","../test/commands/publish.test.ts","../test/commands/test.test.ts","../test/commands/upgrade.test.ts","../test/helpers/init.js","../test/helpers/integrations.ts","../test/helpers/styles.ts","../test/resources/configuration.test.ts","../test/resources/decryption.test.ts","../test/resources/globalConfiguration.test.ts","../test/resources/integrations.test.ts","../test/resources/oauth2.test.ts","../test/resources/template.test.ts","../test/services/integrationsPlatform.test.ts","../test/services/oauth2.test.ts","../scripts/generateTypes.ts","../.eslintrc.js"],"version":"5.8.3"}
1
+ {"root":["../src/baseCommand.ts","../src/configurationTypes.ts","../src/errors.ts","../src/index.ts","../src/commands/activity.ts","../src/commands/dev.ts","../src/commands/encrypt.ts","../src/commands/init.ts","../src/commands/invite.ts","../src/commands/login.ts","../src/commands/oauth2.ts","../src/commands/publish.ts","../src/commands/test.ts","../src/commands/upgrade.ts","../src/hooks/init/displayLogo.ts","../src/resources/configuration.ts","../src/resources/credentials.ts","../src/resources/decryption.ts","../src/resources/fileSystem.ts","../src/resources/globalConfiguration.ts","../src/resources/integrations.ts","../src/resources/integrationsPlatform.ts","../src/resources/oauth2.ts","../src/resources/template.ts","../src/services/integrationsPlatform.ts","../src/services/integrationsPlatformClient.ts","../src/services/oauth2.ts","../test/errors.test.ts","../test/commands/activity.test.ts","../test/commands/dev.test.ts","../test/commands/encrypt.test.ts","../test/commands/init.test.ts","../test/commands/invite.test.ts","../test/commands/login.test.ts","../test/commands/oauth2.test.ts","../test/commands/publish.test.ts","../test/commands/test.test.ts","../test/commands/upgrade.test.ts","../test/helpers/init.js","../test/helpers/integrations.ts","../test/helpers/styles.ts","../test/resources/configuration.test.ts","../test/resources/decryption.test.ts","../test/resources/globalConfiguration.test.ts","../test/resources/integrations.test.ts","../test/resources/oauth2.test.ts","../test/resources/template.test.ts","../test/services/integrationsPlatform.test.ts","../test/services/oauth2.test.ts","../scripts/generateTypes.ts","../.eslintrc.js"],"version":"5.9.3"}