Add Publish permission & action

Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu>
This commit is contained in:
Convly 2020-08-11 16:39:05 +02:00 committed by Pierre Noël
parent 38d896f0ea
commit 310a0d16f3
7 changed files with 67 additions and 42 deletions

View File

@ -10,8 +10,15 @@ const actionFields = [
'pluginName',
'subjects',
'conditions',
'options',
];
const defaultAction = {
options: {
fieldsGranularity: true,
},
};
/**
* Return a prefixed id that depends on the pluginName
* @param {Object} params
@ -19,15 +26,13 @@ const actionFields = [
* @param {Object} params.uid - uid defined by the developer
*/
const getActionId = ({ pluginName, uid }) => {
let id = '';
if (pluginName === 'admin') {
id = `admin::${uid}`;
return `admin::${uid}`;
} else if (pluginName) {
id = `plugins::${pluginName}.${uid}`;
} else {
id = `application::${uid}`;
return `plugins::${pluginName}.${uid}`;
}
return id;
return `application::${uid}`;
};
/**
@ -42,7 +47,7 @@ function createAction(attributes) {
action.subCategory = attributes.subCategory || 'general';
}
return action;
return _.merge(action, defaultAction);
}
module.exports = {

View File

@ -1,10 +1,9 @@
'use strict';
const _ = require('lodash');
const domain = require('../../domain/action');
const actionProviderService = require('../permission/action-provider');
describe('Action Provider Service', () => {
const createdActions = [];
beforeEach(() => {
global.strapi = {
plugins: { aPlugin: {} },
@ -37,8 +36,6 @@ describe('Action Provider Service', () => {
..._.omit(readAction, ['uid']),
actionId: 'admin::marketplace.read',
});
createdActions.push(createdAction);
});
test('Can register a settings action without subCategory', async () => {
@ -50,7 +47,6 @@ describe('Action Provider Service', () => {
actionId: 'admin::marketplace.create',
subCategory: 'general',
});
createdActions.push(createdAction);
});
test('Can get all registered entries (array)', () => {
@ -61,6 +57,12 @@ describe('Action Provider Service', () => {
expect(actionProviderService.getAllByMap().size).toBe(2);
});
test('Can get an action by its actionId', () => {
const actionId = 'admin::marketplace.create';
const expected = domain.createAction(createAction);
expect(actionProviderService.getByActionId(actionId)).toStrictEqual(expected);
});
test('Can register a settings action with a pluginName other than "admin"', async () => {
const action = {
uid: 'marketplace.update',

View File

@ -110,24 +110,20 @@ const getNestedFieldsWithIntermediate = (
* @param {array} actions array of actions
* @param {object} options
* @param {number} options.nestingLevel level of nesting
* @param {array} options.fieldsNullFor actionIds where the fields should be null
* @param {array} options.restrictedSubjects subjectsId to ignore
* @returns {array<permissions>}
*/
const getPermissionsWithNestedFields = (
actions,
{ nestingLevel, fieldsNullFor = [], restrictedSubjects = [] } = {}
) =>
const getPermissionsWithNestedFields = (actions, { nestingLevel, restrictedSubjects = [] } = {}) =>
actions.reduce((perms, action) => {
action.subjects
.filter(subject => !restrictedSubjects.includes(subject))
.forEach(contentTypeUid => {
const fields = fieldsNullFor.includes(action.actionId)
? null
: getNestedFields(strapi.contentTypes[contentTypeUid], {
const fields = action.options.fieldsGranularity
? getNestedFields(strapi.contentTypes[contentTypeUid], {
components: strapi.components,
nestingLevel,
});
})
: null;
perms.push({
action: action.actionId,
subject: contentTypeUid,
@ -143,28 +139,30 @@ const getPermissionsWithNestedFields = (
* @param {object} permissions array of existing permissions in db
* @param {object} options
* @param {number} options.nestingLevel level of nesting
* @param {array} options.fieldsNullFor actionIds where the fields should be null
* @returns {array<permissions>}
*/
const cleanPermissionFields = (permissions, { nestingLevel, fieldsNullFor = [] }) =>
const cleanPermissionFields = (permissions, { nestingLevel }) =>
permissions.map(perm => {
let newFields = perm.fields;
if (fieldsNullFor.includes(perm.action)) {
const { action: actionId, fields, subject } = perm;
const action = strapi.admin.services.permission.actionProvider.getByActionId(actionId);
let newFields = fields;
if (!action.options.fieldsGranularity) {
newFields = null;
} else if (perm.subject && strapi.contentTypes[perm.subject]) {
const possiblefields = getNestedFieldsWithIntermediate(strapi.contentTypes[perm.subject], {
} else if (subject && strapi.contentTypes[subject]) {
const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], {
components: strapi.components,
nestingLevel,
});
const requiredFields = getNestedFields(strapi.contentTypes[perm.subject], {
const requiredFields = getNestedFields(strapi.contentTypes[subject], {
components: strapi.components,
requiredOnly: true,
nestingLevel,
existingFields: perm.fields,
existingFields: fields,
});
const badNestedFields = _.uniq([
..._.intersection(perm.fields, possiblefields),
..._.intersection(fields, possibleFields),
...requiredFields,
]);
newFields = badNestedFields.filter(

View File

@ -28,7 +28,7 @@ const arePermissionsEqual = (perm1, perm2) =>
/**
* Removes unwanted fields from a permission
* @param permission
* @param perm
* @returns {*}
*/
const sanitizePermission = perm => ({
@ -157,10 +157,7 @@ const cleanPermissionInDatabase = async () => {
// Second, clean fields of permissions (add required ones, remove the non-existing anymore ones)
const permissionsInDb = dbPermissions.filter(perm => !permissionsToRemoveIds.includes(perm.id));
const permissionsWithCleanFields = strapi.admin.services['content-type'].cleanPermissionFields(
permissionsInDb,
{
fieldsNullFor: ['plugins::content-manager.explorer.delete'],
}
permissionsInDb
);
// Update only the ones that need to be updated
@ -197,10 +194,7 @@ const resetSuperAdminPermissions = async () => {
const contentTypesActions = allActions.filter(a => a.section === 'contentTypes');
const permissions = strapi.admin.services['content-type'].getPermissionsWithNestedFields(
contentTypesActions,
{
fieldsNullFor: ['plugins::content-manager.explorer.delete'],
}
contentTypesActions
);
const otherActions = allActions.filter(a => a.section !== 'contentTypes');

View File

@ -16,8 +16,16 @@ const createActionProvider = () => {
*/
get(uid, pluginName) {
const actionId = getActionId({ pluginName, uid });
const action = actions.get(actionId);
return action;
return actions.get(actionId);
},
/**
* Get an action by its actionId
* @param {string} actionId
* @returns {Action}
*/
getByActionId(actionId) {
return actions.get(actionId);
},
/**

View File

@ -32,7 +32,7 @@ const registerProviderActionSchema = yup
then: yup
.array()
.of(yup.string())
.required(),
.requiredAllowEmpty(),
otherwise: yup
.mixed()
.oneOf([undefined], 'subjects should only be defined for the "contentTypes" section'),
@ -62,6 +62,9 @@ const registerProviderActionSchema = yup
}
),
}),
options: yup.object({
fieldsGranularity: yup.boolean(),
}),
})
.noUnknown()
);

View File

@ -94,6 +94,8 @@ const registerPermissions = () => {
'content-manager'
].services.contenttypes.getDisplayedContentTypesUids();
const hasDraftAndPublish = uid => strapi.contentTypes[uid].options.draftAndPublish;
const actions = [
{
section: 'contentTypes',
@ -122,6 +124,19 @@ const registerPermissions = () => {
uid: 'explorer.delete',
pluginName: 'content-manager',
subjects: contentTypesUids,
options: {
fieldsGranularity: false,
},
},
{
section: 'contentTypes',
displayName: 'Publish',
uid: 'explorer.publish',
pluginName: 'content-manager',
subjects: contentTypesUids.filter(hasDraftAndPublish),
options: {
fieldsGranularity: false,
},
},
{
section: 'plugins',