From 06d95419f47b1b8c5c4ac15c4024b9f971858faa Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Thu, 18 Aug 2022 13:31:02 +0200 Subject: [PATCH 1/3] add regeneration of tokens --- .../admin/server/controllers/api-token.js | 15 +++++++- .../core/admin/server/routes/api-tokens.js | 11 ++++++ .../services/__tests__/api-token.test.js | 35 +++++++++++++++++++ .../core/admin/server/services/api-token.js | 22 ++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/packages/core/admin/server/controllers/api-token.js b/packages/core/admin/server/controllers/api-token.js index 6ac27b28bb..2eaa8b4d50 100644 --- a/packages/core/admin/server/controllers/api-token.js +++ b/packages/core/admin/server/controllers/api-token.js @@ -37,6 +37,20 @@ module.exports = { ctx.created({ data: apiToken }); }, + async regenerate(ctx) { + const { body } = ctx.request; + const apiTokenService = getService('api-token'); + + const alreadyExists = await apiTokenService.exists({ name: body.id }); + if (!alreadyExists) { + ctx.notFound('API Token not found'); + return; + } + + const accessToken = await apiTokenService.regenerate(body.id); + ctx.created({ data: accessToken }); + }, + async list(ctx) { const apiTokenService = getService('api-token'); const apiTokens = await apiTokenService.list(); @@ -59,7 +73,6 @@ module.exports = { if (!apiToken) { ctx.notFound('API Token not found'); - return; } diff --git a/packages/core/admin/server/routes/api-tokens.js b/packages/core/admin/server/routes/api-tokens.js index 30147b0a32..acb34d9b45 100644 --- a/packages/core/admin/server/routes/api-tokens.js +++ b/packages/core/admin/server/routes/api-tokens.js @@ -56,4 +56,15 @@ module.exports = [ ], }, }, + { + method: 'PUT', + path: '/api-tokens/:id/regenerate', + handler: 'api-token.regenerate', + config: { + policies: [ + 'admin::isAuthenticatedAdmin', + { name: 'admin::hasPermissions', config: { actions: ['admin::api-tokens.update'] } }, + ], + }, + }, ]; diff --git a/packages/core/admin/server/services/__tests__/api-token.test.js b/packages/core/admin/server/services/__tests__/api-token.test.js index c79cdb7d95..bedfa0f3bb 100644 --- a/packages/core/admin/server/services/__tests__/api-token.test.js +++ b/packages/core/admin/server/services/__tests__/api-token.test.js @@ -263,6 +263,41 @@ describe('API Token', () => { expect(res).toEqual(attributes); }); }); + + describe('regenerate', () => { + test('It regenerates the accessKey', async () => { + const update = jest.fn(({ data }) => Promise.resolve(data)); + + global.strapi = { + query() { + return { update }; + }, + config: { + get: jest.fn(() => ''), + }, + }; + + const id = 1; + const attributes = { + name: 'api-token_tests-updated-name', + description: 'api-token_tests-description', + type: 'read-only', + }; + + const res = await apiTokenService.regenerate(id); + + expect(update).toHaveBeenCalledWith(id, { + select: ['id', 'accessKey'], + where: { id }, + data: { + ...attributes, + accessKey: expect.any(String), + }, + }); + expect(res).toEqual(attributes); + }); + }); + describe('getByName', () => { const token = { id: 1, diff --git a/packages/core/admin/server/services/api-token.js b/packages/core/admin/server/services/api-token.js index 5829a14df5..de1da814e9 100644 --- a/packages/core/admin/server/services/api-token.js +++ b/packages/core/admin/server/services/api-token.js @@ -71,6 +71,27 @@ const create = async (attributes) => { }; }; +/** + * @param {string|number} id + * + * @returns {Promise} + */ +const regenerate = async (id) => { + const accessKey = crypto.randomBytes(128).toString('hex'); + + const apiToken = await strapi.query('admin::api-token').update(id, { + select: ['id', 'accessKey'], + data: { + accessKey: hash(accessKey), + }, + }); + + return { + ...apiToken, + accessKey, + }; +}; + /** * @returns {void} */ @@ -162,6 +183,7 @@ const getBy = async (whereParams = {}) => { module.exports = { create, + regenerate, exists, checkSaltIsDefined, hash, From 9941198dac8df8599331863ecf75b60d5eb3e83e Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Thu, 18 Aug 2022 14:03:59 +0200 Subject: [PATCH 2/3] fix regeneration --- .../core/admin/server/controllers/api-token.js | 9 +++++---- packages/core/admin/server/routes/api-tokens.js | 2 +- .../server/services/__tests__/api-token.test.js | 3 ++- packages/core/admin/server/services/api-token.js | 3 ++- .../admin/server/tests/admin-api-token.test.e2e.js | 14 ++++++++++++++ 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/core/admin/server/controllers/api-token.js b/packages/core/admin/server/controllers/api-token.js index 8cde465fc1..71b719f97c 100644 --- a/packages/core/admin/server/controllers/api-token.js +++ b/packages/core/admin/server/controllers/api-token.js @@ -39,16 +39,17 @@ module.exports = { }, async regenerate(ctx) { - const { body } = ctx.request; + const { id } = ctx.params; const apiTokenService = getService('api-token'); - const alreadyExists = await apiTokenService.exists({ name: body.id }); - if (!alreadyExists) { + const apiTokenExists = await apiTokenService.getById(id); + if (!apiTokenExists) { ctx.notFound('API Token not found'); return; } - const accessToken = await apiTokenService.regenerate(body.id); + const accessToken = await apiTokenService.regenerate(id); + ctx.created({ data: accessToken }); }, diff --git a/packages/core/admin/server/routes/api-tokens.js b/packages/core/admin/server/routes/api-tokens.js index acb34d9b45..e994382db6 100644 --- a/packages/core/admin/server/routes/api-tokens.js +++ b/packages/core/admin/server/routes/api-tokens.js @@ -57,7 +57,7 @@ module.exports = [ }, }, { - method: 'PUT', + method: 'POST', path: '/api-tokens/:id/regenerate', handler: 'api-token.regenerate', config: { diff --git a/packages/core/admin/server/services/__tests__/api-token.test.js b/packages/core/admin/server/services/__tests__/api-token.test.js index 6669db03c7..789a9166f1 100644 --- a/packages/core/admin/server/services/__tests__/api-token.test.js +++ b/packages/core/admin/server/services/__tests__/api-token.test.js @@ -258,7 +258,8 @@ describe('API Token', () => { const id = 1; const res = await apiTokenService.regenerate(id); - expect(update).toHaveBeenCalledWith(id, { + expect(update).toHaveBeenCalledWith({ + where: { id }, select: ['id', 'accessKey'], data: { accessKey: apiTokenService.hash(mockedApiToken.hexedString), diff --git a/packages/core/admin/server/services/api-token.js b/packages/core/admin/server/services/api-token.js index 23f4f55bbe..cba015b91d 100644 --- a/packages/core/admin/server/services/api-token.js +++ b/packages/core/admin/server/services/api-token.js @@ -138,8 +138,9 @@ const create = async (attributes) => { const regenerate = async (id) => { const accessKey = crypto.randomBytes(128).toString('hex'); - const apiToken = await strapi.query('admin::api-token').update(id, { + const apiToken = await strapi.query('admin::api-token').update({ select: ['id', 'accessKey'], + where: { id }, data: { accessKey: hash(accessKey), }, diff --git a/packages/core/admin/server/tests/admin-api-token.test.e2e.js b/packages/core/admin/server/tests/admin-api-token.test.e2e.js index 2c49c6f722..3d4d77787b 100644 --- a/packages/core/admin/server/tests/admin-api-token.test.e2e.js +++ b/packages/core/admin/server/tests/admin-api-token.test.e2e.js @@ -608,4 +608,18 @@ describe('Admin API Token v2 CRUD (e2e)', () => { updatedAt: expect.any(String), }); }); + + test('Regenerates an api token access key)', async () => { + const token = await createValidToken(); + + const res = await rq({ + url: `/admin/api-tokens/${token.id}/regenerate`, + method: 'POST', + }); + + expect(res.statusCode).toBe(200); + expect(res.body.data).toMatchObject({ + accessKey: expect.any(String), + }); + }); }); From 7ce7db6604d160ad6f3f19667b2fbc8550aa5c8c Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Thu, 18 Aug 2022 14:12:34 +0200 Subject: [PATCH 3/3] update tests --- .../core/admin/server/tests/admin-api-token.test.e2e.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/core/admin/server/tests/admin-api-token.test.e2e.js b/packages/core/admin/server/tests/admin-api-token.test.e2e.js index 3d4d77787b..f3079f8979 100644 --- a/packages/core/admin/server/tests/admin-api-token.test.e2e.js +++ b/packages/core/admin/server/tests/admin-api-token.test.e2e.js @@ -609,7 +609,7 @@ describe('Admin API Token v2 CRUD (e2e)', () => { }); }); - test('Regenerates an api token access key)', async () => { + test('Regenerates an api token access key', async () => { const token = await createValidToken(); const res = await rq({ @@ -617,9 +617,13 @@ describe('Admin API Token v2 CRUD (e2e)', () => { method: 'POST', }); - expect(res.statusCode).toBe(200); + expect(res.statusCode).toBe(201); expect(res.body.data).toMatchObject({ accessKey: expect.any(String), }); }); + + test.todo('Regenerated access key works'); + test.todo('Tokens access content for which they are authorized'); + test.todo('Tokens fail to access content for which they are not authorized'); });