Merge pull request #17887 from strapi/feature/test-content-api-sanitization

This commit is contained in:
Jamie Howard 2023-09-08 14:52:43 +01:00 committed by GitHub
commit c0a61c7e40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 21 deletions

View File

@ -74,14 +74,21 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
return body; return body;
}; };
const updateContentType = async (uid, data) => { /**
const result = await requests.admin({ * Create a full access token to authenticate the content API with
method: 'PUT', */
url: `/content-type-builder/content-types/${uid}`, const getFullAccessToken = async () => {
body: data, const res = await requests.admin.post('/admin/api-tokens', {
body: {
lifespan: null,
description: '',
type: 'full-access',
name: 'Full Access',
permissions: null,
},
}); });
expect(result.statusCode).toBe(201); return res.body.data.accessKey;
}; };
beforeAll(async () => { beforeAll(async () => {
@ -89,9 +96,9 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
// eslint-disable-next-line node/no-extraneous-require // eslint-disable-next-line node/no-extraneous-require
hasRW = require('@strapi/strapi/lib/utils/ee').features.isEnabled('review-workflows'); hasRW = require('@strapi/strapi/lib/utils/ee').features.isEnabled('review-workflows');
strapi = await createStrapiInstance(); strapi = await createStrapiInstance({ bypassAuth: false });
requests.public = createRequest({ strapi });
requests.admin = await createAuthRequest({ strapi }); requests.admin = await createAuthRequest({ strapi });
requests.public = createRequest({ strapi }).setToken(await getFullAccessToken());
defaultStage = await strapi.query(STAGE_MODEL_UID).create({ defaultStage = await strapi.query(STAGE_MODEL_UID).create({
data: { name: 'Stage' }, data: { name: 'Stage' },
@ -509,6 +516,7 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
test('Should update the assignee on an entity', async () => { test('Should update the assignee on an entity', async () => {
const entry = await createEntry(productUID, { name: 'Product' }); const entry = await createEntry(productUID, { name: 'Product' });
const user = requests.admin.getLoggedUser(); const user = requests.admin.getLoggedUser();
const response = await requests.admin({ const response = await requests.admin({
method: 'PUT', method: 'PUT',
url: `/admin/content-manager/collection-types/${productUID}/${entry.id}/assignee`, url: `/admin/content-manager/collection-types/${productUID}/${entry.id}/assignee`,
@ -538,6 +546,34 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
expect(response.body.error.name).toEqual('ApplicationError'); expect(response.body.error.name).toEqual('ApplicationError');
expect(response.body.error.message).toEqual('Selected user does not exist'); expect(response.body.error.message).toEqual('Selected user does not exist');
}); });
test('Correctly sanitize private fields of assignees in the content API', async () => {
const assigneeAttribute = 'strapi_assignee';
const { status, body } = await requests.public.get(`/api/${model.pluralName}`, {
qs: { populate: assigneeAttribute },
});
expect(status).toBe(200);
const privateUserFields = [
'password',
'email',
'resetPasswordToken',
'registrationToken',
'isActive',
'roles',
'blocked',
];
// Assert that every assignee returned is sanitized correctly
body.data.forEach((item) => {
expect(item.attributes).toHaveProperty(assigneeAttribute);
privateUserFields.forEach((field) => {
expect(item.attributes[assigneeAttribute]).not.toHaveProperty(field);
});
});
});
}); });
describe('Review Workflow is disabled', () => { describe('Review Workflow is disabled', () => {

View File

@ -11,7 +11,7 @@ const builder = createTestBuilder();
let strapi; let strapi;
let file; let file;
let rq; let contentAPIRequest;
const schemas = { const schemas = {
contentTypes: { contentTypes: {
@ -85,9 +85,9 @@ const fixtures = {
const uploadFile = async () => { const uploadFile = async () => {
const strapi = await createStrapiInstance(); const strapi = await createStrapiInstance();
const rq = await createAuthRequest({ strapi }); const request = await createAuthRequest({ strapi });
const res = await rq({ const res = await request({
method: 'POST', method: 'POST',
url: '/upload', url: '/upload',
formData: { formData: {
@ -113,7 +113,7 @@ describe('Sanitize populated entries', () => {
.build(); .build();
strapi = await createStrapiInstance(); strapi = await createStrapiInstance();
rq = createContentAPIRequest({ strapi }); contentAPIRequest = createContentAPIRequest({ strapi });
}); });
afterAll(async () => { afterAll(async () => {
@ -123,15 +123,18 @@ describe('Sanitize populated entries', () => {
describe('Populate simple media', () => { describe('Populate simple media', () => {
test('Media can be populated without restricted attributes', async () => { test('Media can be populated without restricted attributes', async () => {
const { status, body } = await rq.get(`/${schemas.contentTypes.a.pluralName}`, { const { status, body } = await contentAPIRequest.get(
qs: { `/${schemas.contentTypes.a.pluralName}`,
populate: { {
cover: { qs: {
populate: '*', populate: {
cover: {
populate: '*',
},
}, },
}, },
}, }
}); );
expect(status).toBe(200); expect(status).toBe(200);
expect(body.data[0].attributes.cover).toBeDefined(); expect(body.data[0].attributes.cover).toBeDefined();
@ -140,7 +143,7 @@ describe('Sanitize populated entries', () => {
}); });
test("Media's relations (from related) can be populated without restricted attributes", async () => { test("Media's relations (from related) can be populated without restricted attributes", async () => {
const { status, body } = await rq.get(`/upload/files/${file.id}`, { const { status, body } = await contentAPIRequest.get(`/upload/files/${file.id}`, {
qs: { populate: { related: { populate: '*' } } }, qs: { populate: { related: { populate: '*' } } },
}); });
@ -163,7 +166,7 @@ describe('Sanitize populated entries', () => {
test('Wildcard populate is transformed to an exhaustive list of populatable fields', async () => { test('Wildcard populate is transformed to an exhaustive list of populatable fields', async () => {
const findManyMock = jest.spyOn(strapi.entityService, 'findMany'); const findManyMock = jest.spyOn(strapi.entityService, 'findMany');
const { status } = await rq.get(`/${schemas.contentTypes.b.pluralName}`, { const { status } = await contentAPIRequest.get(`/${schemas.contentTypes.b.pluralName}`, {
qs: { fields: ['id'], populate: '*' }, qs: { fields: ['id'], populate: '*' },
}); });