diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index bf7c1fac..e6def7e3 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -1,4 +1,6 @@ unreleased: + new features: + - GH-1003 Added support for `pm.vault` VariableScope fixed bugs: - GH-1018 Fixed warnings for all `postman.*` legacy APIs chores: diff --git a/README.md b/README.md index de04ebe8..1cee68fb 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,18 @@ The following section outlines the API available inside sandbox scripts ### pm +- pm.test +- pm.info +- pm.vault - pm.globals +- pm.cookies +- pm.execution +- pm.variables +- pm.visualizer +- pm.sendRequest - pm.environment +- pm.iterationData - pm.collectionVariables -- pm.test #### pre-request script specials diff --git a/lib/sandbox/execution.js b/lib/sandbox/execution.js index ab521ac9..f5b0d8e8 100644 --- a/lib/sandbox/execution.js +++ b/lib/sandbox/execution.js @@ -18,7 +18,7 @@ const _ = require('lodash'), test: true }, - CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals'], + CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals', 'vaultSecrets'], trackingOptions = { autoCompact: true }; diff --git a/lib/sandbox/pmapi.js b/lib/sandbox/pmapi.js index 1782b8f4..ffd6262b 100644 --- a/lib/sandbox/pmapi.js +++ b/lib/sandbox/pmapi.js @@ -63,6 +63,7 @@ function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, execution._variables.addLayer(execution.environment.values); execution._variables.addLayer(execution.collectionVariables.values); execution._variables.addLayer(execution.globals.values); + execution._variables.addLayer(execution.vaultSecrets.values); execution.cookies && (execution.cookies.jar = function () { return new PostmanCookieJar(cookieStore); @@ -124,6 +125,11 @@ function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, requestId: execution.legacy._itemId }), + /** + * @type {VariableScope} + */ + vault: execution.vaultSecrets, + /** * @type {VariableScope} */ diff --git a/test/unit/pm-variables-tracking.test.js b/test/unit/pm-variables-tracking.test.js index e2fd0973..e81736d0 100644 --- a/test/unit/pm-variables-tracking.test.js +++ b/test/unit/pm-variables-tracking.test.js @@ -26,6 +26,10 @@ describe('pm api variables', function () { assert.equal(pm.collectionVariables.mutations.count(), 0); pm.collectionVariables.set('foo', 'foo'); assert.equal(pm.collectionVariables.mutations.count(), 1); + + assert.equal(pm.vault.mutations.count(), 0); + pm.vault.set('foo', 'foo'); + assert.equal(pm.vault.mutations.count(), 1); `, done); }); }); @@ -41,6 +45,7 @@ describe('pm api variables', function () { pm.environment.set('foo', 'environment'); pm.globals.set('foo', 'global'); pm.collectionVariables.set('foo', 'collectionVariables'); + pm.vault.set('foo', 'vaultVariable'); `, function (err, result) { if (err) { return done(err); @@ -58,6 +63,9 @@ describe('pm api variables', function () { expect(result.collectionVariables.mutations).to.be.ok; expect(new sdk.MutationTracker(result.collectionVariables.mutations).count()).to.equal(1); + expect(result.vaultSecrets.mutations).to.be.ok; + expect(new sdk.MutationTracker(result.vaultSecrets.mutations).count()).to.equal(1); + done(); }); }); @@ -82,16 +90,38 @@ describe('pm api variables', function () { ctx.execute(` var assert = require('assert'); + assert.equal(pm.variables.get('bar'), 'bar value'); pm.variables.set('foo', '_variable'); + + assert.equal(pm.environment.get('bar'), 'bar value'); pm.environment.set('foo', 'environment'); + + assert.equal(pm.globals.get('bar'), 'bar value'); pm.globals.set('foo', 'global'); + + assert.equal(pm.collectionVariables.get('bar'), 'bar value'); pm.collectionVariables.set('foo', 'collectionVariables'); + + assert.equal(pm.vault.get('bar'), 'bar value'); + pm.vault.set('foo', 'vault'); `, { context: { globals: scopeDefinition, _variables: scopeDefinition, environment: scopeDefinition, - collectionVariables: scopeDefinition + collectionVariables: scopeDefinition, + vaultSecrets: { + prefix: 'vault:', + values: [ + { key: 'vault:bar', value: 'bar value' } + ], + mutations: { + autoCompact: true, + compacted: { + 'vault:bar': ['vault:bar', 'bar value'] + } + } + } } }, function (err, result) { if (err) { @@ -110,6 +140,9 @@ describe('pm api variables', function () { expect(result.collectionVariables.mutations).to.be.ok; expect(new sdk.MutationTracker(result.collectionVariables.mutations).count()).to.equal(1); + expect(result.vaultSecrets.mutations).to.be.ok; + expect(new sdk.MutationTracker(result.vaultSecrets.mutations).count()).to.equal(1); + done(); }); }); diff --git a/test/unit/pm-variables.test.js b/test/unit/pm-variables.test.js index c77d55e1..25da12f8 100644 --- a/test/unit/pm-variables.test.js +++ b/test/unit/pm-variables.test.js @@ -30,13 +30,15 @@ describe('pm.variables', function () { describe('.set', function () { before(function (done) { - var globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), + var vaultSecretList = new sdk.VariableList(null, { key: 'vault:key-0', value: 'value-0' }), + globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), collectionVarList = new sdk.VariableList(null, { key: 'key-2', value: 'value-2' }), envVarList = new sdk.VariableList(null, { key: 'key-3', value: 'value-3' }), contextData = { 'key-4': 'value-4' }, localVarList = new sdk.VariableList(null, { key: 'key-5', value: 'value-5' }); ctx.execute(` + pm.variables.set("vault:key-0", "modified"); pm.variables.set("key-1", "modified"); pm.variables.set("key-2", "modified"); pm.variables.set("key-3", "modified"); @@ -46,6 +48,7 @@ describe('pm.variables', function () { `, { timeout: 200, context: { + vaultSecrets: new sdk.VariableScope(vaultSecretList), globals: new sdk.VariableScope(globalVarList), collectionVariables: new sdk.VariableScope(collectionVarList), environment: new sdk.VariableScope(envVarList), @@ -64,6 +67,7 @@ describe('pm.variables', function () { it('should return the modified variables in the result', function () { expect(executionResults).to.deep.nested.include({ '_variables.values': [ { type: 'any', value: 'modified', key: 'key-5' }, + { type: 'any', value: 'modified', key: 'vault:key-0' }, { type: 'any', value: 'modified', key: 'key-1' }, { type: 'any', value: 'modified', key: 'key-2' }, { type: 'any', value: 'modified', key: 'key-3' }, @@ -72,8 +76,11 @@ describe('pm.variables', function () { ] }); }); - it('should not modify the globals, envrironment, collection and data variables', function () { + it('should not modify the globals, environment, collection and data variables', function () { expect(executionResults).to.deep.nested.include({ + 'vaultSecrets.values': [ + { type: 'any', value: 'value-0', key: 'vault:key-0' } + ], 'globals.values': [ { type: 'any', value: 'value-1', key: 'key-1' } ], @@ -128,7 +135,12 @@ describe('pm.variables', function () { describe('.get', function () { it('should honour the precendence', function (done) { - var globalVarList = new sdk.VariableList(null, [ + var vaultSecretList = new sdk.VariableList(null, [ + { key: 'vault:key-0', value: 'value-0' }, + { key: 'vault:key-1', value: 'value-0' } + ]), + globalVarList = new sdk.VariableList(null, [ + { key: 'vault:key-1', value: 'value-1' }, { key: 'key-1', value: 'value-1' }, { key: 'key-2', value: 'value-1' }, { key: 'key-3', value: 'value-1' }, @@ -165,11 +177,14 @@ describe('pm.variables', function () { 'key-2': 'value-2', 'key-3': 'value-3', 'key-4': 'value-4', - 'key-5': 'value-5' + 'key-5': 'value-5', + 'vault:key-0': 'value-0', + 'vault:key-1': 'value-1' }); `, { timeout: 200, context: { + vaultSecrets: new sdk.VariableScope(vaultSecretList), globals: new sdk.VariableScope(globalVarList), collectionVariables: new sdk.VariableScope(collectionVarList), environment: new sdk.VariableScope(envVarList), @@ -186,7 +201,8 @@ describe('pm.variables', function () { }); it('should return appropriate variables', function (done) { - var globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), + var vaultSecretList = new sdk.VariableList(null, { key: 'vault:key-0', value: 'value-0' }), + globalVarList = new sdk.VariableList(null, { key: 'key-1', value: 'value-1' }), collectionVarList = new sdk.VariableList(null, { key: 'key-2', value: 'value-2' }), envVarList = new sdk.VariableList(null, { key: 'key-3', value: 'value-3' }), contextData = { 'key-4': 'value-4' }, @@ -194,6 +210,7 @@ describe('pm.variables', function () { ctx.execute(` var assert = require('assert'); + assert.strictEqual(pm.variables.get('vault:key-0'), 'value-0'); assert.strictEqual(pm.variables.get('key-1'), 'value-1'); assert.strictEqual(pm.variables.get('key-2'), 'value-2'); assert.strictEqual(pm.variables.get('key-3'), 'value-3'); @@ -203,6 +220,7 @@ describe('pm.variables', function () { `, { timeout: 200, context: { + vaultSecrets: new sdk.VariableScope(vaultSecretList), globals: new sdk.VariableScope(globalVarList), collectionVariables: new sdk.VariableScope(collectionVarList), environment: new sdk.VariableScope(envVarList), @@ -221,6 +239,7 @@ describe('pm.variables', function () { it('should reinitialize the variables when same sandbox instance is used again', function (done) { ctx.execute(` var assert = require('assert'); + assert.strictEqual(pm.variables.get('vault:key-0'), undefined); assert.strictEqual(pm.variables.get('key-1'), undefined); assert.strictEqual(pm.variables.get('key-2'), undefined); assert.strictEqual(pm.variables.get('key-3'), undefined); @@ -234,6 +253,7 @@ describe('pm.variables', function () { if (err) { return done(err); } expect(execution).to.deep.nested.include({ + 'vaultSecrets.values': [], 'globals.values': [], '_variables.values': [], 'collectionVariables.values': [], diff --git a/test/unit/sandbox-libraries/pm.test.js b/test/unit/sandbox-libraries/pm.test.js index fa3b83b7..317608b6 100644 --- a/test/unit/sandbox-libraries/pm.test.js +++ b/test/unit/sandbox-libraries/pm.test.js @@ -1,4 +1,5 @@ -const CookieStore = require('@postman/tough-cookie').Store; +const { VariableScope } = require('postman-collection'), + CookieStore = require('@postman/tough-cookie').Store; describe('sandbox library - pm api', function () { this.timeout(1000 * 60); @@ -30,6 +31,17 @@ describe('sandbox library - pm api', function () { value: 2.9, type: 'number' }], + vaultSecrets: new VariableScope({ + prefix: 'vault:', + values: [{ + key: 'vault:var1', + value: 'one-vault', + type: 'string' + }, { + key: 'vault:var2', + value: 'two-vault', + type: 'string' + }] }), data: { var1: 'one-data' } @@ -265,6 +277,77 @@ describe('sandbox library - pm api', function () { }); }); + describe('vault', function () { + it('should be defined as VariableScope', function (done) { + context.execute(` + var assert = require('assert'), + VariableScope = require('postman-collection').VariableScope; + assert.strictEqual(VariableScope.isVariableScope(pm.vault), true); + `, { context: sampleContextData }, done); + }); + + it('should be a readonly property', function (done) { + context.execute(` + var assert = require('assert'), + _vaultSecrets; + + _vaultSecrets = pm.vault; + pm.vault = []; + + assert.strictEqual(pm.vault, _vaultSecrets, 'property stays unchanged'); + `, { context: sampleContextData }, done); + }); + + it('should forward vaultSecrets forwarded during execution', function (done) { + context.execute(` + var assert = require('assert'); + assert.strictEqual(pm.vault.get('var1'), 'one-vault'); + assert.strictEqual(pm.vault.get('var2'), 'two-vault'); + `, { context: sampleContextData }, done); + }); + + it('pm.vault.toObject must return a pojo', function (done) { + context.execute(` + var assert = require('assert'); + + assert.strictEqual(_.isPlainObject(pm.vault.toObject()), true); + assert.deepEqual(pm.vault.toObject(), { + 'vault:var1': 'one-vault', + 'vault:var2': 'two-vault' + }); + `, { context: sampleContextData }, done); + }); + it('pm.variables.toObject must contain vaultSecrets', function (done) { + context.execute(` + var assert = require('assert'); + + assert.strictEqual(_.isPlainObject(pm.variables.toObject()), true); + assert.deepEqual(pm.variables.toObject(), { + 'vault:var1': 'one-vault', + 'vault:var2': 'two-vault', + 'var1': 'one-data', + 'var2': 2.5 + }); + `, { context: sampleContextData }, done); + }); + it('should propagate updated vault secrets from inside sandbox', function (done) { + context.execute(` + var assert = require('assert'); + + pm.vault.set('var1', 'one-one-vault'); + assert.strictEqual(pm.vault.get('var1'), 'one-one-vault'); + `, { context: sampleContextData }, function (err, exec) { + expect(err).to.be.null; + expect(exec).to.be.ok; + expect(exec).to.deep.nested.include({ 'vaultSecrets.values': [ + { type: 'string', value: 'one-one-vault', key: 'vault:var1' }, + { type: 'string', value: 'two-vault', key: 'vault:var2' } + ] }); + done(); + }); + }); + }); + describe('request', function () { it('should be defined as sdk Request object', function (done) { context.execute(` diff --git a/types/index.d.ts b/types/index.d.ts index 4cdf585e..f53c1603 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for postman-sandbox 4.7.1 +// Type definitions for postman-sandbox 5.0.0 // Project: https://github.com/postmanlabs/postman-sandbox // Definitions by: PostmanLabs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -175,6 +175,7 @@ declare class Postman { * stored inside of this object. */ info: Info; + vault: VariableScope; globals: VariableScope; environment: VariableScope; collectionVariables: VariableScope; diff --git a/types/sandbox/prerequest.d.ts b/types/sandbox/prerequest.d.ts index 91578a4a..89088245 100644 --- a/types/sandbox/prerequest.d.ts +++ b/types/sandbox/prerequest.d.ts @@ -1,4 +1,4 @@ -// Type definitions for postman-sandbox 4.7.1 +// Type definitions for postman-sandbox 5.0.0 // Project: https://github.com/postmanlabs/postman-sandbox // Definitions by: PostmanLabs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -109,6 +109,7 @@ declare class Postman { * stored inside of this object. */ info: Info; + vault: import("postman-collection").VariableScope; globals: import("postman-collection").VariableScope; environment: import("postman-collection").VariableScope; collectionVariables: import("postman-collection").VariableScope; diff --git a/types/sandbox/test.d.ts b/types/sandbox/test.d.ts index 0403a4a1..d049859f 100644 --- a/types/sandbox/test.d.ts +++ b/types/sandbox/test.d.ts @@ -1,4 +1,4 @@ -// Type definitions for postman-sandbox 4.7.1 +// Type definitions for postman-sandbox 5.0.0 // Project: https://github.com/postmanlabs/postman-sandbox // Definitions by: PostmanLabs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -139,6 +139,7 @@ declare class Postman { * stored inside of this object. */ info: Info; + vault: import("postman-collection").VariableScope; globals: import("postman-collection").VariableScope; environment: import("postman-collection").VariableScope; collectionVariables: import("postman-collection").VariableScope;