Socket
Socket
Sign inDemoInstall

strapi-utils

Package Overview
Dependencies
Maintainers
8
Versions
282
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

strapi-utils - npm Package Compare versions

Comparing version 3.2.0-beta.0 to 3.2.0-beta.1

109

lib/__tests__/content-types.test.js
'use strict';
const { getVisibleAttributes, getNonWritableAttributes, constants } = require('../content-types');
const {
isPrivateAttribute,
getPrivateAttributes,
getVisibleAttributes,
getNonWritableAttributes,
constants,
} = require('../content-types');
const createModelWithPrivates = (privateAttributes = []) => ({
options: {
privateAttributes,
},
attributes: {
foo: {
type: 'string',
private: true,
},
bar: {
type: 'number',
private: false,
},
foobar: {
type: 'string',
},
},
});
const createConfig = (privateAttributes = []) => ({
get: jest.fn(() => privateAttributes),
});
const createModel = opts => ({

@@ -11,2 +40,6 @@ primaryKey: 'id',

describe('Content types utils', () => {
beforeEach(() => {
jest.resetAllMocks();
});
test('Verify constants exist', () => {

@@ -30,3 +63,2 @@ expect(constants.CREATED_BY_ATTRIBUTE).toBeDefined();

'id',
constants.PUBLISHED_AT_ATTRIBUTE,
constants.CREATED_BY_ATTRIBUTE,

@@ -153,2 +185,75 @@ constants.UPDATED_BY_ATTRIBUTE,

});
describe('getPrivateAttributes', () => {
test('Attribute is private in the model attributes', () => {
const model = createModelWithPrivates();
global.strapi = { config: createConfig() };
const privateAttributes = getPrivateAttributes(model);
expect(privateAttributes).toContain('foo');
expect(privateAttributes).not.toContain('bar');
expect(privateAttributes).not.toContain('foobar');
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
test('Attribute is set to private in the app config', () => {
const model = createModelWithPrivates();
global.strapi = { config: createConfig(['bar']) };
const privateAttributes = getPrivateAttributes(model);
expect(privateAttributes).toContain('foo');
expect(privateAttributes).toContain('bar');
expect(privateAttributes).not.toContain('foobar');
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
test('Attribute is set to private in the model options', () => {
const model = createModelWithPrivates(['foobar']);
global.strapi = { config: createConfig() };
const privateAttributes = getPrivateAttributes(model);
expect(privateAttributes).toContain('foo');
expect(privateAttributes).not.toContain('bar');
expect(privateAttributes).toContain('foobar');
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
});
describe('isPrivateAttribute', () => {
test('Attribute is private in the model attributes', () => {
const model = createModelWithPrivates();
global.strapi = { config: createConfig() };
Object.assign(model, { privateAttributes: getPrivateAttributes(model) });
expect(isPrivateAttribute(model, 'foo')).toBeTruthy();
expect(isPrivateAttribute(model, 'bar')).toBeFalsy();
expect(isPrivateAttribute(model, 'foobar')).toBeFalsy();
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
test('Attribute is set to private in the app config', () => {
const model = createModelWithPrivates();
global.strapi = { config: createConfig(['bar']) };
Object.assign(model, { privateAttributes: getPrivateAttributes(model) });
expect(isPrivateAttribute(model, 'foo')).toBeTruthy();
expect(isPrivateAttribute(model, 'bar')).toBeTruthy();
expect(isPrivateAttribute(model, 'foobar')).toBeFalsy();
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
test('Attribute is set to private in the model options', () => {
const model = createModelWithPrivates(['foobar']);
global.strapi = { config: createConfig() };
Object.assign(model, { privateAttributes: getPrivateAttributes(model) });
expect(isPrivateAttribute(model, 'foo')).toBeTruthy();
expect(isPrivateAttribute(model, 'bar')).toBeFalsy();
expect(isPrivateAttribute(model, 'foobar')).toBeTruthy();
expect(strapi.config.get).toHaveBeenCalledWith('api.responses.privateAttributes', []);
});
});
});

122

lib/__tests__/sanitize-entity.test.js

@@ -8,2 +8,3 @@ 'use strict';

const input = {
id: 1,
email: 'foo@bar.com',

@@ -43,2 +44,3 @@ firstname: 'foo',

},
privateAttributes: ['email'],
attributes: {

@@ -87,2 +89,3 @@ email: {

},
privateAttributes: ['secret'],
attributes: {

@@ -109,7 +112,12 @@ name: {

global.strapi = {
getModel(name) {
return models[name];
},
};
beforeEach(() => {
global.strapi = {
getModel(name) {
return models[name];
},
config: {
get: jest.fn,
},
};
});

@@ -120,3 +128,3 @@ describe('Basic', () => {

{ withPrivate: false, isOutput: true, includeFields: null },
_.pick(input, ['firstname', 'lastname']),
_.pick(input, ['id', 'firstname', 'lastname']),
],

@@ -126,12 +134,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']),
],

@@ -141,20 +149,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']),
],

@@ -169,2 +177,53 @@ ];

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'],
},
privateAttributes: [].concat(models.user.privateAttributes, ['firstname'], ['id']),
};
test.each(tests)(`Test n°%#`, (options, expected) => {
expect(sanitizeEntity(input, { ...options, model })).toStrictEqual(expected);
});
});
});
describe('With relation', () => {

@@ -175,6 +234,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',
]),
],

@@ -184,3 +246,3 @@ [

{ withPrivate: false, isOutput: true, includeFields: ['firstname', 'lastname'] },
_.pick(inputWithRelation, ['firstname', 'lastname']),
_.pick(inputWithRelation, ['id', 'firstname', 'lastname']),
],

@@ -190,5 +252,3 @@ [

{ withPrivate: false, isOutput: true, includeFields: ['article'] },
{
article: _.pick(inputWithRelation.article, ['name', 'content']),
},
_.pick(inputWithRelation, ['id', 'article.name', 'article.content']),
],

@@ -198,3 +258,3 @@ [

{ withPrivate: false, isOutput: true, includeFields: ['article.name'] },
_.pick(inputWithRelation, ['article.name']),
_.pick(inputWithRelation, ['id', 'article.name']),
],

@@ -204,3 +264,3 @@ [

{ withPrivate: true, isOutput: true, includeFields: null },
_.pick(inputWithRelation, ['email', 'firstname', 'lastname', 'article']),
_.pick(inputWithRelation, ['id', 'email', 'firstname', 'lastname', 'article']),
],

@@ -211,3 +271,3 @@ [

{
..._.pick(inputWithRelation, 'firstname', 'lastname'),
..._.pick(inputWithRelation, ['id', 'firstname', 'lastname']),
article: _.times(3, () => _.pick(article, ['name', 'content'])),

@@ -229,3 +289,3 @@ },

const expected = _.pick(dataSource, ['firstname', 'lastname', 'dz']);
const expected = _.pick(dataSource, ['id', 'firstname', 'lastname', 'dz']);

@@ -239,3 +299,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'])),

@@ -265,4 +325,4 @@ };

const expected = [
_.pick(input, 'firstname', 'lastname'),
_.pick(input, 'firstname', 'lastname'),
_.pick(input, 'id', 'firstname', 'lastname'),
_.pick(input, 'id', 'firstname', 'lastname'),
];

@@ -269,0 +329,0 @@

@@ -13,12 +13,5 @@ 'use strict';

const HIDDEN_ATTRIBUTES = [
ID_ATTRIBUTE,
PUBLISHED_AT_ATTRIBUTE,
CREATED_BY_ATTRIBUTE,
UPDATED_BY_ATTRIBUTE,
];
const NON_WRITABLE_ATTRIBUTES = [ID_ATTRIBUTE, CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE];
const NON_VISIBLE_ATTRIBUTES = [...NON_WRITABLE_ATTRIBUTES, PUBLISHED_AT_ATTRIBUTE];
// making it clear hidden attributes could still be writable
const NON_WRITABLE_ATTRIBUTES = [...HIDDEN_ATTRIBUTES];
const constants = {

@@ -56,3 +49,3 @@ ID_ATTRIBUTE,

const getNonVisibleAttributes = model => {
return _.uniq([model.primaryKey, ...getTimestamps(model), ...HIDDEN_ATTRIBUTES]);
return _.uniq([model.primaryKey, ...getTimestamps(model), ...NON_VISIBLE_ATTRIBUTES]);
};

@@ -69,5 +62,20 @@

const getPrivateAttributes = (model = {}) => {
return _.union(
strapi.config.get('api.responses.privateAttributes', []),
_.get(model, 'options.privateAttributes', []),
_.keys(_.pickBy(model.attributes, attr => !!attr.private))
);
};
const isPrivateAttribute = (model = {}, attributeName) => {
return model.privateAttributes.includes(attributeName);
};
module.exports = {
getPrivateAttributes,
isPrivateAttribute,
constants,
getNonWritableAttributes,
getNonVisibleAttributes,
getVisibleAttributes,

@@ -74,0 +82,0 @@ hasDraftAndPublish,

'use strict';
const _ = require('lodash');
const { constants } = require('./content-types');
const { constants, isPrivateAttribute } = require('./content-types');
const {

@@ -40,3 +40,3 @@ ID_ATTRIBUTE,

if (shouldRemoveAttribute(attribute, { withPrivate, isOutput })) {
if (shouldRemoveAttribute(model, key, attribute, { withPrivate, isOutput })) {
return acc;

@@ -138,9 +138,5 @@ }

const shouldRemoveAttribute = (attribute, { withPrivate, isOutput }) => {
if (_.isNil(attribute)) {
return false;
}
const shouldRemoveAttribute = (model, key, attribute = {}, { withPrivate, isOutput }) => {
const isPassword = attribute.type === 'password';
const isPrivate = attribute.private === true;
const isPrivate = isPrivateAttribute(model, key);

@@ -147,0 +143,0 @@ const shouldRemovePassword = isOutput;

{
"name": "strapi-utils",
"version": "3.2.0-beta.0",
"version": "3.2.0-beta.1",
"description": "Shared utilities for the Strapi packages",

@@ -48,3 +48,3 @@ "homepage": "http://strapi.io",

"license": "SEE LICENSE IN LICENSE",
"gitHead": "90761175f6a0f3a36d9742f3e169cc0cc8068972"
"gitHead": "fcb2878987cbb6b78b55a14b8370f1d348bf33f7"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc