2021-08-26 14:37:55 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const crypto = require('crypto');
|
|
|
|
|
2021-08-30 14:00:53 +02:00
|
|
|
/**
|
|
|
|
* @typedef {'read-only'|'full-access'} TokenType
|
|
|
|
*/
|
|
|
|
|
2021-08-27 09:44:29 +02:00
|
|
|
/**
|
|
|
|
* @typedef ApiToken
|
|
|
|
*
|
2021-08-30 14:00:53 +02:00
|
|
|
* @property {number|string} id
|
2021-08-27 09:44:29 +02:00
|
|
|
* @property {string} name
|
|
|
|
* @property {string} [description]
|
|
|
|
* @property {string} accessKey
|
2021-08-30 14:00:53 +02:00
|
|
|
* @property {TokenType} type
|
2021-08-27 09:44:29 +02:00
|
|
|
*/
|
|
|
|
|
2021-09-02 10:47:06 +02:00
|
|
|
/** @constant {Array<string>} */
|
2021-10-05 13:13:45 +02:00
|
|
|
const SELECT_FIELDS = ['id', 'name', 'description', 'type', 'createdAt'];
|
2021-09-02 10:47:06 +02:00
|
|
|
|
2021-08-26 14:37:55 +02:00
|
|
|
/**
|
2021-08-27 16:23:19 +02:00
|
|
|
* @param {Object} whereParams
|
2021-09-16 14:36:54 +02:00
|
|
|
* @param {string|number} [whereParams.id]
|
|
|
|
* @param {string} [whereParams.name]
|
2021-08-27 16:23:19 +02:00
|
|
|
* @param {string} [whereParams.description]
|
2021-09-16 14:36:54 +02:00
|
|
|
* @param {string} [whereParams.accessKey]
|
2021-08-26 14:37:55 +02:00
|
|
|
*
|
2021-08-27 10:30:18 +02:00
|
|
|
* @returns {Promise<boolean>}
|
2021-08-26 14:37:55 +02:00
|
|
|
*/
|
2021-08-27 16:23:19 +02:00
|
|
|
const exists = async (whereParams = {}) => {
|
2021-09-16 14:36:54 +02:00
|
|
|
const apiToken = await getBy(whereParams);
|
2021-08-27 16:23:19 +02:00
|
|
|
|
|
|
|
return !!apiToken;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} accessKey
|
|
|
|
*
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
const hash = accessKey => {
|
|
|
|
return crypto
|
2021-10-26 12:18:53 +02:00
|
|
|
.createHmac('sha512', strapi.config.get('admin.apiToken.salt'))
|
2021-08-27 17:06:05 +02:00
|
|
|
.update(accessKey)
|
2021-08-27 16:23:19 +02:00
|
|
|
.digest('hex');
|
2021-08-26 14:37:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {Object} attributes
|
2021-08-30 14:00:53 +02:00
|
|
|
* @param {TokenType} attributes.type
|
2021-08-26 14:37:55 +02:00
|
|
|
* @param {string} attributes.name
|
|
|
|
* @param {string} [attributes.description]
|
|
|
|
*
|
2021-08-27 09:44:29 +02:00
|
|
|
* @returns {Promise<ApiToken>}
|
2021-08-26 14:37:55 +02:00
|
|
|
*/
|
|
|
|
const create = async attributes => {
|
|
|
|
const accessKey = crypto.randomBytes(128).toString('hex');
|
|
|
|
|
2021-08-27 16:23:19 +02:00
|
|
|
const apiToken = await strapi.query('admin::api-token').create({
|
2021-09-02 10:47:06 +02:00
|
|
|
select: SELECT_FIELDS,
|
2021-08-26 14:37:55 +02:00
|
|
|
data: {
|
|
|
|
...attributes,
|
2021-08-27 16:23:19 +02:00
|
|
|
accessKey: hash(accessKey),
|
2021-08-26 14:37:55 +02:00
|
|
|
},
|
|
|
|
});
|
2021-08-27 16:23:19 +02:00
|
|
|
|
|
|
|
return {
|
|
|
|
...apiToken,
|
|
|
|
accessKey,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
2022-01-24 18:13:27 +01:00
|
|
|
const checkSaltIsDefined = () => {
|
|
|
|
if (!strapi.config.get('admin.apiToken.salt')) {
|
|
|
|
const secretExample = crypto.randomBytes(16).toString('base64');
|
2021-08-27 16:47:02 +02:00
|
|
|
throw new Error(
|
2022-02-09 17:46:53 +01:00
|
|
|
`Missing apiToken.salt. Please set apiToken.salt in config/admin.js (ex: ${secretExample}).
|
|
|
|
For security reasons, prefere storing the secret in a environment variable. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`
|
2021-08-27 16:47:02 +02:00
|
|
|
);
|
2021-08-27 16:23:19 +02:00
|
|
|
}
|
2021-08-26 14:37:55 +02:00
|
|
|
};
|
|
|
|
|
2021-08-27 08:14:36 +02:00
|
|
|
/**
|
2021-09-02 10:47:06 +02:00
|
|
|
* @returns {Promise<Omit<ApiToken, 'accessKey'>>}
|
2021-08-27 08:14:36 +02:00
|
|
|
*/
|
|
|
|
const list = async () => {
|
2021-08-30 14:00:53 +02:00
|
|
|
return strapi.query('admin::api-token').findMany({
|
2021-09-02 10:47:06 +02:00
|
|
|
select: SELECT_FIELDS,
|
2021-08-27 08:39:08 +02:00
|
|
|
orderBy: { name: 'ASC' },
|
|
|
|
});
|
2021-08-27 08:14:36 +02:00
|
|
|
};
|
|
|
|
|
2021-08-31 15:31:54 +02:00
|
|
|
/**
|
|
|
|
* @param {string|number} id
|
|
|
|
*
|
2021-09-02 10:47:06 +02:00
|
|
|
* @returns {Promise<Omit<ApiToken, 'accessKey'>>}
|
2021-08-31 15:31:54 +02:00
|
|
|
*/
|
|
|
|
const revoke = async id => {
|
2021-09-02 10:47:06 +02:00
|
|
|
return strapi.query('admin::api-token').delete({ select: SELECT_FIELDS, where: { id } });
|
2021-08-31 15:31:54 +02:00
|
|
|
};
|
|
|
|
|
2021-09-02 11:56:14 +02:00
|
|
|
/**
|
|
|
|
* @param {string|number} id
|
|
|
|
*
|
|
|
|
* @returns {Promise<Omit<ApiToken, 'accessKey'>>}
|
|
|
|
*/
|
2021-09-06 15:14:45 +02:00
|
|
|
const getById = async id => {
|
2021-09-16 14:36:54 +02:00
|
|
|
return getBy({ id });
|
2021-09-02 11:56:14 +02:00
|
|
|
};
|
|
|
|
|
2021-09-08 14:38:43 +02:00
|
|
|
/**
|
|
|
|
* @param {string} name
|
|
|
|
*
|
|
|
|
* @returns {Promise<Omit<ApiToken, 'accessKey'>>}
|
|
|
|
*/
|
|
|
|
const getByName = async name => {
|
2021-09-16 14:36:54 +02:00
|
|
|
return getBy({ name });
|
2021-09-08 14:38:43 +02:00
|
|
|
};
|
|
|
|
|
2021-09-06 13:30:52 +02:00
|
|
|
/**
|
|
|
|
* @param {string|number} id
|
|
|
|
* @param {Object} attributes
|
|
|
|
* @param {TokenType} attributes.type
|
|
|
|
* @param {string} attributes.name
|
|
|
|
* @param {string} [attributes.description]
|
|
|
|
*
|
|
|
|
* @returns {Promise<Omit<ApiToken, 'accessKey'>>}
|
|
|
|
*/
|
|
|
|
const update = async (id, attributes) => {
|
|
|
|
return strapi
|
|
|
|
.query('admin::api-token')
|
|
|
|
.update({ where: { id }, data: attributes, select: SELECT_FIELDS });
|
|
|
|
};
|
|
|
|
|
2021-09-16 14:36:54 +02:00
|
|
|
/**
|
|
|
|
* @param {Object} whereParams
|
|
|
|
* @param {string|number} [whereParams.id]
|
|
|
|
* @param {string} [whereParams.name]
|
|
|
|
* @param {string} [whereParams.description]
|
|
|
|
* @param {string} [whereParams.accessKey]
|
|
|
|
*
|
|
|
|
* @returns {Promise<Omit<ApiToken, 'accessKey'> | null>}
|
|
|
|
*/
|
|
|
|
const getBy = async (whereParams = {}) => {
|
|
|
|
if (Object.keys(whereParams).length === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return strapi.query('admin::api-token').findOne({ select: SELECT_FIELDS, where: whereParams });
|
|
|
|
};
|
|
|
|
|
2021-08-26 14:37:55 +02:00
|
|
|
module.exports = {
|
|
|
|
create,
|
|
|
|
exists,
|
2022-01-24 18:13:27 +01:00
|
|
|
checkSaltIsDefined,
|
2021-08-27 16:23:19 +02:00
|
|
|
hash,
|
2021-08-27 08:14:36 +02:00
|
|
|
list,
|
2021-08-31 15:31:54 +02:00
|
|
|
revoke,
|
2021-09-06 15:14:45 +02:00
|
|
|
getById,
|
2021-09-06 13:30:52 +02:00
|
|
|
update,
|
2021-09-08 14:38:43 +02:00
|
|
|
getByName,
|
2021-09-16 14:36:54 +02:00
|
|
|
getBy,
|
2021-08-26 14:37:55 +02:00
|
|
|
};
|