@unito/integration-cli 0.63.3 → 0.63.4

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.
@@ -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();
@@ -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
  }
@@ -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,5 +1,5 @@
1
1
  {
2
- "version": "0.63.3",
2
+ "version": "0.63.4",
3
3
  "commands": {
4
4
  "activity": {
5
5
  "id": "activity",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unito/integration-cli",
3
- "version": "0.63.3",
3
+ "version": "0.63.4",
4
4
  "description": "Integration CLI",
5
5
  "bin": {
6
6
  "integration-cli": "./bin/run"