2024-03-13 22:13:40 +01:00

180 lines
4.8 KiB
JavaScript

'use strict';
const _ = require('lodash');
const { NotFoundError } = require('@strapi/utils').errors;
const { getService } = require('../utils');
module.exports = ({ strapi }) => ({
async createRole(params) {
if (!params.type) {
params.type = _.snakeCase(_.deburr(_.toLower(params.name)));
}
const role = await strapi.db
.query('plugin::users-permissions.role')
.create({ data: _.omit(params, ['users', 'permissions']) });
const createPromises = _.flatMap(params.permissions, (type, typeName) => {
return _.flatMap(type.controllers, (controller, controllerName) => {
return _.reduce(
controller,
(acc, action, actionName) => {
const { enabled /* policy */ } = action;
if (enabled) {
const actionID = `${typeName}.${controllerName}.${actionName}`;
acc.push(
strapi.db
.query('plugin::users-permissions.permission')
.create({ data: { action: actionID, role: role.id } })
);
}
return acc;
},
[]
);
});
});
await Promise.all(createPromises);
},
async findOne(roleID) {
const role = await strapi.db
.query('plugin::users-permissions.role')
.findOne({ where: { id: roleID }, populate: ['permissions'] });
if (!role) {
throw new NotFoundError('Role not found');
}
const allActions = getService('users-permissions').getActions();
// Group by `type`.
role.permissions.forEach((permission) => {
const [type, controller, action] = permission.action.split('.');
_.set(allActions, `${type}.controllers.${controller}.${action}`, {
enabled: true,
policy: '',
});
});
return {
...role,
permissions: allActions,
};
},
async find() {
const roles = await strapi.db
.query('plugin::users-permissions.role')
.findMany({ sort: ['name'] });
for (const role of roles) {
role.nb_users = await strapi.db
.query('plugin::users-permissions.user')
.count({ where: { role: { id: role.id } } });
}
return roles;
},
async updateRole(roleID, data) {
const role = await strapi.db
.query('plugin::users-permissions.role')
.findOne({ where: { id: roleID }, populate: ['permissions'] });
if (!role) {
throw new NotFoundError('Role not found');
}
await strapi.db.query('plugin::users-permissions.role').update({
where: { id: roleID },
data: _.pick(data, ['name', 'description']),
});
const { permissions } = data;
const newActions = _.flatMap(permissions, (type, typeName) => {
return _.flatMap(type.controllers, (controller, controllerName) => {
return _.reduce(
controller,
(acc, action, actionName) => {
const { enabled /* policy */ } = action;
if (enabled) {
acc.push(`${typeName}.${controllerName}.${actionName}`);
}
return acc;
},
[]
);
});
});
const oldActions = role.permissions.map(({ action }) => action);
const toDelete = role.permissions.reduce((acc, permission) => {
if (!newActions.includes(permission.action)) {
acc.push(permission);
}
return acc;
}, []);
const toCreate = newActions
.filter((action) => !oldActions.includes(action))
.map((action) => ({ action, role: role.id }));
await Promise.all(
toDelete.map((permission) =>
strapi.db
.query('plugin::users-permissions.permission')
.delete({ where: { id: permission.id } })
)
);
await Promise.all(
toCreate.map((permissionInfo) =>
strapi.db.query('plugin::users-permissions.permission').create({ data: permissionInfo })
)
);
},
async deleteRole(roleID, publicRoleID) {
const role = await strapi.db
.query('plugin::users-permissions.role')
.findOne({ where: { id: roleID }, populate: ['users', 'permissions'] });
if (!role) {
throw new NotFoundError('Role not found');
}
// Move users to guest role.
await Promise.all(
role.users.map((user) => {
return strapi.db.query('plugin::users-permissions.user').update({
where: { id: user.id },
data: { role: publicRoleID },
});
})
);
// Remove permissions related to this role.
// TODO: use delete many
await Promise.all(
role.permissions.map((permission) => {
return strapi.db.query('plugin::users-permissions.permission').delete({
where: { id: permission.id },
});
})
);
// Delete the role.
await strapi.db.query('plugin::users-permissions.role').delete({ where: { id: roleID } });
},
});