2020-01-23 16:59:50 +01:00
|
|
|
/**
|
|
|
|
* Policies util
|
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
2018-03-30 17:05:24 +02:00
|
|
|
const _ = require('lodash');
|
2020-01-23 16:59:50 +01:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const GLOBAL_PREFIX = 'global::';
|
|
|
|
const PLUGIN_PREFIX = 'plugins::';
|
|
|
|
const ADMIN_PREFIX = 'admin::';
|
|
|
|
const APPLICATION_PREFIX = 'application::';
|
2020-01-23 16:59:50 +01:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const isPolicyGenerator = _.isArray;
|
2020-01-23 16:59:50 +01:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const getPolicyIn = (container, policy) =>
|
|
|
|
_.get(container, ['config', 'policies', _.toLower(policy)]);
|
|
|
|
|
|
|
|
const policyExistsIn = (container, policy) => !_.isUndefined(getPolicyIn(container, policy));
|
|
|
|
|
|
|
|
const stripPolicy = (policy, prefix) => policy.replace(prefix, '');
|
|
|
|
|
|
|
|
const createPolicy = (policyName, args) => ({ policyName, args });
|
2020-06-10 18:04:47 +02:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const resolveHandler = policy => (_.isFunction(policy) ? policy : policy.handler);
|
|
|
|
|
|
|
|
const parsePolicy = policy =>
|
|
|
|
isPolicyGenerator(policy) ? createPolicy(...policy) : createPolicy(policy);
|
|
|
|
|
|
|
|
const resolvePolicy = policyName => {
|
|
|
|
for (const policyModel of Object.values(policyModelsProvider)) {
|
|
|
|
if (policyModel.exists(policyName)) {
|
|
|
|
return resolveHandler(policyModel.get)(policyName);
|
|
|
|
}
|
2020-01-29 15:30:53 +01:00
|
|
|
}
|
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
return undefined;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getLegacyPolicy = (policy, plugin, apiName) => {
|
2020-01-29 15:30:53 +01:00
|
|
|
let [absoluteApiName, policyName] = policy.split('.');
|
|
|
|
let absoluteApi = _.get(strapi.api, absoluteApiName);
|
2020-06-18 11:41:12 +02:00
|
|
|
|
2020-01-29 15:30:53 +01:00
|
|
|
if (policyExistsIn(absoluteApi, policyName)) {
|
2020-06-18 11:41:12 +02:00
|
|
|
return resolveHandler(getPolicyIn(absoluteApi, policyName));
|
2020-01-29 15:30:53 +01:00
|
|
|
}
|
|
|
|
|
2020-01-23 16:59:50 +01:00
|
|
|
const pluginPolicy = `${PLUGIN_PREFIX}${plugin}.${policy}`;
|
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
if (plugin && policyModelsProvider.plugin.exists(pluginPolicy)) {
|
|
|
|
return resolveHandler(policyModelsProvider.plugin.get(pluginPolicy));
|
2020-01-23 16:59:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const api = _.get(strapi.api, apiName);
|
2020-01-29 15:30:53 +01:00
|
|
|
if (api && policyExistsIn(api, policy)) {
|
2020-06-18 11:41:12 +02:00
|
|
|
return resolveHandler(getPolicyIn(api, policy));
|
2020-01-23 16:59:50 +01:00
|
|
|
}
|
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
return undefined;
|
2020-01-23 16:59:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const globalPolicy = ({ method, endpoint, controller, action, plugin }) => {
|
|
|
|
return async (ctx, next) => {
|
|
|
|
ctx.request.route = {
|
|
|
|
endpoint: `${method} ${endpoint}`,
|
|
|
|
controller: _.toLower(controller),
|
|
|
|
action: _.toLower(action),
|
2020-06-18 11:41:12 +02:00
|
|
|
splitEndpoint: endpoint,
|
2020-01-23 16:59:50 +01:00
|
|
|
verb: _.toLower(method),
|
|
|
|
plugin,
|
2018-04-10 11:47:01 +02:00
|
|
|
};
|
2020-01-23 16:59:50 +01:00
|
|
|
|
|
|
|
await next();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const createPolicyModelsProvider = () => ({
|
|
|
|
APIPolicy: {
|
|
|
|
is(policy) {
|
|
|
|
return _.startsWith(policy, APPLICATION_PREFIX);
|
|
|
|
},
|
|
|
|
exists(policy) {
|
|
|
|
return this.is(policy) && !_.isUndefined(this.get(policy));
|
|
|
|
},
|
|
|
|
get: policy => {
|
|
|
|
const [, policyWithoutPrefix] = policy.split('::');
|
|
|
|
const [api = '', policyName = ''] = policyWithoutPrefix.split('.');
|
|
|
|
return getPolicyIn(_.get(strapi, ['api', api]), policyName);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
admin: {
|
|
|
|
is(policy) {
|
|
|
|
return _.startsWith(policy, ADMIN_PREFIX);
|
|
|
|
},
|
|
|
|
exists(policy) {
|
|
|
|
return this.is(policy) && !_.isUndefined(this.get(policy));
|
|
|
|
},
|
|
|
|
get: policy => {
|
|
|
|
return getPolicyIn(_.get(strapi, 'admin'), stripPolicy(policy, ADMIN_PREFIX));
|
|
|
|
},
|
|
|
|
},
|
|
|
|
plugin: {
|
|
|
|
is(policy) {
|
|
|
|
return _.startsWith(policy, PLUGIN_PREFIX);
|
|
|
|
},
|
|
|
|
exists(policy) {
|
|
|
|
return this.is(policy) && !_.isUndefined(this.get(policy));
|
|
|
|
},
|
|
|
|
get(policy) {
|
|
|
|
const [plugin = '', policyName = ''] = stripPolicy(policy, PLUGIN_PREFIX).split('.');
|
|
|
|
return getPolicyIn(_.get(strapi, ['plugins', plugin]), policyName);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
global: {
|
|
|
|
is(policy) {
|
|
|
|
return _.startsWith(policy, GLOBAL_PREFIX);
|
|
|
|
},
|
|
|
|
exists(policy) {
|
|
|
|
return this.is(policy) && !_.isUndefined(this.get(policy));
|
|
|
|
},
|
|
|
|
get(policy) {
|
|
|
|
return getPolicyIn(strapi, stripPolicy(policy, GLOBAL_PREFIX));
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const policyModelsProvider = createPolicyModelsProvider();
|
2020-01-23 16:59:50 +01:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const get = (policy, plugin, apiName) => {
|
|
|
|
const { policyName, args } = parsePolicy(policy);
|
2020-01-23 16:59:50 +01:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const resolvedPolicy = resolvePolicy(policyName);
|
2020-06-10 18:04:47 +02:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
if (resolvedPolicy !== undefined) {
|
|
|
|
return isPolicyGenerator(policy) ? resolvedPolicy(args) : resolvedPolicy;
|
|
|
|
}
|
2020-06-10 18:04:47 +02:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
const legacyPolicy = getLegacyPolicy(policy, plugin, apiName);
|
2020-06-10 18:04:47 +02:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
if (legacyPolicy !== undefined) {
|
|
|
|
return legacyPolicy;
|
|
|
|
}
|
2020-01-29 15:30:53 +01:00
|
|
|
|
2020-06-18 11:41:12 +02:00
|
|
|
throw new Error(`Could not find policy "${policy}"`);
|
2020-01-29 15:30:53 +01:00
|
|
|
};
|
|
|
|
|
2020-01-23 16:59:50 +01:00
|
|
|
module.exports = {
|
|
|
|
get,
|
|
|
|
globalPolicy,
|
2018-03-30 17:05:24 +02:00
|
|
|
};
|