mirror of
https://github.com/strapi/strapi.git
synced 2025-12-24 05:34:33 +00:00
allow for partial payload to update a token
This commit is contained in:
parent
f7bd99cb74
commit
31d74d2710
@ -210,7 +210,7 @@ describe('API Token Controller', () => {
|
||||
|
||||
test('Fails if the name is already taken', async () => {
|
||||
const getById = jest.fn(() => ({ id, ...body }));
|
||||
const exists = jest.fn(() => true);
|
||||
const getByName = jest.fn(() => ({ id: 2, name: body.name }));
|
||||
const badRequest = jest.fn();
|
||||
const ctx = createContext({ body, params: { id } }, { badRequest });
|
||||
|
||||
@ -218,8 +218,8 @@ describe('API Token Controller', () => {
|
||||
admin: {
|
||||
services: {
|
||||
'api-token': {
|
||||
exists,
|
||||
getById,
|
||||
getByName,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -227,7 +227,7 @@ describe('API Token Controller', () => {
|
||||
|
||||
await apiTokenController.update(ctx);
|
||||
|
||||
expect(exists).toHaveBeenCalledWith({ name: body.name });
|
||||
expect(getByName).toHaveBeenCalledWith(body.name);
|
||||
expect(badRequest).toHaveBeenCalledWith('Name already taken');
|
||||
});
|
||||
|
||||
@ -255,7 +255,7 @@ describe('API Token Controller', () => {
|
||||
test('Updates API Token Successfully', async () => {
|
||||
const update = jest.fn().mockResolvedValue(body);
|
||||
const getById = jest.fn(() => ({ id, ...body }));
|
||||
const exists = jest.fn(() => false);
|
||||
const getByName = jest.fn(() => null);
|
||||
const badRequest = jest.fn();
|
||||
const notFound = jest.fn();
|
||||
const send = jest.fn();
|
||||
@ -266,7 +266,7 @@ describe('API Token Controller', () => {
|
||||
services: {
|
||||
'api-token': {
|
||||
getById,
|
||||
exists,
|
||||
getByName,
|
||||
update,
|
||||
},
|
||||
},
|
||||
@ -276,7 +276,7 @@ describe('API Token Controller', () => {
|
||||
await apiTokenController.update(ctx);
|
||||
|
||||
expect(getById).toHaveBeenCalledWith(id);
|
||||
expect(exists).toHaveBeenCalledWith({ name: body.name });
|
||||
expect(getByName).toHaveBeenCalledWith(body.name);
|
||||
expect(badRequest).not.toHaveBeenCalled();
|
||||
expect(notFound).not.toHaveBeenCalled();
|
||||
expect(update).toHaveBeenCalledWith(id, body);
|
||||
|
||||
@ -73,16 +73,19 @@ module.exports = {
|
||||
const { id } = ctx.params;
|
||||
const apiTokenService = getService('api-token');
|
||||
|
||||
const attributes = body;
|
||||
/**
|
||||
* We trim both field to avoid having issues with either:
|
||||
* - having a space at the end or start of the value.
|
||||
* - having only spaces as value;
|
||||
*/
|
||||
const attributes = {
|
||||
name: trim(body.name),
|
||||
description: trim(body.description),
|
||||
type: body.type,
|
||||
};
|
||||
if (has(attributes, 'name')) {
|
||||
attributes.name = trim(body.name);
|
||||
}
|
||||
|
||||
if (has(attributes, 'description') || attributes.description === null) {
|
||||
attributes.description = trim(body.description);
|
||||
}
|
||||
|
||||
try {
|
||||
await validateApiTokenUpdateInput(attributes);
|
||||
@ -96,8 +99,8 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (has(attributes, 'name')) {
|
||||
const nameAlreadyTaken = await apiTokenService.exists({ name: attributes.name });
|
||||
if (nameAlreadyTaken) {
|
||||
const nameAlreadyTaken = await apiTokenService.getByName(attributes.name);
|
||||
if (!!nameAlreadyTaken && nameAlreadyTaken.id !== id) {
|
||||
return ctx.badRequest('Name already taken');
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ describe('API Token', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
describe('getById', () => {
|
||||
const token = {
|
||||
id: 1,
|
||||
name: 'api-token_tests-name',
|
||||
@ -274,4 +274,48 @@ describe('API Token', () => {
|
||||
expect(res).toEqual(attributes);
|
||||
});
|
||||
});
|
||||
describe('getByName', () => {
|
||||
const token = {
|
||||
id: 1,
|
||||
name: 'api-token_tests-name',
|
||||
description: 'api-token_tests-description',
|
||||
type: 'read-only',
|
||||
};
|
||||
|
||||
test('It retrieves the token', async () => {
|
||||
const findOne = jest.fn().mockResolvedValue(token);
|
||||
|
||||
global.strapi = {
|
||||
query() {
|
||||
return { findOne };
|
||||
},
|
||||
};
|
||||
|
||||
const res = await apiTokenService.getByName(token.name);
|
||||
|
||||
expect(findOne).toHaveBeenCalledWith({
|
||||
select: ['id', 'name', 'description', 'type'],
|
||||
where: { name: token.name },
|
||||
});
|
||||
expect(res).toEqual(token);
|
||||
});
|
||||
|
||||
test('It returns `null` if the resource does not exist', async () => {
|
||||
const findOne = jest.fn().mockResolvedValue(null);
|
||||
|
||||
global.strapi = {
|
||||
query() {
|
||||
return { findOne };
|
||||
},
|
||||
};
|
||||
|
||||
const res = await apiTokenService.getByName('unexistant-name');
|
||||
|
||||
expect(findOne).toHaveBeenCalledWith({
|
||||
select: ['id', 'name', 'description', 'type'],
|
||||
where: { name: 'unexistant-name' },
|
||||
});
|
||||
expect(res).toEqual(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -116,6 +116,15 @@ const getById = async id => {
|
||||
return strapi.query('admin::api-token').findOne({ select: SELECT_FIELDS, where: { id } });
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*
|
||||
* @returns {Promise<Omit<ApiToken, 'accessKey'>>}
|
||||
*/
|
||||
const getByName = async name => {
|
||||
return strapi.query('admin::api-token').findOne({ select: SELECT_FIELDS, where: { name } });
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string|number} id
|
||||
* @param {Object} attributes
|
||||
@ -140,4 +149,5 @@ module.exports = {
|
||||
revoke,
|
||||
getById,
|
||||
update,
|
||||
getByName,
|
||||
};
|
||||
|
||||
@ -8,8 +8,8 @@ const { createAuthRequest } = require('../../../../../test/helpers/request');
|
||||
*
|
||||
* N° Description
|
||||
* -------------------------------------------
|
||||
* 1. Fails to creates an api token (missing parameters from the body)
|
||||
* 2. Fails to creates an api token (invalid `type` in the body)
|
||||
* 1. Fails to create an api token (missing parameters from the body)
|
||||
* 2. Fails to create an api token (invalid `type` in the body)
|
||||
* 3. Creates an api token (successfully)
|
||||
* 4. Creates an api token without a description (successfully)
|
||||
* 5. Creates an api token with trimmed description and name (successfully)
|
||||
@ -20,8 +20,10 @@ const { createAuthRequest } = require('../../../../../test/helpers/request');
|
||||
* 10. Returns a 404 if the ressource to retrieve does not exist
|
||||
* 11. Updates a token (successfully)
|
||||
* 12. Returns a 404 if the ressource to update does not exist
|
||||
* 13. Fails to creates an api token (missing parameters from the body)
|
||||
* 14. Fails to creates an api token (invalid `type` in the body)
|
||||
* 13. Updates a token with partial payload (successfully)
|
||||
* 14. Fails to update an api token (invalid `type` in the body)
|
||||
* 15. Updates a token when passing a `null` description (successfully)
|
||||
* 16. Updates a token but not the description of no description is passed (successfully)
|
||||
*/
|
||||
|
||||
describe('Admin API Token CRUD (e2e)', () => {
|
||||
@ -262,12 +264,14 @@ describe('Admin API Token CRUD (e2e)', () => {
|
||||
type: body.type,
|
||||
id: apiTokens[0].id,
|
||||
});
|
||||
|
||||
apiTokens[0] = res.body.data;
|
||||
});
|
||||
|
||||
test('12. Returns a 404 if the ressource to update does not exist', async () => {
|
||||
const body = {
|
||||
name: 'api-token_tests-updated-name',
|
||||
description: 'api-token_tests-description',
|
||||
description: 'api-token_tests-updated-description',
|
||||
type: 'read-only',
|
||||
};
|
||||
|
||||
@ -281,27 +285,26 @@ describe('Admin API Token CRUD (e2e)', () => {
|
||||
expect(res.body.data).toBeUndefined();
|
||||
});
|
||||
|
||||
test('13. Fails to update an api token (missing parameters from the body)', async () => {
|
||||
test('13. Updates a token with partial payload (successfully)', async () => {
|
||||
const body = {
|
||||
name: 'api-token_tests-updated-name',
|
||||
description: 'api-token_tests-description',
|
||||
description: 'api-token_tests-re-updated-description',
|
||||
};
|
||||
|
||||
const res = await rq({
|
||||
url: '/admin/api-tokens/1',
|
||||
url: `/admin/api-tokens/${apiTokens[0].id}`,
|
||||
method: 'PUT',
|
||||
body,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'ValidationError',
|
||||
data: {
|
||||
type: ['type is a required field'],
|
||||
},
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.data).toMatchObject({
|
||||
name: apiTokens[0].name,
|
||||
description: body.description,
|
||||
type: apiTokens[0].type,
|
||||
id: apiTokens[0].id,
|
||||
});
|
||||
|
||||
apiTokens[0] = res.body.data;
|
||||
});
|
||||
|
||||
test('14. Fails to update an api token (invalid `type` in the body)', async () => {
|
||||
@ -327,4 +330,48 @@ describe('Admin API Token CRUD (e2e)', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('15. Updates a token when passing a `null` description (successfully)', async () => {
|
||||
const body = {
|
||||
description: null,
|
||||
};
|
||||
|
||||
const res = await rq({
|
||||
url: `/admin/api-tokens/${apiTokens[0].id}`,
|
||||
method: 'PUT',
|
||||
body,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.data).toMatchObject({
|
||||
name: apiTokens[0].name,
|
||||
description: '',
|
||||
type: apiTokens[0].type,
|
||||
id: apiTokens[0].id,
|
||||
});
|
||||
|
||||
apiTokens[0] = res.body.data;
|
||||
});
|
||||
|
||||
test('16. Updates a token but not the description of no description is passed (successfully)', async () => {
|
||||
const body = {
|
||||
name: 'api-token_tests-name',
|
||||
};
|
||||
|
||||
const res = await rq({
|
||||
url: `/admin/api-tokens/${apiTokens[0].id}`,
|
||||
method: 'PUT',
|
||||
body,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.data).toMatchObject({
|
||||
name: body.name,
|
||||
description: apiTokens[0].description,
|
||||
type: apiTokens[0].type,
|
||||
id: apiTokens[0].id,
|
||||
});
|
||||
|
||||
apiTokens[0] = res.body.data;
|
||||
});
|
||||
});
|
||||
|
||||
@ -32,12 +32,12 @@ const apiTokenUpdateSchema = yup
|
||||
name: yup
|
||||
.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
description: yup.string().optional(),
|
||||
.notNull(),
|
||||
description: yup.string().nullable(),
|
||||
type: yup
|
||||
.string()
|
||||
.oneOf(Object.values(constants.API_TOKEN_TYPE))
|
||||
.required(),
|
||||
.notNull(),
|
||||
})
|
||||
.noUnknown();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user