register actions in contentapi bootstrap

This commit is contained in:
Ben Irvin 2022-08-22 17:31:15 +02:00
parent 423eb0e283
commit 7a1de40bb6
2 changed files with 51 additions and 61 deletions

View File

@ -2,64 +2,6 @@
const { uniq } = require('lodash');
const permissions = require('./permissions');
/**
* Create a content API container that holds logic, tools and utils. (eg: permissions, ...)
*/
const createContentAPI = (/* strapi */) => {
const syncActions = async () => {
/**
* NOTE: For some reason, this doesn't seem to be necessary because all the routes exist
* createActionProvider uses a providerFactory, which seems to already include everything, and when we try
* to register our actions we get an error that the keys already exist
* Could providerFactory not be providing a new provider, and instead sharing the registry with everything that uses it?
*
* If this isn't an issue to fix and is expected, we don't need the route registration code below and it should be removed
* */
// Start of route registration
const apiRoutesName = Object.values(strapi.api)
.map((api) => api.routes)
.reduce((acc, routesMap) => {
const routes = Object.values(routesMap)
// Only content api routes
.filter((p) => p.type === 'content-api')
// Resolve every handler name for each route
.reduce((a, p) => a.concat(p.routes.map((i) => i.handler)), []);
return acc.concat(routes);
}, []);
const pluginsRoutesname = Object.values(strapi.plugins)
.map((plugin) => plugin.routes['content-api'] || {})
.map((p) => (p.routes || []).map((i) => i.handler))
.flat();
const actions = apiRoutesName.concat(pluginsRoutesname);
Promise.all(
uniq(actions).map((action) =>
providers.action.register(action).catch(() => {
// console.log('Key already exists', action);
})
)
);
};
// End of route registration
// Add providers
const providers = {
action: permissions.providers.createActionProvider(),
condition: permissions.providers.createConditionProvider(),
};
// create permission engine
const engine = permissions
.createPermissionEngine({ providers })
.on('before-format::validate.permission', createValidatePermissionHandler(providers.action));
return {
permissions: {
engine,
providers,
syncActions,
},
};
};
/**
* Creates an handler which check that the permission's action exists in the action registry
@ -78,4 +20,54 @@ const createValidatePermissionHandler =
}
};
/**
* Create a content API container that holds logic, tools and utils. (eg: permissions, ...)
*/
const createContentAPI = (/* strapi */) => {
// Add providers
const providers = {
action: permissions.providers.createActionProvider(),
condition: permissions.providers.createConditionProvider(),
};
const syncActions = async () => {
// Register actions
const apiRoutesName = Object.values(strapi.api)
.map((api) => api.routes)
.reduce((acc, routesMap) => {
const routes = Object.values(routesMap)
// Only content api routes
.filter((p) => p.type === 'content-api')
// Resolve every handler name for each route
.reduce((a, p) => a.concat(p.routes.map((i) => i.handler)), []);
return acc.concat(routes);
}, []);
const pluginsRoutesname = Object.values(strapi.plugins)
.map((plugin) => plugin.routes['content-api'] || {})
.map((p) => (p.routes || []).map((i) => i.handler))
.flat();
const actions = apiRoutesName.concat(pluginsRoutesname);
Promise.all(
uniq(actions).map((action) =>
providers.action.register(action).catch(() => {
console.warn('Trying to add action that already exists', action);
})
)
);
};
// create permission engine
const engine = permissions
.createPermissionEngine({ providers })
.on('before-format::validate.permission', createValidatePermissionHandler(providers.action));
return {
permissions: {
engine,
providers,
syncActions,
},
};
};
module.exports = createContentAPI;

View File

@ -171,9 +171,7 @@ module.exports = ({ strapi }) => ({
const toDelete = _.difference(permissionsFoundInDB, allActions);
// Register actions into the content API action provider
// TODO: do this in the content API bootstrap phase instead
allActions.forEach((action) => strapi.contentAPI.permissions.providers.action.register(action));
// NOTE: actions are registered in content API bootstrap syncActions
await Promise.all(
toDelete.map((action) => {