strapi-utils
Advanced tools
Comparing version 3.1.5 to 3.1.6
'use strict'; | ||
const _ = require('lodash'); | ||
const sanitizeEntity = require('../sanitize-entity'); | ||
const { sanitizeEntity } = require('../sanitize-entity'); | ||
describe('Sanitize Entity', () => { | ||
const input = { | ||
id: 1, | ||
email: 'foo@bar.com', | ||
@@ -106,7 +107,12 @@ firstname: 'foo', | ||
global.strapi = { | ||
getModel(name) { | ||
return models[name]; | ||
}, | ||
}; | ||
beforeEach(() => { | ||
global.strapi = { | ||
getModel(name) { | ||
return models[name]; | ||
}, | ||
config: { | ||
get: jest.fn, | ||
}, | ||
}; | ||
}); | ||
@@ -117,3 +123,3 @@ describe('Basic', () => { | ||
{ withPrivate: false, isOutput: true, includeFields: null }, | ||
_.pick(input, ['firstname', 'lastname']), | ||
_.pick(input, ['id', 'firstname', 'lastname']), | ||
], | ||
@@ -123,12 +129,12 @@ [{ withPrivate: false, isOutput: false, includeFields: null }, input], | ||
{ withPrivate: false, isOutput: true, includeFields: ['firstname'] }, | ||
_.pick(input, ['firstname']), | ||
_.pick(input, ['id', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: false, isOutput: true, includeFields: ['email', 'firstname'] }, | ||
_.pick(input, ['firstname']), | ||
_.pick(input, ['id', 'firstname']), | ||
], | ||
[{ withPrivate: false, isOutput: true, includeFields: ['password'] }, {}], | ||
[{ withPrivate: false, isOutput: true, includeFields: ['password'] }, _.pick(input, ['id'])], | ||
[ | ||
{ withPrivate: true, isOutput: true, includeFields: null }, | ||
_.pick(input, ['email', 'firstname', 'lastname']), | ||
_.pick(input, ['id', 'email', 'firstname', 'lastname']), | ||
], | ||
@@ -138,20 +144,20 @@ [{ withPrivate: true, isOutput: false, includeFields: null }, input], | ||
{ withPrivate: true, isOutput: true, includeFields: ['firstname'] }, | ||
_.pick(input, ['firstname']), | ||
_.pick(input, ['id', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: true, isOutput: true, includeFields: ['email', 'firstname'] }, | ||
_.pick(input, ['email', 'firstname']), | ||
_.pick(input, ['id', 'email', 'firstname']), | ||
], | ||
[{ withPrivate: true, isOutput: true, includeFields: ['password'] }, {}], | ||
[{ withPrivate: true, isOutput: true, includeFields: ['password'] }, _.pick(input, ['id'])], | ||
[ | ||
{ withPrivate: true, isOutput: false, includeFields: ['firstname'] }, | ||
_.pick(input, ['firstname']), | ||
_.pick(input, ['id', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: true, isOutput: false, includeFields: ['email', 'firstname'] }, | ||
_.pick(input, ['email', 'firstname']), | ||
_.pick(input, ['id', 'email', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: true, isOutput: false, includeFields: ['password'] }, | ||
_.pick(input, ['password']), | ||
_.pick(input, ['id', 'password']), | ||
], | ||
@@ -166,2 +172,60 @@ ]; | ||
describe('With private attributes', () => { | ||
describe('When options.privateAttributes exists in model, the attributes in options.privateAttributes must be hidden', () => { | ||
const tests = [ | ||
[{ withPrivate: false, isOutput: true, includeFields: null }, _.pick(input, ['lastname'])], | ||
[{ withPrivate: false, isOutput: false, includeFields: null }, input], | ||
[{ withPrivate: false, isOutput: true, includeFields: ['firstname'] }, {}], | ||
[{ withPrivate: false, isOutput: true, includeFields: ['email', 'firstname'] }, {}], | ||
[{ withPrivate: false, isOutput: true, includeFields: ['password'] }, {}], | ||
[ | ||
{ withPrivate: true, isOutput: true, includeFields: null }, | ||
_.pick(input, ['id', 'email', 'firstname', 'lastname']), | ||
], | ||
[{ withPrivate: true, isOutput: false, includeFields: null }, input], | ||
[ | ||
{ withPrivate: true, isOutput: true, includeFields: ['firstname'] }, | ||
_.pick(input, ['id', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: true, isOutput: true, includeFields: ['email', 'firstname'] }, | ||
_.pick(input, ['id', 'email', 'firstname']), | ||
], | ||
[{ withPrivate: true, isOutput: true, includeFields: ['password'] }, _.pick(input, ['id'])], | ||
[ | ||
{ withPrivate: true, isOutput: false, includeFields: ['firstname'] }, | ||
_.pick(input, ['id', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: true, isOutput: false, includeFields: ['email', 'firstname'] }, | ||
_.pick(input, ['id', 'email', 'firstname']), | ||
], | ||
[ | ||
{ withPrivate: true, isOutput: false, includeFields: ['password'] }, | ||
_.pick(input, ['id', 'password']), | ||
], | ||
]; | ||
const model = { | ||
...models.user, | ||
options: { | ||
...models.user.options, | ||
privateAttributes: ['firstname'], | ||
}, | ||
}; | ||
test.each(tests)(`Test n°%#`, (options, expected) => { | ||
global.strapi = { | ||
config: { | ||
get: jest.fn(path => { | ||
return path === 'api.responses.privateAttributes' ? ['id'] : []; | ||
}), | ||
}, | ||
}; | ||
expect(sanitizeEntity(input, { ...options, model })).toStrictEqual(expected); | ||
}); | ||
}); | ||
}); | ||
describe('With relation', () => { | ||
@@ -172,6 +236,9 @@ const tests = [ | ||
{ withPrivate: false, isOutput: true, includeFields: null }, | ||
{ | ||
..._.pick(inputWithRelation, ['firstname', 'lastname']), | ||
article: _.pick(inputWithRelation.article, ['name', 'content']), | ||
}, | ||
_.pick(inputWithRelation, [ | ||
'id', | ||
'firstname', | ||
'lastname', | ||
'article.name', | ||
'article.content', | ||
]), | ||
], | ||
@@ -181,3 +248,3 @@ [ | ||
{ withPrivate: false, isOutput: true, includeFields: ['firstname', 'lastname'] }, | ||
_.pick(inputWithRelation, ['firstname', 'lastname']), | ||
_.pick(inputWithRelation, ['id', 'firstname', 'lastname']), | ||
], | ||
@@ -187,5 +254,3 @@ [ | ||
{ withPrivate: false, isOutput: true, includeFields: ['article'] }, | ||
{ | ||
article: _.pick(inputWithRelation.article, ['name', 'content']), | ||
}, | ||
_.pick(inputWithRelation, ['id', 'article.name', 'article.content']), | ||
], | ||
@@ -195,3 +260,3 @@ [ | ||
{ withPrivate: false, isOutput: true, includeFields: ['article.name'] }, | ||
_.pick(inputWithRelation, ['article.name']), | ||
_.pick(inputWithRelation, ['id', 'article.name']), | ||
], | ||
@@ -201,3 +266,3 @@ [ | ||
{ withPrivate: true, isOutput: true, includeFields: null }, | ||
_.pick(inputWithRelation, ['email', 'firstname', 'lastname', 'article']), | ||
_.pick(inputWithRelation, ['id', 'email', 'firstname', 'lastname', 'article']), | ||
], | ||
@@ -208,3 +273,3 @@ [ | ||
{ | ||
..._.pick(inputWithRelation, 'firstname', 'lastname'), | ||
..._.pick(inputWithRelation, ['id', 'firstname', 'lastname']), | ||
article: _.times(3, () => _.pick(article, ['name', 'content'])), | ||
@@ -226,3 +291,3 @@ }, | ||
const expected = _.pick(dataSource, ['firstname', 'lastname', 'dz']); | ||
const expected = _.pick(dataSource, ['id', 'firstname', 'lastname', 'dz']); | ||
@@ -236,3 +301,3 @@ expect(sanitizeEntity(dataSource, { model })).toStrictEqual(expected); | ||
const expected = { | ||
..._.pick(inputWithDz, ['firstname', 'lastname']), | ||
..._.pick(inputWithDz, ['id', 'firstname', 'lastname']), | ||
dz: inputWithDz.dz.map(comp => _.pick(comp, ['__component', 'name', 'content'])), | ||
@@ -262,4 +327,4 @@ }; | ||
const expected = [ | ||
_.pick(input, 'firstname', 'lastname'), | ||
_.pick(input, 'firstname', 'lastname'), | ||
_.pick(input, 'id', 'firstname', 'lastname'), | ||
_.pick(input, 'id', 'firstname', 'lastname'), | ||
]; | ||
@@ -266,0 +331,0 @@ |
@@ -9,3 +9,3 @@ 'use strict'; | ||
const parseMultipartData = require('./parse-multipart'); | ||
const sanitizeEntity = require('./sanitize-entity'); | ||
const { sanitizeEntity, getPrivateAttributes } = require('./sanitize-entity'); | ||
const parseType = require('./parse-type'); | ||
@@ -44,2 +44,3 @@ const finder = require('./finder'); | ||
sanitizeEntity, | ||
getPrivateAttributes, | ||
parseType, | ||
@@ -46,0 +47,0 @@ nameToSlug, |
@@ -33,3 +33,3 @@ 'use strict'; | ||
if (shouldRemoveAttribute(attribute, { withPrivate, isOutput })) { | ||
if (shouldRemoveAttribute(model, key, attribute, { withPrivate, isOutput })) { | ||
return acc; | ||
@@ -124,9 +124,16 @@ } | ||
const shouldRemoveAttribute = (attribute, { withPrivate, isOutput }) => { | ||
if (_.isNil(attribute)) { | ||
return false; | ||
} | ||
const getPrivateAttributes = model => { | ||
const allPrivatesAttributes = _.union( | ||
strapi.config.get('api.responses.privateAttributes', []), | ||
_.get(model, 'options.privateAttributes', []) | ||
); | ||
return allPrivatesAttributes; | ||
}; | ||
const shouldRemoveAttribute = (model, key, attribute = {}, { withPrivate, isOutput }) => { | ||
const privateAttributes = getPrivateAttributes(model); | ||
const isPassword = attribute.type === 'password'; | ||
const isPrivate = attribute.private === true; | ||
const isPrivate = attribute.private === true || privateAttributes.includes(key); | ||
@@ -139,2 +146,5 @@ const shouldRemovePassword = isOutput; | ||
module.exports = sanitizeEntity; | ||
module.exports = { | ||
sanitizeEntity, | ||
getPrivateAttributes, | ||
}; |
{ | ||
"name": "strapi-utils", | ||
"version": "3.1.5", | ||
"version": "3.1.6", | ||
"description": "Shared utilities for the Strapi packages", | ||
@@ -44,7 +44,7 @@ "homepage": "http://strapi.io", | ||
"engines": { | ||
"node": ">=10.10.0 <13", | ||
"node": ">=10.16.0 <13", | ||
"npm": ">=6.0.0" | ||
}, | ||
"license": "SEE LICENSE IN LICENSE", | ||
"gitHead": "736a580001cd6f0d94ff2d5a930554f6d42e0477" | ||
"gitHead": "3c7c33eab7bc35c60237646b41699b991fb62ff0" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
1
80287
28
2362