mirror of
https://github.com/strapi/strapi.git
synced 2025-09-22 14:59:07 +00:00
Merge branch 'api-token-v2/regenerate-tokens-api' into api-token-v2/backend-expirations
This commit is contained in:
commit
ae90cf5fd0
@ -38,6 +38,21 @@ module.exports = {
|
|||||||
ctx.created({ data: apiToken });
|
ctx.created({ data: apiToken });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async regenerate(ctx) {
|
||||||
|
const { id } = ctx.params;
|
||||||
|
const apiTokenService = getService('api-token');
|
||||||
|
|
||||||
|
const apiTokenExists = await apiTokenService.getById(id);
|
||||||
|
if (!apiTokenExists) {
|
||||||
|
ctx.notFound('API Token not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessToken = await apiTokenService.regenerate(id);
|
||||||
|
|
||||||
|
ctx.created({ data: accessToken });
|
||||||
|
},
|
||||||
|
|
||||||
async list(ctx) {
|
async list(ctx) {
|
||||||
const apiTokenService = getService('api-token');
|
const apiTokenService = getService('api-token');
|
||||||
const apiTokens = await apiTokenService.list();
|
const apiTokens = await apiTokenService.list();
|
||||||
@ -60,7 +75,6 @@ module.exports = {
|
|||||||
|
|
||||||
if (!apiToken) {
|
if (!apiToken) {
|
||||||
ctx.notFound('API Token not found');
|
ctx.notFound('API Token not found');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,4 +56,15 @@ module.exports = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
path: '/api-tokens/:id/regenerate',
|
||||||
|
handler: 'api-token.regenerate',
|
||||||
|
config: {
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{ name: 'admin::hasPermissions', config: { actions: ['admin::api-tokens.update'] } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -256,6 +256,33 @@ describe('API Token', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 res = await apiTokenService.regenerate(id);
|
||||||
|
|
||||||
|
expect(update).toHaveBeenCalledWith({
|
||||||
|
where: { id },
|
||||||
|
select: ['id', 'accessKey'],
|
||||||
|
data: {
|
||||||
|
accessKey: apiTokenService.hash(mockedApiToken.hexedString),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res).toEqual({ accessKey: mockedApiToken.hexedString });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('update', () => {
|
describe('update', () => {
|
||||||
test('Updates a non-custom token', async () => {
|
test('Updates a non-custom token', async () => {
|
||||||
const token = {
|
const token = {
|
||||||
|
@ -161,6 +161,28 @@ const create = async (attributes) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string|number} id
|
||||||
|
*
|
||||||
|
* @returns {Promise<ApiToken>}
|
||||||
|
*/
|
||||||
|
const regenerate = async (id) => {
|
||||||
|
const accessKey = crypto.randomBytes(128).toString('hex');
|
||||||
|
|
||||||
|
const apiToken = await strapi.query('admin::api-token').update({
|
||||||
|
select: ['id', 'accessKey'],
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
accessKey: hash(accessKey),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...apiToken,
|
||||||
|
accessKey,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
@ -372,6 +394,7 @@ const mapTokenPermissions = (token) => {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
create,
|
create,
|
||||||
|
regenerate,
|
||||||
exists,
|
exists,
|
||||||
checkSaltIsDefined,
|
checkSaltIsDefined,
|
||||||
hash,
|
hash,
|
||||||
|
@ -609,6 +609,23 @@ describe('Admin API Token v2 CRUD (e2e)', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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(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');
|
||||||
test.todo('Sets expiration time correctly');
|
test.todo('Sets expiration time correctly');
|
||||||
test.todo("Doesn't have expiration if not set");
|
test.todo("Doesn't have expiration if not set");
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user