mirror of
https://github.com/strapi/strapi.git
synced 2025-12-12 23:44:08 +00:00
add route GET /admin/permissions
Signed-off-by: Pierre Noël <petersg83@gmail.com>
This commit is contained in:
parent
5fffffa72d
commit
ae0dcb9745
@ -194,6 +194,14 @@
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/permissions",
|
||||
"handler": "permission.getAll",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
15
packages/strapi-admin/controllers/permission.js
Normal file
15
packages/strapi-admin/controllers/permission.js
Normal file
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Returns every permissions, in nested format
|
||||
* @param {KoaContext} ctx - koa context
|
||||
*/
|
||||
async getAll(ctx) {
|
||||
const allWithNestedFormat = await strapi.admin.permissionProvider.getAllWithNestedFormat();
|
||||
|
||||
ctx.body = {
|
||||
data: allWithNestedFormat,
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -4,7 +4,7 @@ const { yup, formatYupErrors } = require('strapi-utils');
|
||||
|
||||
const handleReject = error => Promise.reject(formatYupErrors(error));
|
||||
|
||||
const roleCreateUpdateSchema = yup
|
||||
const roleCreateSchema = yup
|
||||
.object()
|
||||
.shape({
|
||||
name: yup
|
||||
@ -15,6 +15,14 @@ const roleCreateUpdateSchema = yup
|
||||
})
|
||||
.noUnknown();
|
||||
|
||||
const roleUpdateSchema = yup
|
||||
.object()
|
||||
.shape({
|
||||
name: yup.string().min(1),
|
||||
description: yup.string().nullable(),
|
||||
})
|
||||
.noUnknown();
|
||||
|
||||
const roleDeleteSchema = yup
|
||||
.object()
|
||||
.shape({
|
||||
@ -27,15 +35,11 @@ const roleDeleteSchema = yup
|
||||
.noUnknown();
|
||||
|
||||
const validateRoleCreateInput = async data => {
|
||||
return roleCreateUpdateSchema
|
||||
.validate(data, { strict: true, abortEarly: false })
|
||||
.catch(handleReject);
|
||||
return roleCreateSchema.validate(data, { strict: true, abortEarly: false }).catch(handleReject);
|
||||
};
|
||||
|
||||
const validateRoleUpdateInput = async data => {
|
||||
return roleCreateUpdateSchema
|
||||
.validate(data, { strict: true, abortEarly: false })
|
||||
.catch(handleReject);
|
||||
return roleUpdateSchema.validate(data, { strict: true, abortEarly: false }).catch(handleReject);
|
||||
};
|
||||
|
||||
const validateRoleDeleteInput = async data => {
|
||||
|
||||
@ -25,7 +25,7 @@ describe('Permission Provider Service', () => {
|
||||
};
|
||||
|
||||
await permissionProvider.register([permission]);
|
||||
const permissions = permissionProvider.getPermissions();
|
||||
const permissions = permissionProvider.getAll();
|
||||
|
||||
expect(permissions).toMatchObject([
|
||||
{
|
||||
@ -46,7 +46,7 @@ describe('Permission Provider Service', () => {
|
||||
};
|
||||
|
||||
await permissionProvider.register([permission]);
|
||||
const permissions = permissionProvider.getPermissions();
|
||||
const permissions = permissionProvider.getAll();
|
||||
|
||||
expect(permissions).toMatchObject([
|
||||
{
|
||||
@ -68,7 +68,7 @@ describe('Permission Provider Service', () => {
|
||||
};
|
||||
|
||||
await permissionProvider.register([permission]);
|
||||
const permissions = permissionProvider.getPermissions();
|
||||
const permissions = permissionProvider.getAll();
|
||||
|
||||
expect(permissions).toMatchObject([
|
||||
{
|
||||
@ -89,7 +89,7 @@ describe('Permission Provider Service', () => {
|
||||
};
|
||||
|
||||
await permissionProvider.register([permission]);
|
||||
const permissions = permissionProvider.getPermissions();
|
||||
const permissions = permissionProvider.getAll();
|
||||
|
||||
expect(permissions).toMatchObject([
|
||||
{
|
||||
@ -136,13 +136,8 @@ describe('Permission Provider Service', () => {
|
||||
category: 'plugins and marketplace',
|
||||
};
|
||||
|
||||
await permissionProvider.register([permission]);
|
||||
|
||||
expect(global.strapi.stopWithError).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
name: 'ValidationError',
|
||||
message: '[0].pluginName is not an existing plugin',
|
||||
})
|
||||
expect(() => permissionProvider.register([permission])).toThrow(
|
||||
'[0].pluginName is not an existing plugin'
|
||||
);
|
||||
});
|
||||
|
||||
@ -154,13 +149,8 @@ describe('Permission Provider Service', () => {
|
||||
section: 'settings',
|
||||
};
|
||||
|
||||
await permissionProvider.register([permission]);
|
||||
|
||||
expect(global.strapi.stopWithError).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
name: 'ValidationError',
|
||||
message: '[0].category is a required field',
|
||||
})
|
||||
expect(() => permissionProvider.register([permission])).toThrow(
|
||||
'[0].category is a required field'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -22,8 +22,10 @@ describe('Permission Service', () => {
|
||||
test('Delete previous permissions', async () => {
|
||||
const deleteFn = jest.fn(() => Promise.resolve([]));
|
||||
const create = jest.fn(() => Promise.resolve({}));
|
||||
const getAll = jest.fn(() => []);
|
||||
|
||||
global.strapi = {
|
||||
admin: { permissionProvider: { getAll } },
|
||||
query() {
|
||||
return { delete: deleteFn, create };
|
||||
},
|
||||
@ -37,8 +39,14 @@ describe('Permission Service', () => {
|
||||
test('Create new permissions', async () => {
|
||||
const deleteFn = jest.fn(() => Promise.resolve([]));
|
||||
const create = jest.fn(() => Promise.resolve({}));
|
||||
const getAll = jest.fn(() =>
|
||||
Array(5)
|
||||
.fill(0)
|
||||
.map((v, i) => ({ permissionId: `action-${i}` }))
|
||||
);
|
||||
|
||||
global.strapi = {
|
||||
admin: { permissionProvider: { getAll } },
|
||||
query() {
|
||||
return { delete: deleteFn, create };
|
||||
},
|
||||
@ -46,13 +54,13 @@ describe('Permission Service', () => {
|
||||
|
||||
const permissions = Array(5)
|
||||
.fill(0)
|
||||
.map(() => ({ action: 'test' }));
|
||||
.map((v, i) => ({ action: `action-${i}` }));
|
||||
|
||||
await permissionService.assign(1, permissions);
|
||||
|
||||
expect(create).toHaveBeenCalledTimes(5);
|
||||
expect(create).toHaveBeenCalledWith({
|
||||
action: 'test',
|
||||
expect(create).toHaveBeenNthCalledWith(1, {
|
||||
action: 'action-0',
|
||||
role: 1,
|
||||
conditions: [],
|
||||
fields: [],
|
||||
|
||||
@ -4,7 +4,7 @@ const { validateRegisterProviderPermission } = require('../validation/permission
|
||||
|
||||
const calculateId = permission => {
|
||||
let id = '';
|
||||
const sanitizedname = _.snakeCase(permission.name).replace('_', '.');
|
||||
const sanitizedname = _.snakeCase(permission.name).replace(/_/g, '.');
|
||||
if (permission.pluginName === 'admin') {
|
||||
id = `admin::${sanitizedname}`;
|
||||
} else {
|
||||
@ -13,12 +13,12 @@ const calculateId = permission => {
|
||||
return id;
|
||||
};
|
||||
|
||||
const formatPermission = permission => {
|
||||
const formatPermissionToBeRegistered = permission => {
|
||||
const formattedPermission = _.clone(permission);
|
||||
formattedPermission.permissionId = calculateId(permission);
|
||||
formattedPermission.conditions = permission.conditions || [];
|
||||
|
||||
if (permission.section === 'settings') {
|
||||
if (['settings', 'plugins'].includes(permission.section)) {
|
||||
formattedPermission.subCategory = permission.subCategory || 'general';
|
||||
}
|
||||
|
||||
@ -39,18 +39,58 @@ const getDuplicatedIds = permissions => {
|
||||
return duplicatedIds;
|
||||
};
|
||||
|
||||
const formatPermissionsToNestedFormat = formattedPermissions => {
|
||||
const sections = formattedPermissions.reduce((result, p) => {
|
||||
const checkboxItem = {
|
||||
displayName: p.displayName,
|
||||
action: p.permissionId,
|
||||
};
|
||||
|
||||
switch (p.section) {
|
||||
case 'contentTypes':
|
||||
checkboxItem.subjects = p.subjects;
|
||||
break;
|
||||
case 'plugins':
|
||||
checkboxItem.subCategory = p.subCategory;
|
||||
checkboxItem.plugin = `plugin::${p.pluginName}`;
|
||||
break;
|
||||
case 'settings':
|
||||
checkboxItem.category = p.category;
|
||||
checkboxItem.subCategory = p.subCategory;
|
||||
break;
|
||||
case 'default':
|
||||
throw new Error(`Unknown section ${p.section}`);
|
||||
}
|
||||
|
||||
result[p.section] = result[p.section] || [];
|
||||
result[p.section].push(checkboxItem);
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
sections,
|
||||
conditions: [],
|
||||
};
|
||||
};
|
||||
|
||||
class PermissionProvider {
|
||||
constructor() {
|
||||
this.permissions = [];
|
||||
this.permissionsWithNestedFormat = {};
|
||||
}
|
||||
|
||||
getPermissions() {
|
||||
getAll() {
|
||||
return _.cloneDeep(this.permissions);
|
||||
}
|
||||
|
||||
getAllWithNestedFormat() {
|
||||
return _.cloneDeep(this.permissionsWithNestedFormat);
|
||||
}
|
||||
|
||||
register(newPermissions) {
|
||||
validateRegisterProviderPermission(newPermissions);
|
||||
const newPermissionsWithIds = newPermissions.map(formatPermission);
|
||||
const newPermissionsWithIds = newPermissions.map(formatPermissionToBeRegistered);
|
||||
const mergedPermissions = [...this.permissions, ...newPermissionsWithIds];
|
||||
const duplicatedIds = getDuplicatedIds(mergedPermissions);
|
||||
|
||||
@ -65,6 +105,7 @@ class PermissionProvider {
|
||||
}
|
||||
|
||||
this.permissions = mergedPermissions;
|
||||
this.permissionsWithNestedFormat = formatPermissionsToNestedFormat(mergedPermissions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,9 +26,20 @@ const find = (params = {}) => {
|
||||
* @param {Array<Permission{action,subject,fields,conditions}>} permissions - permissions to assign to the role
|
||||
*/
|
||||
const assign = async (roleID, permissions = []) => {
|
||||
// TODO: verify the data once we have the permissions registry
|
||||
const existingPermissions = strapi.admin.permissionProvider.getAll();
|
||||
for (let permission of permissions) {
|
||||
const permissionExists = existingPermissions.find(
|
||||
ep =>
|
||||
ep.permissionId === permission.action &&
|
||||
(ep.section !== 'contentTypes' || ep.subjects.includes(permission.subject))
|
||||
);
|
||||
if (!permissionExists) {
|
||||
throw strapi.errors.badRequest(
|
||||
`ValidationError', 'This permission doesn't exist: ${JSON.stringify(permission)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// clear previous permissions
|
||||
await strapi.query('permission', 'admin').delete({ role: roleID });
|
||||
|
||||
const permissionsWithRole = permissions.map(permission => {
|
||||
|
||||
22
packages/strapi-admin/test/admin-permission.test.e2e.js
Normal file
22
packages/strapi-admin/test/admin-permission.test.e2e.js
Normal file
@ -0,0 +1,22 @@
|
||||
const { registerAndLogin } = require('../../../test/helpers/auth');
|
||||
const { createAuthRequest } = require('../../../test/helpers/request');
|
||||
const expectedPermissions = require('./permissions');
|
||||
|
||||
let rq;
|
||||
|
||||
describe('Role CRUD End to End', () => {
|
||||
beforeAll(async () => {
|
||||
const token = await registerAndLogin();
|
||||
rq = createAuthRequest(token);
|
||||
}, 60000);
|
||||
|
||||
test('Can get the existing permissions', async () => {
|
||||
let res = await rq({
|
||||
url: '/admin/permissions',
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.data).toMatchObject(expectedPermissions);
|
||||
});
|
||||
});
|
||||
@ -355,11 +355,11 @@ describe('Role CRUD End to End', () => {
|
||||
body: {
|
||||
permissions: [
|
||||
{
|
||||
action: 'test.action',
|
||||
action: 'plugins::users-permissions.roles.update',
|
||||
},
|
||||
{
|
||||
action: 'test.action2',
|
||||
subject: 'model1',
|
||||
action: 'plugins::content-manager.create',
|
||||
subject: 'plugins::upload.file',
|
||||
conditions: ['isOwner'],
|
||||
},
|
||||
],
|
||||
@ -384,6 +384,29 @@ describe('Role CRUD End to End', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("can't assign non-existing permissions on role", async () => {
|
||||
const res = await rq({
|
||||
url: `/admin/roles/${data.rolesWithoutUsers[0].id}/permissions`,
|
||||
method: 'PUT',
|
||||
body: {
|
||||
permissions: [
|
||||
{
|
||||
action: 'non.existing.action',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
console.log('res.body', res.body);
|
||||
expect(res.body).toMatchObject({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message:
|
||||
'ValidationError\', \'This permission doesn\'t exist: {"action":"non.existing.action"}',
|
||||
});
|
||||
});
|
||||
|
||||
test('get permissions role', async () => {
|
||||
const res = await rq({
|
||||
url: `/admin/roles/${data.rolesWithoutUsers[0].id}/permissions`,
|
||||
|
||||
285
packages/strapi-admin/test/permissions.json
Normal file
285
packages/strapi-admin/test/permissions.json
Normal file
@ -0,0 +1,285 @@
|
||||
{
|
||||
"sections": {
|
||||
"settings": [
|
||||
{
|
||||
"displayName": "Can access to the marketplace",
|
||||
"action": "admin::marketplace.read",
|
||||
"category": "plugins and marketplace",
|
||||
"subCategory": "marketplace"
|
||||
},
|
||||
{
|
||||
"displayName": "Install (only for dev env)",
|
||||
"action": "admin::marketplace.plugins.install",
|
||||
"category": "plugins and marketplace",
|
||||
"subCategory": "plugins"
|
||||
},
|
||||
{
|
||||
"displayName": "Uninstall (only for dev env)",
|
||||
"action": "admin::marketplace.plugins.uninstall",
|
||||
"category": "plugins and marketplace",
|
||||
"subCategory": "plugins"
|
||||
},
|
||||
{
|
||||
"displayName": "Create",
|
||||
"action": "admin::webhooks.create",
|
||||
"category": "webhooks",
|
||||
"subCategory": "general"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "admin::webhooks.read",
|
||||
"category": "webhooks",
|
||||
"subCategory": "general"
|
||||
},
|
||||
{
|
||||
"displayName": "Update",
|
||||
"action": "admin::webhooks.update",
|
||||
"category": "webhooks",
|
||||
"subCategory": "general"
|
||||
},
|
||||
{
|
||||
"displayName": "Delete",
|
||||
"action": "admin::webhooks.delete",
|
||||
"category": "webhooks",
|
||||
"subCategory": "general"
|
||||
},
|
||||
{
|
||||
"displayName": "Create (invite)",
|
||||
"action": "admin::users.create",
|
||||
"category": "users and roles",
|
||||
"subCategory": "users"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "admin::users.read",
|
||||
"category": "users and roles",
|
||||
"subCategory": "users"
|
||||
},
|
||||
{
|
||||
"displayName": "Update",
|
||||
"action": "admin::users.update",
|
||||
"category": "users and roles",
|
||||
"subCategory": "users"
|
||||
},
|
||||
{
|
||||
"displayName": "Delete",
|
||||
"action": "admin::users.delete",
|
||||
"category": "users and roles",
|
||||
"subCategory": "users"
|
||||
},
|
||||
{
|
||||
"displayName": "Create",
|
||||
"action": "admin::roles.create",
|
||||
"category": "users and roles",
|
||||
"subCategory": "roles"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "admin::roles.read",
|
||||
"category": "users and roles",
|
||||
"subCategory": "roles"
|
||||
},
|
||||
{
|
||||
"displayName": "Update",
|
||||
"action": "admin::roles.update",
|
||||
"category": "users and roles",
|
||||
"subCategory": "roles"
|
||||
},
|
||||
{
|
||||
"displayName": "Delete",
|
||||
"action": "admin::roles.delete",
|
||||
"category": "users and roles",
|
||||
"subCategory": "roles"
|
||||
}
|
||||
],
|
||||
"plugins": [
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "plugins::content-type-builder.read",
|
||||
"subCategory": "general",
|
||||
"plugin": "plugin::content-type-builder"
|
||||
},
|
||||
{
|
||||
"displayName": "Can access to the Documentation",
|
||||
"action": "plugins::documentation.read",
|
||||
"subCategory": "general",
|
||||
"plugin": "plugin::documentation"
|
||||
},
|
||||
{
|
||||
"displayName": "Update and delete",
|
||||
"action": "plugins::documentation.settings.update",
|
||||
"subCategory": "settings",
|
||||
"plugin": "plugin::documentation"
|
||||
},
|
||||
{
|
||||
"displayName": "Regenerate",
|
||||
"action": "plugins::documentation.settings.regenerate",
|
||||
"subCategory": "settings",
|
||||
"plugin": "plugin::documentation"
|
||||
},
|
||||
{
|
||||
"displayName": "Can access to the Media Library",
|
||||
"action": "plugins::upload.read",
|
||||
"subCategory": "general",
|
||||
"plugin": "plugin::upload"
|
||||
},
|
||||
{
|
||||
"displayName": "Create (upload)",
|
||||
"action": "plugins::upload.assets.create",
|
||||
"subCategory": "assets",
|
||||
"plugin": "plugin::upload"
|
||||
},
|
||||
{
|
||||
"displayName": "Update (crop, details, replace)",
|
||||
"action": "plugins::upload.assets.update",
|
||||
"subCategory": "assets",
|
||||
"plugin": "plugin::upload"
|
||||
},
|
||||
{
|
||||
"displayName": "Download",
|
||||
"action": "plugins::upload.assets.download",
|
||||
"subCategory": "assets",
|
||||
"plugin": "plugin::upload"
|
||||
},
|
||||
{
|
||||
"displayName": "Copy link",
|
||||
"action": "plugins::upload.assets.copy.link",
|
||||
"subCategory": "assets",
|
||||
"plugin": "plugin::upload"
|
||||
},
|
||||
{
|
||||
"displayName": "Configure view",
|
||||
"action": "plugins::content-manager.single.types.configure.view",
|
||||
"subCategory": "single types",
|
||||
"plugin": "plugin::content-manager"
|
||||
},
|
||||
{
|
||||
"displayName": "Configure view",
|
||||
"action": "plugins::content-manager.collection.types.configure.view",
|
||||
"subCategory": "collection types",
|
||||
"plugin": "plugin::content-manager"
|
||||
},
|
||||
{
|
||||
"displayName": "Configure Layout",
|
||||
"action": "plugins::content-manager.components.configure.layout",
|
||||
"subCategory": "components",
|
||||
"plugin": "plugin::content-manager"
|
||||
},
|
||||
{
|
||||
"displayName": "Create",
|
||||
"action": "plugins::users-permissions.roles.create",
|
||||
"subCategory": "roles",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "plugins::users-permissions.roles.read",
|
||||
"subCategory": "roles",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Update",
|
||||
"action": "plugins::users-permissions.roles.update",
|
||||
"subCategory": "roles",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Delete",
|
||||
"action": "plugins::users-permissions.roles.delete",
|
||||
"subCategory": "roles",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "plugins::users-permissions.providers.read",
|
||||
"subCategory": "providers",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Edit",
|
||||
"action": "plugins::users-permissions.providers.update",
|
||||
"subCategory": "providers",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "plugins::users-permissions.email.templates.read",
|
||||
"subCategory": "emailTemplates",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Edit",
|
||||
"action": "plugins::users-permissions.email.templates.update",
|
||||
"subCategory": "emailTemplates",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "plugins::users-permissions.advanced.settings.read",
|
||||
"subCategory": "advancedSettings",
|
||||
"plugin": "plugin::users-permissions"
|
||||
},
|
||||
{
|
||||
"displayName": "Edit",
|
||||
"action": "plugins::users-permissions.advanced.settings.update",
|
||||
"subCategory": "advancedSettings",
|
||||
"plugin": "plugin::users-permissions"
|
||||
}
|
||||
],
|
||||
"contentTypes": [
|
||||
{
|
||||
"displayName": "Create",
|
||||
"action": "plugins::content-manager.create",
|
||||
"subjects": [
|
||||
"strapi::permission",
|
||||
"strapi::role",
|
||||
"strapi::user",
|
||||
"plugins::users-permissions.permission",
|
||||
"plugins::users-permissions.role",
|
||||
"plugins::users-permissions.user",
|
||||
"plugins::upload.file"
|
||||
]
|
||||
},
|
||||
{
|
||||
"displayName": "Read",
|
||||
"action": "plugins::content-manager.read",
|
||||
"subjects": [
|
||||
"strapi::permission",
|
||||
"strapi::role",
|
||||
"strapi::user",
|
||||
"plugins::users-permissions.permission",
|
||||
"plugins::users-permissions.role",
|
||||
"plugins::users-permissions.user",
|
||||
"plugins::upload.file"
|
||||
]
|
||||
},
|
||||
{
|
||||
"displayName": "Update",
|
||||
"action": "plugins::content-manager.update",
|
||||
"subjects": [
|
||||
"strapi::permission",
|
||||
"strapi::role",
|
||||
"strapi::user",
|
||||
"plugins::users-permissions.permission",
|
||||
"plugins::users-permissions.role",
|
||||
"plugins::users-permissions.user",
|
||||
"plugins::upload.file"
|
||||
]
|
||||
},
|
||||
{
|
||||
"displayName": "Delete",
|
||||
"action": "plugins::content-manager.delete",
|
||||
"subjects": [
|
||||
"strapi::permission",
|
||||
"strapi::role",
|
||||
"strapi::user",
|
||||
"plugins::users-permissions.permission",
|
||||
"plugins::users-permissions.role",
|
||||
"plugins::users-permissions.user",
|
||||
"plugins::upload.file"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"conditions": []
|
||||
}
|
||||
@ -15,29 +15,29 @@ const registerProviderPermissionSchema = yup
|
||||
.string()
|
||||
.oneOf(['contentTypes', 'plugins', 'settings'])
|
||||
.required(),
|
||||
pluginName: yup.mixed().when('section', {
|
||||
pluginName: yup
|
||||
.string()
|
||||
.required()
|
||||
.isAPluginName(),
|
||||
subjects: yup.mixed().when('section', {
|
||||
is: 'contentTypes',
|
||||
then: yup.mixed().oneOf([undefined]),
|
||||
otherwise: yup
|
||||
.string()
|
||||
.required()
|
||||
.isAPluginName(),
|
||||
then: yup
|
||||
.array()
|
||||
.of(yup.string().isAContentTypeId())
|
||||
.required(),
|
||||
otherwise: yup.mixed().oneOf([undefined]),
|
||||
}),
|
||||
displayName: yup.string().required(),
|
||||
category: yup
|
||||
.mixed()
|
||||
.when('section', {
|
||||
is: val => ['plugins', 'contentTypes'].includes(val),
|
||||
then: yup.mixed().oneOf([undefined]),
|
||||
otherwise: yup.string().required(),
|
||||
}),
|
||||
subCategory: yup
|
||||
.mixed()
|
||||
.when('section', {
|
||||
is: 'contentTypes',
|
||||
then: yup.mixed().oneOf([undefined]),
|
||||
otherwise: yup.string(),
|
||||
}),
|
||||
category: yup.mixed().when('section', {
|
||||
is: val => ['plugins', 'contentTypes'].includes(val),
|
||||
then: yup.mixed().oneOf([undefined]),
|
||||
otherwise: yup.string().required(),
|
||||
}),
|
||||
subCategory: yup.mixed().when('section', {
|
||||
is: 'contentTypes',
|
||||
then: yup.mixed().oneOf([undefined]),
|
||||
otherwise: yup.string(),
|
||||
}),
|
||||
conditions: yup.array().of(yup.string()),
|
||||
})
|
||||
.noUnknown()
|
||||
@ -47,7 +47,11 @@ const validateRegisterProviderPermission = data => {
|
||||
try {
|
||||
registerProviderPermissionSchema.validateSync(data, { strict: true, abortEarly: false });
|
||||
} catch (e) {
|
||||
strapi.stopWithError(e);
|
||||
if (e.errors.length > 0) {
|
||||
throw new yup.ValidationError(e.errors.join(', '));
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ module.exports = () => {
|
||||
async function syncSchemas() {
|
||||
await syncContentTypesSchemas();
|
||||
await syncComponentsSchemas();
|
||||
registerPermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,14 +59,10 @@ async function updateContentTypes(configurations) {
|
||||
const contentTypesToDelete = _.difference(DBUIDs, currentUIDS);
|
||||
|
||||
// delette old schemas
|
||||
await Promise.all(
|
||||
contentTypesToDelete.map(uid => contentTypeService.deleteConfiguration(uid))
|
||||
);
|
||||
await Promise.all(contentTypesToDelete.map(uid => contentTypeService.deleteConfiguration(uid)));
|
||||
|
||||
// create new schemas
|
||||
await Promise.all(
|
||||
contentTypesToAdd.map(uid => generateNewConfiguration(uid))
|
||||
);
|
||||
await Promise.all(contentTypesToAdd.map(uid => generateNewConfiguration(uid)));
|
||||
|
||||
// update current schemas
|
||||
await Promise.all(contentTypesToUpdate.map(uid => updateConfiguration(uid)));
|
||||
@ -102,9 +99,7 @@ async function syncComponentsSchemas() {
|
||||
const componentsToDelete = _.difference(DBUIDs, realUIDs);
|
||||
|
||||
// delette old schemas
|
||||
await Promise.all(
|
||||
componentsToDelete.map(uid => componentService.deleteConfiguration(uid))
|
||||
);
|
||||
await Promise.all(componentsToDelete.map(uid => componentService.deleteConfiguration(uid)));
|
||||
|
||||
// create new schemas
|
||||
await Promise.all(componentsToAdd.map(uid => generateNewConfiguration(uid)));
|
||||
@ -112,3 +107,61 @@ async function syncComponentsSchemas() {
|
||||
// update current schemas
|
||||
await Promise.all(componentsToUpdate.map(uid => updateConfiguration(uid)));
|
||||
}
|
||||
|
||||
function registerPermissions() {
|
||||
const contentTypesUids = Object.keys(strapi.contentTypes); // TODO: filter to not have internal contentTypes
|
||||
|
||||
const permissions = [
|
||||
{
|
||||
section: 'contentTypes',
|
||||
displayName: 'Create',
|
||||
name: 'create',
|
||||
pluginName: 'content-manager',
|
||||
subjects: contentTypesUids,
|
||||
},
|
||||
{
|
||||
section: 'contentTypes',
|
||||
displayName: 'Read',
|
||||
name: 'read',
|
||||
pluginName: 'content-manager',
|
||||
subjects: contentTypesUids,
|
||||
},
|
||||
{
|
||||
section: 'contentTypes',
|
||||
displayName: 'Update',
|
||||
name: 'update',
|
||||
pluginName: 'content-manager',
|
||||
subjects: contentTypesUids,
|
||||
},
|
||||
{
|
||||
section: 'contentTypes',
|
||||
displayName: 'Delete',
|
||||
name: 'delete',
|
||||
pluginName: 'content-manager',
|
||||
subjects: contentTypesUids,
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Configure view',
|
||||
name: 'single-types.configure-view',
|
||||
subCategory: 'single types',
|
||||
pluginName: 'content-manager',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Configure view',
|
||||
name: 'collection-types.configure-view',
|
||||
subCategory: 'collection types',
|
||||
pluginName: 'content-manager',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Configure Layout',
|
||||
name: 'components.configure-layout',
|
||||
subCategory: 'components',
|
||||
pluginName: 'content-manager',
|
||||
},
|
||||
];
|
||||
|
||||
strapi.admin.permissionProvider.register(permissions);
|
||||
}
|
||||
|
||||
14
packages/strapi-plugin-content-type-builder/config/functions/bootstrap.js
vendored
Normal file
14
packages/strapi-plugin-content-type-builder/config/functions/bootstrap.js
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = () => {
|
||||
const permissions = [
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Read',
|
||||
name: 'read',
|
||||
pluginName: 'content-type-builder',
|
||||
},
|
||||
];
|
||||
|
||||
strapi.admin.permissionProvider.register(permissions);
|
||||
};
|
||||
@ -107,4 +107,30 @@ module.exports = async () => {
|
||||
'utf8'
|
||||
);
|
||||
}
|
||||
|
||||
// Add permissions
|
||||
const permissions = [
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Can access to the Documentation',
|
||||
name: 'read',
|
||||
pluginName: 'documentation',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Update and delete',
|
||||
name: 'settings.update',
|
||||
subCategory: 'settings',
|
||||
pluginName: 'documentation',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Regenerate',
|
||||
name: 'settings.regenerate',
|
||||
subCategory: 'settings',
|
||||
pluginName: 'documentation',
|
||||
},
|
||||
];
|
||||
|
||||
strapi.admin.permissionProvider.register(permissions);
|
||||
};
|
||||
|
||||
@ -28,6 +28,7 @@ module.exports = async () => {
|
||||
}
|
||||
|
||||
await pruneObsoleteRelations();
|
||||
registerPermissions();
|
||||
};
|
||||
|
||||
const createProvider = ({ provider, providerOptions }) => {
|
||||
@ -79,3 +80,44 @@ const pruneObsoleteRelationsQuery = ({ model }) => {
|
||||
{ $pull: { related: { kind: { $nin: modelsId } } } }
|
||||
);
|
||||
};
|
||||
|
||||
const registerPermissions = () => {
|
||||
const permissions = [
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Can access to the Media Library',
|
||||
name: 'read',
|
||||
pluginName: 'upload',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Create (upload)',
|
||||
name: 'assets.create',
|
||||
subCategory: 'assets',
|
||||
pluginName: 'upload',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Update (crop, details, replace)',
|
||||
name: 'assets.update',
|
||||
subCategory: 'assets',
|
||||
pluginName: 'upload',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Download',
|
||||
name: 'assets.download',
|
||||
subCategory: 'assets',
|
||||
pluginName: 'upload',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Copy link',
|
||||
name: 'assets.copy-link',
|
||||
subCategory: 'assets',
|
||||
pluginName: 'upload',
|
||||
},
|
||||
];
|
||||
|
||||
strapi.admin.permissionProvider.register(permissions);
|
||||
};
|
||||
|
||||
@ -3,8 +3,14 @@ const bootstrap = require('../../config/functions/bootstrap');
|
||||
describe('Upload plugin bootstrap function', () => {
|
||||
test('Sets default config if id does not exist', async () => {
|
||||
const setStore = jest.fn(() => {});
|
||||
const register = jest.fn(() => {});
|
||||
|
||||
global.strapi = {
|
||||
admin: {
|
||||
permissionProvider: {
|
||||
register,
|
||||
},
|
||||
},
|
||||
log: {
|
||||
error() {},
|
||||
},
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
const _ = require('lodash');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
const usersPermissionsPermissions = require('../users-permissions-permissions');
|
||||
|
||||
module.exports = async () => {
|
||||
const pluginStore = strapi.store({
|
||||
environment: '',
|
||||
@ -180,4 +182,6 @@ module.exports = async () => {
|
||||
|
||||
strapi.reload.isWatching = true;
|
||||
}
|
||||
|
||||
strapi.admin.permissionProvider.register(usersPermissionsPermissions.permissions);
|
||||
};
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
module.exports = {
|
||||
permissions: [
|
||||
{
|
||||
// Roles
|
||||
section: 'plugins',
|
||||
displayName: 'Create',
|
||||
name: 'roles.create',
|
||||
subCategory: 'roles',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Read',
|
||||
name: 'roles.read',
|
||||
subCategory: 'roles',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Update',
|
||||
name: 'roles.update',
|
||||
subCategory: 'roles',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Delete',
|
||||
name: 'roles.delete',
|
||||
subCategory: 'roles',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
// providers
|
||||
section: 'plugins',
|
||||
displayName: 'Read',
|
||||
name: 'providers.read',
|
||||
subCategory: 'providers',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Edit',
|
||||
name: 'providers.update',
|
||||
subCategory: 'providers',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
// emailTemplates
|
||||
section: 'plugins',
|
||||
displayName: 'Read',
|
||||
name: 'emailTemplates.read',
|
||||
subCategory: 'emailTemplates',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Edit',
|
||||
name: 'emailTemplates.update',
|
||||
subCategory: 'emailTemplates',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
// advancedSettings
|
||||
section: 'plugins',
|
||||
displayName: 'Read',
|
||||
name: 'advancedSettings.read',
|
||||
subCategory: 'advancedSettings',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
displayName: 'Edit',
|
||||
name: 'advancedSettings.update',
|
||||
subCategory: 'advancedSettings',
|
||||
pluginName: 'users-permissions',
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -28,10 +28,22 @@ function isAPluginName(message) {
|
||||
});
|
||||
}
|
||||
|
||||
function isAContentTypeId(message) {
|
||||
return this.test('is not a content-type id', message, function(value) {
|
||||
return Object.keys(strapi.contentTypes).includes(value)
|
||||
? true
|
||||
: this.createError({
|
||||
path: this.path,
|
||||
message: `${this.path} is not an existing content-type id`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
yup.addMethod(yup.mixed, 'notNil', isNotNill);
|
||||
yup.addMethod(yup.mixed, 'notNull', isNotNull);
|
||||
yup.addMethod(yup.array, 'requiredAllowEmpty', arrayRequiredAllowEmpty);
|
||||
yup.addMethod(yup.string, 'isAPluginName', isAPluginName);
|
||||
yup.addMethod(yup.string, 'isAContentTypeId', isAContentTypeId);
|
||||
|
||||
class StrapiIDSchema extends MixedSchemaType {
|
||||
constructor() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user