add route GET /admin/permissions

Signed-off-by: Pierre Noël <petersg83@gmail.com>
This commit is contained in:
Pierre Noël 2020-06-04 18:30:26 +02:00 committed by Alexandre Bodin
parent 5fffffa72d
commit ae0dcb9745
19 changed files with 714 additions and 68 deletions

View File

@ -194,6 +194,14 @@
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/permissions",
"handler": "permission.getAll",
"config": {
"policies": []
}
}
]
}

View 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,
};
},
};

View File

@ -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 => {

View File

@ -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'
);
});
});

View File

@ -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: [],

View File

@ -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);
}
}

View File

@ -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 => {

View 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);
});
});

View File

@ -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`,

View 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": []
}

View File

@ -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;
}
}
};

View File

@ -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);
}

View 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);
};

View File

@ -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);
};

View File

@ -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);
};

View File

@ -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() {},
},

View File

@ -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);
};

View File

@ -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',
},
],
};

View File

@ -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() {