mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 18:33:55 +00:00
refacto
Signed-off-by: Pierre Noël <petersg83@gmail.com>
This commit is contained in:
parent
1bc8ae4d0f
commit
907d6c9d33
@ -20,7 +20,7 @@ module.exports = async () => {
|
||||
await strapi.admin.services.permission.ensureBoundPermissionsInDatabase();
|
||||
await strapi.admin.services.user.migrateUsers();
|
||||
await strapi.admin.services.role.createRolesIfNoneExist();
|
||||
await strapi.admin.services.permission.resetSuperAdminPermissions();
|
||||
await strapi.admin.services.role.resetSuperAdminPermissions();
|
||||
await strapi.admin.services.role.displayWarningIfNoSuperAdmin();
|
||||
await strapi.admin.services.user.displayWarningIfUsersDontHaveRole();
|
||||
};
|
||||
|
||||
@ -168,11 +168,11 @@ describe('Role controller', () => {
|
||||
admin: {
|
||||
services: {
|
||||
role: {
|
||||
assignPermissions,
|
||||
findOne: findOneRole,
|
||||
getSuperAdmin: jest.fn(() => undefined),
|
||||
},
|
||||
permission: {
|
||||
assign: assignPermissions,
|
||||
conditionProvider: {
|
||||
getAll: jest.fn(() => [{ id: 'admin::is-creator' }]),
|
||||
},
|
||||
|
||||
@ -129,7 +129,10 @@ module.exports = {
|
||||
permissionsToAssign = input.permissions;
|
||||
}
|
||||
|
||||
const permissions = await strapi.admin.services.permission.assign(role.id, permissionsToAssign);
|
||||
const permissions = await strapi.admin.services.role.assignPermissions(
|
||||
role.id,
|
||||
permissionsToAssign
|
||||
);
|
||||
|
||||
ctx.body = {
|
||||
data: permissions,
|
||||
|
||||
@ -96,7 +96,10 @@ module.exports = {
|
||||
return ctx.notFound('role.notFound');
|
||||
}
|
||||
|
||||
const permissions = await strapi.admin.services.permission.assign(role.id, input.permissions);
|
||||
const permissions = await strapi.admin.services.role.assignPermissions(
|
||||
role.id,
|
||||
input.permissions
|
||||
);
|
||||
|
||||
ctx.body = {
|
||||
data: permissions,
|
||||
|
||||
@ -19,86 +19,6 @@ describe('Permission Service', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Assign permissions', () => {
|
||||
test('Delete previous permissions', async () => {
|
||||
const createMany = jest.fn(() => Promise.resolve([]));
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve({ id: 0 }));
|
||||
const sendDidUpdateRolePermissions = jest.fn();
|
||||
const find = jest.fn(() => Promise.resolve([{ id: 3 }]));
|
||||
const deleteFn = jest.fn();
|
||||
const getAll = jest.fn(() => []);
|
||||
|
||||
global.strapi = {
|
||||
admin: {
|
||||
services: {
|
||||
metrics: { sendDidUpdateRolePermissions },
|
||||
permission: { actionProvider: { getAll } },
|
||||
role: { getSuperAdmin },
|
||||
}
|
||||
},
|
||||
query() {
|
||||
return { delete: deleteFn, createMany, find };
|
||||
},
|
||||
};
|
||||
|
||||
await permissionService.assign(1, []);
|
||||
|
||||
expect(deleteFn).toHaveBeenCalledWith({ id_in: [3] });
|
||||
});
|
||||
|
||||
test('Create new permissions', async () => {
|
||||
const permissions = Array(5)
|
||||
.fill(0)
|
||||
.map((v, i) => ({ action: `action-${i}` }));
|
||||
|
||||
const deleteFn = jest.fn(() => Promise.resolve([]));
|
||||
const createMany = jest.fn(() => Promise.resolve([]));
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve({ id: 0 }));
|
||||
const sendDidUpdateRolePermissions = jest.fn();
|
||||
const find = jest.fn(() => Promise.resolve([]));
|
||||
const getAll = jest.fn(() => permissions.map(perm => ({ actionId: perm.action })));
|
||||
const removeUnkownConditionIds = jest.fn(conds => _.intersection(conds, ['cond']));
|
||||
|
||||
global.strapi = {
|
||||
admin: {
|
||||
services: {
|
||||
metrics: { sendDidUpdateRolePermissions },
|
||||
role: { getSuperAdmin },
|
||||
permission: {
|
||||
actionProvider: { getAll },
|
||||
conditionProvider: {
|
||||
getAll: jest.fn(() => [{ id: 'admin::is-creator' }]),
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
removeUnkownConditionIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
query() {
|
||||
return { delete: deleteFn, createMany, find };
|
||||
},
|
||||
};
|
||||
|
||||
const permissionsToAssign = [...permissions];
|
||||
permissionsToAssign[4] = {
|
||||
...permissions[4],
|
||||
conditions: ['cond', 'unknown-cond'],
|
||||
};
|
||||
|
||||
await permissionService.assign(1, permissionsToAssign);
|
||||
|
||||
expect(createMany).toHaveBeenCalledTimes(1);
|
||||
expect(createMany).toHaveBeenCalledWith([
|
||||
{ action: 'action-0', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-1', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-2', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-3', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-4', conditions: ['cond'], fields: null, role: 1, subject: null },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Find User Permissions', () => {
|
||||
test('Find calls the right db query', async () => {
|
||||
const find = jest.fn(({ role_in }) => role_in);
|
||||
@ -229,70 +149,4 @@ describe('Permission Service', () => {
|
||||
permissionService.actionProvider.getAllByMap = prevGetAllByMap;
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetSuperAdminPermissions', () => {
|
||||
test('No superAdmin role exist', async () => {
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve(undefined));
|
||||
const createMany = jest.fn();
|
||||
|
||||
global.strapi = {
|
||||
query: () => ({ createMany }),
|
||||
admin: { services: { role: { getSuperAdmin } } },
|
||||
};
|
||||
|
||||
await permissionService.resetSuperAdminPermissions();
|
||||
|
||||
expect(createMany).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
test('Reset super admin permissions', async () => {
|
||||
const actions = [
|
||||
{
|
||||
actionId: 'action-1',
|
||||
subjects: ['country'],
|
||||
section: 'contentTypes',
|
||||
},
|
||||
];
|
||||
const permissions = [
|
||||
{
|
||||
action: 'action-1',
|
||||
subject: 'country',
|
||||
fields: ['name'],
|
||||
conditions: [],
|
||||
},
|
||||
];
|
||||
const getAll = jest.fn(() => actions);
|
||||
const getAllConditions = jest.fn(() => []);
|
||||
const find = jest.fn(() => [{ action: 'action-2', id: 2 }]);
|
||||
const deleteFn = jest.fn(() => []);
|
||||
const getPermissionsWithNestedFields = jest.fn(() => [...permissions]); // cloned, otherwise it is modified inside resetSuperAdminPermissions()
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve({ id: 1 }));
|
||||
const createMany = jest.fn(() => Promise.resolve([{ ...permissions[0], role: { id: 1 } }]));
|
||||
const removeUnkownConditionIds = jest.fn(conds => conds);
|
||||
|
||||
global.strapi = {
|
||||
query: () => ({ createMany, find, delete: deleteFn }),
|
||||
admin: {
|
||||
services: {
|
||||
permission: {
|
||||
actionProvider: { getAll },
|
||||
conditionProvider: { getAll: getAllConditions },
|
||||
},
|
||||
condition: { removeUnkownConditionIds },
|
||||
'content-type': { getPermissionsWithNestedFields },
|
||||
role: { getSuperAdmin },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await permissionService.resetSuperAdminPermissions();
|
||||
|
||||
expect(deleteFn).toHaveBeenCalledWith({ id_in: [2] });
|
||||
expect(createMany).toHaveBeenCalledWith([
|
||||
{
|
||||
...permissions[0],
|
||||
role: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -275,7 +275,6 @@ describe('Role', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Count roles', () => {
|
||||
test('Count roles without params', async () => {
|
||||
const count = jest.fn(() => Promise.resolve(2));
|
||||
@ -302,7 +301,6 @@ describe('Role', () => {
|
||||
expect(count).toHaveBeenCalledWith(params);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createRolesIfNoneExist', () => {
|
||||
test("Don't create roles if one already exist", async () => {
|
||||
const count = jest.fn(() => Promise.resolve(1));
|
||||
@ -405,21 +403,26 @@ describe('Role', () => {
|
||||
restrictedSubjects: ['plugins::users-permissions.user'],
|
||||
});
|
||||
expect(createMany).toHaveBeenCalledTimes(2);
|
||||
expect(createMany).toHaveBeenNthCalledWith(1, 2, [
|
||||
...permissions,
|
||||
...defaultPermissions.map(d => ({
|
||||
...d,
|
||||
conditions: [],
|
||||
})),
|
||||
]);
|
||||
expect(createMany).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
[
|
||||
...permissions,
|
||||
...defaultPermissions.map(d => ({
|
||||
...d,
|
||||
conditions: [],
|
||||
})),
|
||||
].map(p => ({ ...p, role: 2 }))
|
||||
);
|
||||
|
||||
expect(createMany).toHaveBeenNthCalledWith(2, 3, [
|
||||
{ ...permissions[0], conditions: ['admin::is-creator'] },
|
||||
...defaultPermissions,
|
||||
]);
|
||||
expect(createMany).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
[
|
||||
{ ...permissions[0], conditions: ['admin::is-creator'] },
|
||||
...defaultPermissions,
|
||||
].map(p => ({ ...p, role: 3 }))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('displayWarningIfNoSuperAdmin', () => {
|
||||
test('superAdmin role exists & a user is superAdmin', async () => {
|
||||
const findOne = jest.fn(() => ({ id: 1 }));
|
||||
@ -470,4 +473,145 @@ describe('Role', () => {
|
||||
expect(warn).toHaveBeenCalledWith("Your application doesn't have a super admin user.");
|
||||
});
|
||||
});
|
||||
describe('resetSuperAdminPermissions', () => {
|
||||
test('No superAdmin role exist', async () => {
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve(undefined));
|
||||
const createMany = jest.fn();
|
||||
|
||||
global.strapi = {
|
||||
query: () => ({ createMany }),
|
||||
admin: { services: { role: { getSuperAdmin } } },
|
||||
};
|
||||
|
||||
await roleService.resetSuperAdminPermissions();
|
||||
|
||||
expect(createMany).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
test('Reset super admin permissions', async () => {
|
||||
const actions = [
|
||||
{
|
||||
actionId: 'action-1',
|
||||
subjects: ['country'],
|
||||
section: 'contentTypes',
|
||||
},
|
||||
];
|
||||
const permissions = [
|
||||
{
|
||||
action: 'action-1',
|
||||
subject: 'country',
|
||||
fields: ['name'],
|
||||
conditions: [],
|
||||
},
|
||||
];
|
||||
const getAll = jest.fn(() => actions);
|
||||
const getAllConditions = jest.fn(() => []);
|
||||
const find = jest.fn(() => [{ action: 'action-2', id: 2 }]);
|
||||
const getPermissionsWithNestedFields = jest.fn(() => [...permissions]); // cloned, otherwise it is modified inside resetSuperAdminPermissions()
|
||||
const deleteByIds = jest.fn();
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve({ id: 1 }));
|
||||
const createMany = jest.fn(() => Promise.resolve([{ ...permissions[0], role: { id: 1 } }]));
|
||||
const removeUnkownConditionIds = jest.fn(conds => conds);
|
||||
|
||||
global.strapi = {
|
||||
admin: {
|
||||
services: {
|
||||
permission: {
|
||||
createMany,
|
||||
find,
|
||||
actionProvider: { getAll },
|
||||
conditionProvider: { getAll: getAllConditions },
|
||||
deleteByIds,
|
||||
},
|
||||
condition: { removeUnkownConditionIds },
|
||||
'content-type': { getPermissionsWithNestedFields },
|
||||
role: { getSuperAdmin },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await roleService.resetSuperAdminPermissions();
|
||||
|
||||
expect(deleteByIds).toHaveBeenCalledWith([2]);
|
||||
expect(createMany).toHaveBeenCalledWith([
|
||||
{
|
||||
...permissions[0],
|
||||
role: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('Assign permissions', () => {
|
||||
test('Delete previous permissions', async () => {
|
||||
const createMany = jest.fn(() => Promise.resolve([]));
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve({ id: 0 }));
|
||||
const sendDidUpdateRolePermissions = jest.fn();
|
||||
const find = jest.fn(() => Promise.resolve([{ id: 3 }]));
|
||||
const deleteByIds = jest.fn();
|
||||
const getAll = jest.fn(() => []);
|
||||
|
||||
global.strapi = {
|
||||
admin: {
|
||||
services: {
|
||||
metrics: { sendDidUpdateRolePermissions },
|
||||
permission: { find, createMany, actionProvider: { getAll }, deleteByIds },
|
||||
role: { getSuperAdmin },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await roleService.assignPermissions(1, []);
|
||||
|
||||
expect(deleteByIds).toHaveBeenCalledWith([3]);
|
||||
});
|
||||
|
||||
test('Create new permissions', async () => {
|
||||
const permissions = Array(5)
|
||||
.fill(0)
|
||||
.map((v, i) => ({ action: `action-${i}` }));
|
||||
|
||||
const createMany = jest.fn(() => Promise.resolve([]));
|
||||
const getSuperAdmin = jest.fn(() => Promise.resolve({ id: 0 }));
|
||||
const sendDidUpdateRolePermissions = jest.fn();
|
||||
const find = jest.fn(() => Promise.resolve([]));
|
||||
const getAll = jest.fn(() => permissions.map(perm => ({ actionId: perm.action })));
|
||||
const removeUnkownConditionIds = jest.fn(conds => _.intersection(conds, ['cond']));
|
||||
|
||||
global.strapi = {
|
||||
admin: {
|
||||
services: {
|
||||
metrics: { sendDidUpdateRolePermissions },
|
||||
role: { getSuperAdmin },
|
||||
permission: {
|
||||
find,
|
||||
createMany,
|
||||
actionProvider: { getAll },
|
||||
conditionProvider: {
|
||||
getAll: jest.fn(() => [{ id: 'admin::is-creator' }]),
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
removeUnkownConditionIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const permissionsToAssign = [...permissions];
|
||||
permissionsToAssign[4] = {
|
||||
...permissions[4],
|
||||
conditions: ['cond', 'unknown-cond'],
|
||||
};
|
||||
|
||||
await roleService.assignPermissions(1, permissionsToAssign);
|
||||
|
||||
expect(createMany).toHaveBeenCalledTimes(1);
|
||||
expect(createMany).toHaveBeenCalledWith([
|
||||
{ action: 'action-0', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-1', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-2', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-3', conditions: [], fields: null, role: 1, subject: null },
|
||||
{ action: 'action-4', conditions: ['cond'], fields: null, role: 1, subject: null },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
const _ = require('lodash');
|
||||
const { flatMap, filter } = require('lodash/fp');
|
||||
const pmap = require('p-map');
|
||||
const { validatePermissionsExist } = require('../validation/permission');
|
||||
const createPermissionsManager = require('./permission/permissions-manager');
|
||||
const createConditionProvider = require('./permission/condition-provider');
|
||||
const createPermissionEngine = require('./permission/engine');
|
||||
@ -15,20 +14,6 @@ const { createPermission } = require('../domain/permission');
|
||||
const conditionProvider = createConditionProvider();
|
||||
const engine = createPermissionEngine(conditionProvider);
|
||||
|
||||
const fieldsToCompare = ['action', 'subject', 'fields', 'conditions'];
|
||||
const getPermissionWithSortedFields = perm => {
|
||||
const sortedPerm = _.cloneDeep(perm);
|
||||
if (Array.isArray(sortedPerm.fields)) {
|
||||
sortedPerm.fields.sort();
|
||||
}
|
||||
return sortedPerm;
|
||||
};
|
||||
const arePermissionsEqual = (perm1, perm2) =>
|
||||
_.isEqual(
|
||||
_.pick(getPermissionWithSortedFields(perm1), fieldsToCompare),
|
||||
_.pick(getPermissionWithSortedFields(perm2), fieldsToCompare)
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes unwanted fields from a permission
|
||||
* @param perm
|
||||
@ -62,9 +47,7 @@ const deleteByIds = ids => {
|
||||
* @param permissions
|
||||
* @returns {Promise<*[]|*>}
|
||||
*/
|
||||
const createMany = async (roleId, permissions) => {
|
||||
permissions.forEach(p => p.role = roleId);
|
||||
|
||||
const createMany = async permissions => {
|
||||
return strapi.query('permission', 'admin').createMany(permissions);
|
||||
};
|
||||
|
||||
@ -87,57 +70,6 @@ const find = (params = {}) => {
|
||||
return strapi.query('permission', 'admin').find(params, []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign permissions to a role
|
||||
* @param {string|int} roleId - role ID
|
||||
* @param {Array<Permission{action,subject,fields,conditions}>} permissions - permissions to assign to the role
|
||||
*/
|
||||
const assign = async (roleId, permissions = []) => {
|
||||
try {
|
||||
await validatePermissionsExist(permissions);
|
||||
} catch (err) {
|
||||
throw strapi.errors.badRequest('ValidationError', err);
|
||||
}
|
||||
|
||||
const superAdmin = await strapi.admin.services.role.getSuperAdmin();
|
||||
const isSuperAdmin = superAdmin && superAdmin.id === roleId;
|
||||
|
||||
const permissionsWithRole = permissions.map(permission =>
|
||||
createPermission({
|
||||
...permission,
|
||||
conditions: strapi.admin.services.condition.removeUnkownConditionIds(permission.conditions),
|
||||
role: roleId,
|
||||
})
|
||||
);
|
||||
|
||||
const existingPermissions = await find({ role: roleId, _limit: -1 });
|
||||
const permissionsToAdd = _.differenceWith(
|
||||
permissionsWithRole,
|
||||
existingPermissions,
|
||||
arePermissionsEqual
|
||||
);
|
||||
const permissionsToDelete = _.differenceWith(
|
||||
existingPermissions,
|
||||
permissionsWithRole,
|
||||
arePermissionsEqual
|
||||
);
|
||||
const permissionsToReturn = _.differenceBy(existingPermissions, permissionsToDelete, 'id');
|
||||
|
||||
if (permissionsToDelete.length > 0) {
|
||||
await deleteByIds(permissionsToDelete.map(p => p.id));
|
||||
}
|
||||
if (permissionsToAdd.length > 0) {
|
||||
const createdPermissions = await createMany(roleId, permissionsToAdd);
|
||||
permissionsToReturn.push(...createdPermissions.map(p => ({ ...p, role: p.role.id })));
|
||||
}
|
||||
|
||||
if (!isSuperAdmin && (permissionsToAdd.length || permissionsToDelete.length)) {
|
||||
await strapi.admin.services.metrics.sendDidUpdateRolePermissions();
|
||||
}
|
||||
|
||||
return permissionsToReturn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find all permissions for a user
|
||||
* @param roles
|
||||
@ -250,49 +182,16 @@ const ensureBoundPermissionsInDatabase = async () => {
|
||||
fields: BOUND_ACTIONS_FOR_FIELDS.includes(action) ? fields : null,
|
||||
})
|
||||
);
|
||||
await createMany(editorRole.id, permissions);
|
||||
await createMany(permissions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset super admin permissions (giving it all permissions)
|
||||
* @returns {Promise<>}
|
||||
*/
|
||||
const resetSuperAdminPermissions = async () => {
|
||||
const superAdminRole = await strapi.admin.services.role.getSuperAdmin();
|
||||
if (!superAdminRole) {
|
||||
return;
|
||||
}
|
||||
|
||||
const allActions = strapi.admin.services.permission.actionProvider.getAll();
|
||||
const contentTypesActions = allActions.filter(a => a.section === 'contentTypes');
|
||||
|
||||
const permissions = strapi.admin.services['content-type'].getPermissionsWithNestedFields(
|
||||
contentTypesActions
|
||||
);
|
||||
|
||||
const otherActions = allActions.filter(a => a.section !== 'contentTypes');
|
||||
otherActions.forEach(action => {
|
||||
if (action.subjects) {
|
||||
const newPerms = action.subjects.map(subject =>
|
||||
createPermission({ action: action.actionId, subject })
|
||||
);
|
||||
permissions.push(...newPerms);
|
||||
} else {
|
||||
permissions.push(createPermission({ action: action.actionId }));
|
||||
}
|
||||
});
|
||||
|
||||
await assign(superAdminRole.id, permissions);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createMany,
|
||||
find,
|
||||
deleteByRolesIds,
|
||||
deleteByIds,
|
||||
assign,
|
||||
sanitizePermission,
|
||||
findUserPermissions,
|
||||
actionProvider,
|
||||
@ -300,6 +199,5 @@ module.exports = {
|
||||
engine,
|
||||
conditionProvider,
|
||||
cleanPermissionInDatabase,
|
||||
resetSuperAdminPermissions,
|
||||
ensureBoundPermissionsInDatabase,
|
||||
};
|
||||
|
||||
@ -5,6 +5,7 @@ const { set } = require('lodash/fp');
|
||||
const { generateTimestampCode, stringIncludes } = require('strapi-utils');
|
||||
const { SUPER_ADMIN_CODE } = require('./constants');
|
||||
const { createPermission } = require('../domain/permission');
|
||||
const { validatePermissionsExist } = require('../validation/permission');
|
||||
|
||||
const ACTIONS = {
|
||||
publish: 'plugins::content-manager.explorer.publish',
|
||||
@ -14,6 +15,22 @@ const sanitizeRole = role => {
|
||||
return _.omit(role, ['users', 'permissions']);
|
||||
};
|
||||
|
||||
const fieldsToCompare = ['action', 'subject', 'fields', 'conditions'];
|
||||
|
||||
const getPermissionWithSortedFields = perm => {
|
||||
const sortedPerm = _.cloneDeep(perm);
|
||||
if (Array.isArray(sortedPerm.fields)) {
|
||||
sortedPerm.fields.sort();
|
||||
}
|
||||
return sortedPerm;
|
||||
};
|
||||
|
||||
const arePermissionsEqual = (perm1, perm2) =>
|
||||
_.isEqual(
|
||||
_.pick(getPermissionWithSortedFields(perm1), fieldsToCompare),
|
||||
_.pick(getPermissionWithSortedFields(perm2), fieldsToCompare)
|
||||
);
|
||||
|
||||
/**
|
||||
* Create and save a role in database
|
||||
* @param attributes A partial role object
|
||||
@ -233,8 +250,8 @@ const createRolesIfNoneExist = async ({ createPermissionsForAdmin = false } = {}
|
||||
authorPermissions.push(...getDefaultPluginPermissions({ isAuthor: true }));
|
||||
|
||||
// assign permissions to roles
|
||||
await strapi.admin.services.permission.createMany(editorRole.id, editorPermissions);
|
||||
await strapi.admin.services.permission.createMany(authorRole.id, authorPermissions);
|
||||
await addPermissions(editorRole.id, editorPermissions);
|
||||
await addPermissions(authorRole.id, authorPermissions);
|
||||
|
||||
if (createPermissionsForAdmin) {
|
||||
await strapi.admin.services.permission.resetSuperAdminPermissions();
|
||||
@ -268,6 +285,101 @@ const displayWarningIfNoSuperAdmin = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign permissions to a role
|
||||
* @param {string|int} roleId - role ID
|
||||
* @param {Array<Permission{action,subject,fields,conditions}>} permissions - permissions to assign to the role
|
||||
*/
|
||||
const assignPermissions = async (roleId, permissions = []) => {
|
||||
try {
|
||||
await validatePermissionsExist(permissions);
|
||||
} catch (err) {
|
||||
throw strapi.errors.badRequest('ValidationError', err);
|
||||
}
|
||||
|
||||
const superAdmin = await strapi.admin.services.role.getSuperAdmin();
|
||||
const isSuperAdmin = superAdmin && superAdmin.id === roleId;
|
||||
|
||||
const permissionsWithRole = permissions.map(permission =>
|
||||
createPermission({
|
||||
...permission,
|
||||
conditions: strapi.admin.services.condition.removeUnkownConditionIds(permission.conditions),
|
||||
role: roleId,
|
||||
})
|
||||
);
|
||||
|
||||
const existingPermissions = await strapi.admin.services.permission.find({
|
||||
role: roleId,
|
||||
_limit: -1,
|
||||
});
|
||||
const permissionsToAdd = _.differenceWith(
|
||||
permissionsWithRole,
|
||||
existingPermissions,
|
||||
arePermissionsEqual
|
||||
);
|
||||
const permissionsToDelete = _.differenceWith(
|
||||
existingPermissions,
|
||||
permissionsWithRole,
|
||||
arePermissionsEqual
|
||||
);
|
||||
const permissionsToReturn = _.differenceBy(existingPermissions, permissionsToDelete, 'id');
|
||||
|
||||
if (permissionsToDelete.length > 0) {
|
||||
await strapi.admin.services.permission.deleteByIds(permissionsToDelete.map(p => p.id));
|
||||
}
|
||||
|
||||
if (permissionsToAdd.length > 0) {
|
||||
const createdPermissions = await addPermissions(roleId, permissionsToAdd);
|
||||
permissionsToReturn.push(...createdPermissions.map(p => ({ ...p, role: p.role.id })));
|
||||
}
|
||||
|
||||
if (!isSuperAdmin && (permissionsToAdd.length || permissionsToDelete.length)) {
|
||||
await strapi.admin.services.metrics.sendDidUpdateRolePermissions();
|
||||
}
|
||||
|
||||
return permissionsToReturn;
|
||||
};
|
||||
|
||||
const addPermissions = async (roleId, permissions) => {
|
||||
permissions.forEach(p => {
|
||||
p.role = roleId;
|
||||
});
|
||||
|
||||
return strapi.admin.services.permission.createMany(permissions);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset super admin permissions (giving it all permissions)
|
||||
* @returns {Promise<>}
|
||||
*/
|
||||
const resetSuperAdminPermissions = async () => {
|
||||
const superAdminRole = await strapi.admin.services.role.getSuperAdmin();
|
||||
if (!superAdminRole) {
|
||||
return;
|
||||
}
|
||||
|
||||
const allActions = strapi.admin.services.permission.actionProvider.getAll();
|
||||
const contentTypesActions = allActions.filter(a => a.section === 'contentTypes');
|
||||
|
||||
const permissions = strapi.admin.services['content-type'].getPermissionsWithNestedFields(
|
||||
contentTypesActions
|
||||
);
|
||||
|
||||
const otherActions = allActions.filter(a => a.section !== 'contentTypes');
|
||||
otherActions.forEach(action => {
|
||||
if (action.subjects) {
|
||||
const newPerms = action.subjects.map(subject =>
|
||||
createPermission({ action: action.actionId, subject })
|
||||
);
|
||||
permissions.push(...newPerms);
|
||||
} else {
|
||||
permissions.push(createPermission({ action: action.actionId }));
|
||||
}
|
||||
});
|
||||
|
||||
await assignPermissions(superAdminRole.id, permissions);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
sanitizeRole,
|
||||
create,
|
||||
@ -284,4 +396,7 @@ module.exports = {
|
||||
getSuperAdminWithUsersCount,
|
||||
createRolesIfNoneExist,
|
||||
displayWarningIfNoSuperAdmin,
|
||||
addPermissions,
|
||||
assignPermissions,
|
||||
resetSuperAdminPermissions,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user