Skip to content

Commit 8167475

Browse files
committed
added support of secret variable
1 parent bd8a1f1 commit 8167475

9 files changed

+176
-15
lines changed

lib/collection/mutation-tracker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var _ = require('../util').lodash,
2121
* @returns {Boolean}
2222
*/
2323
isPrimitiveMutation = function (mutation) {
24-
return mutation && mutation.length <= 2;
24+
return mutation && mutation.length <= 3;
2525
},
2626

2727
/**

lib/collection/property.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ var _ = require('../util').lodash,
1616
*
1717
* @private
1818
* @param {*} value Any JS variable within which we are trying to discover {{variables}}
19-
* @param {[Object]} seen Set of objects traversed before to avoid infinite recursion
20-
* @param {[Object]} result Set of variables to accumulate result in the recursive call
21-
* @returns {Object} Set of variables
19+
* @param {Object[]} seen Set of objects traversed before to avoid infinite recursion
20+
* @param {Object[]} result Set of variables to accumulate result in the recursive call
21+
* @returns {Object[]} Set of variables
2222
*/
2323
function _findSubstitutions (value, seen = new Set(), result = new Set()) {
2424
if (!value || seen.has(value)) {

lib/collection/variable-scope.js

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ var _ = require('../util').lodash,
1515
SET: 'set',
1616
UNSET: 'unset'
1717
},
18-
18+
SECRET = 'secret',
19+
DEFAULT = 'default',
1920
VariableScope;
2021

2122
/**
@@ -219,7 +220,7 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ {
219220
*
220221
* @param {String} key - The name of the variable to set.
221222
* @param {*} value - The value of the variable to be set.
222-
* @param {Variable.types} [type] - Optionally, the value of the variable can be set to a type
223+
* @param {'secret' | 'default'} [type] - Optionally, the value of the variable can be set to a type
223224
*/
224225
set: function (key, value, type) {
225226
var variable = this.values.oneNormalizedVariable(key),
@@ -239,7 +240,15 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ {
239240
}
240241

241242
// track the change if mutation tracking is enabled
242-
this._postman_enableTracking && this.mutations.track(MUTATIONS.SET, key, value);
243+
if (this._postman_enableTracking) {
244+
// eslint-disable-next-line security/detect-possible-timing-attacks
245+
if (type === SECRET || type === DEFAULT) {
246+
this.mutations.track(MUTATIONS.SET, key, value, type);
247+
}
248+
else {
249+
this.mutations.track(MUTATIONS.SET, key, value);
250+
}
251+
}
243252
},
244253

245254
/**
@@ -359,13 +368,14 @@ _.assign(VariableScope.prototype, /** @lends VariableScope.prototype */ {
359368
* @param {String} instruction Instruction identifying the type of the mutation, e.g. `set`, `unset`
360369
* @param {String} key -
361370
* @param {*} value -
371+
* @param {String} type -
362372
*/
363-
applyMutation: function (instruction, key, value) {
373+
applyMutation: function (instruction, key, value, type) {
364374
// we know that `set` and `unset` are the only supported instructions
365375
// and we know the parameter signature of both is the same as the items in a mutation
366376
/* istanbul ignore else */
367377
if (this[instruction]) {
368-
this[instruction](key, value);
378+
this[instruction](key, value, type);
369379
}
370380
},
371381

@@ -463,6 +473,41 @@ _.assign(VariableScope, /** @lends VariableScope */ {
463473
}
464474
});
465475

476+
/**
477+
* CollectionVariableScope are the variable scope that are defined at the collection level.
478+
*/
479+
class CollectionVariableScope extends VariableScope {
480+
/**
481+
* Creates a new variable, or updates an existing one.
482+
*
483+
* @param {String} key - The name of the variable to set.
484+
* @param {*} value - The value of the variable to be set.
485+
*/
486+
set (key, value) {
487+
var variable = this.values.oneNormalizedVariable(key),
488+
489+
// create an object that will be used as setter
490+
update = { key, value };
491+
492+
493+
// If a variable by the name key exists, update it's value and return.
494+
// @note adds new variable if existing is disabled. Disabled variables are not updated.
495+
if (variable && !variable.disabled) {
496+
variable.update(update);
497+
}
498+
else {
499+
this.values.add(update);
500+
}
501+
502+
// track the change if mutation tracking is enabled
503+
if (this._postman_enableTracking) {
504+
// eslint-disable-next-line security/detect-possible-timing-attacks
505+
this.mutations.track(MUTATIONS.SET, key, value);
506+
}
507+
}
508+
}
509+
466510
module.exports = {
467-
VariableScope
511+
VariableScope,
512+
CollectionVariableScope
468513
};

lib/collection/variable.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,27 @@ _.assign(Variable, /** @lends Variable */ {
355355
return val; // pass through
356356
},
357357

358+
/**
359+
* @param {*} val -
360+
* @returns {*}
361+
*/
362+
out (val) {
363+
return val; // pass through
364+
}
365+
},
366+
367+
/**
368+
* A "secret" type value stores data as postman secret variables
369+
*/
370+
secret: {
371+
/**
372+
* @param {*} val -
373+
* @returns {*}
374+
*/
375+
in (val) {
376+
return val; // pass through
377+
},
378+
358379
/**
359380
* @param {*} val -
360381
* @returns {*}

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module.exports = {
2828
Variable: require('./collection/variable').Variable,
2929
VariableList: require('./collection/variable-list').VariableList,
3030
VariableScope: require('./collection/variable-scope').VariableScope,
31+
CollectionVariableScope: require('./collection/variable-scope').CollectionVariableScope,
3132
ProxyConfig: require('./collection/proxy-config').ProxyConfig,
3233
ProxyConfigList: require('./collection/proxy-config-list').ProxyConfigList,
3334
Version: require('./collection/version').Version

test/unit/mutation-tracker.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ describe('MutationTracker', function () {
163163
it('should not track invalid mutation format', function () {
164164
var tracker = new MutationTracker();
165165

166-
// expected signature is two parameters
167-
tracker.track('set', 'foo', 'bar', 'baz');
166+
// expected signature is three parameters
167+
tracker.track('set', 'foo', 'bar', 'secret', 'baz');
168168

169169
expect(tracker.count()).to.eql(0);
170170
});

test/unit/variable-scope.test.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,30 @@ describe('VariableScope', function () {
13151315
expect(scope.mutations.count()).to.equal(1);
13161316
});
13171317

1318+
it('should track set operations with datatype when datatype is secret', function () {
1319+
var scope = new VariableScope();
1320+
1321+
scope.enableTracking();
1322+
1323+
scope.set('foo', 'bar', 'secret');
1324+
1325+
expect(scope).to.have.property('mutations');
1326+
expect(scope.mutations.count()).to.equal(1);
1327+
expect(scope.mutations.stream[0].length).to.equal(3);
1328+
});
1329+
1330+
it('should track set operations without datatype when datatype other than secret', function () {
1331+
var scope = new VariableScope();
1332+
1333+
scope.enableTracking();
1334+
1335+
scope.set('foo', 'bar', 'string');
1336+
1337+
expect(scope).to.have.property('mutations');
1338+
expect(scope.mutations.count()).to.equal(1);
1339+
expect(scope.mutations.stream[0].length).to.equal(2);
1340+
});
1341+
13181342
it('should track unset operations', function () {
13191343
var scope = new VariableScope({
13201344
values: [{
@@ -1379,6 +1403,34 @@ describe('VariableScope', function () {
13791403
expect(scope1.values).to.eql(scope2.values);
13801404
});
13811405

1406+
it('should be capable of being replayed with secret datatype', function () {
1407+
var initialState = {
1408+
values: [{
1409+
key: 'foo',
1410+
value: 'foo'
1411+
}, {
1412+
key: 'bar',
1413+
value: 'bar'
1414+
}]
1415+
},
1416+
scope1 = new VariableScope(initialState),
1417+
scope2 = new VariableScope(initialState);
1418+
1419+
scope1.enableTracking();
1420+
1421+
// add a new key
1422+
scope1.set('baz', 'baz', 'secret');
1423+
// update a key
1424+
scope1.set('foo', 'foo updated', 'secret');
1425+
// remove a key
1426+
scope1.unset('bar');
1427+
1428+
// replay mutations on a different object
1429+
scope1.mutations.applyOn(scope2);
1430+
1431+
expect(scope1.values).to.eql(scope2.values);
1432+
});
1433+
13821434
it('should be serialized', function () {
13831435
var scope = new VariableScope(),
13841436
serialized,

test/unit/variable.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ describe('Variable', function () {
128128
});
129129
});
130130

131+
it('should prepopulate value and type when passed to the constructor (secret)', function () {
132+
let v = new Variable({
133+
value: 'Picard',
134+
type: 'secret'
135+
});
136+
137+
expect(v).to.deep.include({
138+
value: 'Picard',
139+
type: 'secret'
140+
});
141+
});
142+
131143
it('should typecast value during construction when type is provided (number)', function () {
132144
var v = new Variable({
133145
value: '108',
@@ -227,6 +239,20 @@ describe('Variable', function () {
227239
expect(v.get()).to.equal(jsonValue);
228240
});
229241

242+
it('should support any data type if type is set to `secret`', function () {
243+
var v = new Variable({ type: 'secret' }),
244+
jsonValue = { iam: 'json' };
245+
246+
v.set('Picard');
247+
expect(v.get()).to.equal('Picard');
248+
249+
v.set(3.142);
250+
expect(v.get()).to.equal(3.142);
251+
252+
v.set(jsonValue);
253+
expect(v.get()).to.equal(jsonValue);
254+
});
255+
230256
it('should type cast values to the specific type set', function () {
231257
var v = new Variable({
232258
type: 'string'

types/index.d.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Type definitions for postman-collection 4.0.2
1+
// Type definitions for postman-collection 4.2.1
22
// Project: https://github.com/postmanlabs/postman-collection
33
// Definitions by: PostmanLabs
44
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
@@ -2365,7 +2365,7 @@ declare module "postman-collection" {
23652365
* @param value - The value of the variable to be set.
23662366
* @param [type] - Optionally, the value of the variable can be set to a type
23672367
*/
2368-
set(key: string, value: any, type?: Variable.types): void;
2368+
set(key: string, value: any, type?: 'secret' | 'default'): void;
23692369
/**
23702370
* Removes the variable with the specified name.
23712371
* @param key - -
@@ -2402,6 +2402,18 @@ declare module "postman-collection" {
24022402
static isVariableScope(obj: any): boolean;
24032403
}
24042404

2405+
/**
2406+
* CollectionVariableScope are the variable scope that are defined at the collection level.
2407+
*/
2408+
export class CollectionVariableScope {
2409+
/**
2410+
* Creates a new variable, or updates an existing one.
2411+
* @param key - The name of the variable to set.
2412+
* @param value - The value of the variable to be set.
2413+
*/
2414+
set(key: string, value: any): void;
2415+
}
2416+
24052417
export namespace Variable {
24062418
/**
24072419
* The object representation of a Variable consists the variable value and type. It also optionally includes the `id`
@@ -2456,7 +2468,11 @@ declare module "postman-collection" {
24562468
* Free-form type of a value. This is the default for any variable, unless specified otherwise. It ensures that
24572469
* the variable can store data in any type and no conversion is done while using Variable.get.
24582470
*/
2459-
any = "{\"in\":\"\",\"out\":\"\"}"
2471+
any = "{\"in\":\"\",\"out\":\"\"}",
2472+
/**
2473+
* A "secret" type value stores data as postman secret variables
2474+
*/
2475+
secret = "{\"in\":\"\",\"out\":\"\"}"
24602476
}
24612477
}
24622478

0 commit comments

Comments
 (0)