From 36d37706ceeec5280dc16b05bed7646cfb9d3cfd Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Fri, 19 Aug 2022 16:33:58 +0200 Subject: [PATCH] add lifespan and expiresAt fields --- .../admin/server/content-types/api-token.js | 10 ++++++ .../services/__tests__/api-token.test.js | 16 ++++++++- .../core/admin/server/services/api-token.js | 33 ++++++++++++++++++- .../admin/server/validation/api-tokens.js | 1 + 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/core/admin/server/content-types/api-token.js b/packages/core/admin/server/content-types/api-token.js index 9c4ef6663a..a21da4405d 100644 --- a/packages/core/admin/server/content-types/api-token.js +++ b/packages/core/admin/server/content-types/api-token.js @@ -60,5 +60,15 @@ module.exports = { configurable: false, required: false, }, + expiresAt: { + type: 'datetime', + configurable: false, + required: false, + }, + lifespan: { + type: 'number', + configurable: false, + required: false, + }, }, }; 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 864340cd2d..c32d10dae9 100644 --- a/packages/core/admin/server/services/__tests__/api-token.test.js +++ b/packages/core/admin/server/services/__tests__/api-token.test.js @@ -10,7 +10,17 @@ describe('API Token', () => { hexedString: '6170692d746f6b656e5f746573742d72616e646f6d2d6279746573', }; - const SELECT_FIELDS = ['id', 'name', 'description', 'lastUsed', 'type', 'createdAt', 'updatedAt']; + const SELECT_FIELDS = [ + 'id', + 'name', + 'description', + 'lastUsed', + 'type', + 'lifespan', + 'expiresAt', + 'createdAt', + 'updatedAt', + ]; beforeAll(() => { jest @@ -48,12 +58,16 @@ describe('API Token', () => { data: { ...attributes, accessKey: apiTokenService.hash(mockedApiToken.hexedString), + expiresAt: null, + lifespan: null, }, populate: ['permissions'], }); expect(res).toEqual({ ...attributes, accessKey: mockedApiToken.hexedString, + expiresAt: null, + lifespan: null, }); }); }); diff --git a/packages/core/admin/server/services/api-token.js b/packages/core/admin/server/services/api-token.js index a9be09c464..005763c6bf 100644 --- a/packages/core/admin/server/services/api-token.js +++ b/packages/core/admin/server/services/api-token.js @@ -1,6 +1,7 @@ 'use strict'; const crypto = require('crypto'); +const { isNumber, isNil } = require('lodash'); const { omit, difference, isEmpty, map, isArray } = require('lodash/fp'); const { ValidationError, NotFoundError } = require('@strapi/utils').errors; const constants = require('./constants'); @@ -17,6 +18,8 @@ const constants = require('./constants'); * @property {string} [description] * @property {string} accessKey * @property {number} lastUsed + * @property {number} lifespan + * @property {number} expiresAt * @property {TokenType} type * @property {(number|ApiTokenPermission)[]} [permissions] */ @@ -30,7 +33,17 @@ const constants = require('./constants'); */ /** @constant {Array} */ -const SELECT_FIELDS = ['id', 'name', 'description', 'lastUsed', 'type', 'createdAt', 'updatedAt']; +const SELECT_FIELDS = [ + 'id', + 'name', + 'description', + 'lastUsed', + 'type', + 'lifespan', + 'expiresAt', + 'createdAt', + 'updatedAt', +]; /** @constant {Array} */ const POPULATE_FIELDS = ['permissions']; @@ -75,10 +88,27 @@ const hash = (accessKey) => { .digest('hex'); }; +/** + * @param {number} lifespan + * + * @returns {null|number} + */ +const getExpirationFields = (lifespan) => { + if (!isNumber(lifespan) && !isNil(lifespan)) { + throw new ValidationError('lifespan must be a number or null'); + } + + return { + lifespan: lifespan || null, + expiresAt: lifespan ? Date.now() + lifespan : null, + }; +}; + /** * @param {Object} attributes * @param {TokenType} attributes.type * @param {string} attributes.name + * @param {number} attributes.lifespan * @param {string[]} [attributes.permissions] * @param {string} [attributes.description] * @@ -96,6 +126,7 @@ const create = async (attributes) => { data: { ...omit('permissions', attributes), accessKey: hash(accessKey), + ...getExpirationFields(attributes.lifespan), }, }); diff --git a/packages/core/admin/server/validation/api-tokens.js b/packages/core/admin/server/validation/api-tokens.js index f63100a5c4..6637139f79 100644 --- a/packages/core/admin/server/validation/api-tokens.js +++ b/packages/core/admin/server/validation/api-tokens.js @@ -10,6 +10,7 @@ const apiTokenCreationSchema = yup description: yup.string().optional(), type: yup.string().oneOf(Object.values(constants.API_TOKEN_TYPE)).required(), permissions: yup.array().of(yup.string()).nullable(), + lifespan: yup.number().nullable(), }) .noUnknown();