Skip to content

Commit

Permalink
fix: secret function (#3707)
Browse files Browse the repository at this point in the history
  • Loading branch information
kobenguyent committed Jun 30, 2023
1 parent cf714ec commit a5f0a4b
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 18 deletions.
8 changes: 4 additions & 4 deletions docs/helpers/REST.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ I.sendDeleteRequest('/api/users/1');
#### Parameters

- `url` **any**
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
- `headers` **[object][4]** the headers object to be sent. By default, it is sent as an empty object

Returns **[Promise][2]<any>** response

Expand All @@ -130,7 +130,7 @@ I.sendGetRequest('/api/users.json');
#### Parameters

- `url` **any**
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
- `headers` **[object][4]** the headers object to be sent. By default, it is sent as an empty object

Returns **[Promise][2]<any>** response

Expand Down Expand Up @@ -167,8 +167,8 @@ I.sendPostRequest('/api/users.json', secret({ "email": "[email protected]" }));
#### Parameters

- `url` **any**
- `payload` **any** the payload to be sent. By default it is sent as an empty object
- `headers` **[object][4]** the headers object to be sent. By default it is sent as an empty object
- `payload` **any** the payload to be sent. By default, it is sent as an empty object
- `headers` **[object][4]** the headers object to be sent. By default, it is sent as an empty object

Returns **[Promise][2]<any>** response

Expand Down
17 changes: 13 additions & 4 deletions lib/helper/REST.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ class REST extends Helper {
request.auth = this.headers.auth;
}

if (typeof request.data === 'object') {
const returnedValue = {};
for (const [key, value] of Object.entries(request.data)) {
returnedValue[key] = value;
if (value instanceof Secret) returnedValue[key] = value.getMasked();
}
_debugRequest.data = returnedValue;
}

if (request.data instanceof Secret) {
_debugRequest.data = '*****';
request.data = (typeof request.data === 'object' && !(request.data instanceof Secret)) ? { ...request.data.toString() } : request.data.toString();
Expand Down Expand Up @@ -199,7 +208,7 @@ class REST extends Helper {
* ```
*
* @param {*} url
* @param {object} [headers={}] - the headers object to be sent. By default it is sent as an empty object
* @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
*
* @returns {Promise<*>} response
*/
Expand All @@ -223,8 +232,8 @@ class REST extends Helper {
* ```
*
* @param {*} url
* @param {*} [payload={}] - the payload to be sent. By default it is sent as an empty object
* @param {object} [headers={}] - the headers object to be sent. By default it is sent as an empty object
* @param {*} [payload={}] - the payload to be sent. By default, it is sent as an empty object
* @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
*
* @returns {Promise<*>} response
*/
Expand Down Expand Up @@ -318,7 +327,7 @@ class REST extends Helper {
* ```
*
* @param {*} url
* @param {object} [headers={}] - the headers object to be sent. By default it is sent as an empty object
* @param {object} [headers={}] - the headers object to be sent. By default, it is sent as an empty object
*
* @returns {Promise<*>} response
*/
Expand Down
9 changes: 5 additions & 4 deletions lib/secret.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable max-classes-per-file */
const { deepClone } = require('./utils');

const maskedString = '*****';

/** @param {string} secret */
class Secret {
constructor(secret) {
Expand All @@ -13,7 +15,7 @@ class Secret {
}

getMasked() {
return '*****';
return maskedString;
}

/**
Expand All @@ -36,12 +38,11 @@ function secretObject(obj, fieldsToHide = []) {
if (prop === 'toString') {
return function () {
const maskedObject = deepClone(obj);
fieldsToHide.forEach(f => maskedObject[f] = '****');
fieldsToHide.forEach(f => maskedObject[f] = maskedString);
return JSON.stringify(maskedObject);
};
}

return obj[prop];
return fieldsToHide.includes(prop) ? new Secret(obj[prop]) : obj[prop];
},
};

Expand Down
7 changes: 6 additions & 1 deletion lib/step.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,12 @@ class Step {
} else if (arg.toString && arg.toString() !== '[object Object]') {
return arg.toString();
} else if (typeof arg === 'object') {
return JSON.stringify(arg);
const returnedArg = {};
for (const [key, value] of Object.entries(arg)) {
returnedArg[key] = value;
if (value instanceof Secret) returnedArg[key] = value.getMasked();
}
return JSON.stringify(returnedArg);
}
return arg;
}).join(', ');
Expand Down
11 changes: 6 additions & 5 deletions test/rest/REST_test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const path = require('path');
const expect = require('expect');
const fs = require('fs');
const FormData = require('form-data');
const { secret } = require('../../lib/secret');

const TestHelper = require('../support/TestHelper');
const REST = require('../../lib/helper/REST');
const Container = require('../../lib/container');
const Secret = require("../../lib/secret");

const api_url = TestHelper.jsonServerUrl();
global.codeceptjs = require('../../lib');
Expand Down Expand Up @@ -71,15 +72,15 @@ describe('REST', () => {
});

it('should send POST requests with secret', async () => {
const secretData = secret({ name: 'john', password: '123456' }, 'password');
const secretData = Secret.secret({ name: 'john', password: '123456' }, 'password');
const response = await I.sendPostRequest('/user', secretData);
response.data.name.should.eql('john');
response.data.password.should.eql('123456');
secretData.toString().should.include('"password":"****"');
expect(response.data.password).toEqual({ _secret: '123456' });
expect(secretData.password.getMasked()).toEqual('*****');
});

it('should send POST requests with secret form encoded is not converted to string', async () => {
const secretData = secret('name=john&password=123456');
const secretData = Secret.secret('name=john&password=123456');
const response = await I.sendPostRequest('/user', secretData);
response.data.name.should.eql('john');
response.data.password.should.eql('123456');
Expand Down
19 changes: 19 additions & 0 deletions test/unit/secret_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const expect = require('expect');
const Secret = require('../../lib/secret');

describe('Secret tests', () => {
it('should be the Secret instance', () => {
const string = Secret.secret('hello');
expect(string).toBeInstanceOf(Secret);
});

it('should be the Secret instance when using as object', () => {
const obj = Secret.secret({ password: 'world' }, 'password');
expect(obj.password).toBeInstanceOf(Secret);
});

it('should mask the field when provided', () => {
const obj = Secret.secret({ password: 'world' }, 'password');
expect(obj.password.getMasked()).toBe('*****');
});
});

0 comments on commit a5f0a4b

Please sign in to comment.