mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 09:56:44 +00:00 
			
		
		
		
	Add Publish permission & action
Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu>
This commit is contained in:
		
							parent
							
								
									38d896f0ea
								
							
						
					
					
						commit
						310a0d16f3
					
				| @ -10,8 +10,15 @@ const actionFields = [ | |||||||
|   'pluginName', |   'pluginName', | ||||||
|   'subjects', |   'subjects', | ||||||
|   'conditions', |   'conditions', | ||||||
|  |   'options', | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
|  | const defaultAction = { | ||||||
|  |   options: { | ||||||
|  |     fieldsGranularity: true, | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Return a prefixed id that depends on the pluginName |  * Return a prefixed id that depends on the pluginName | ||||||
|  * @param {Object} params |  * @param {Object} params | ||||||
| @ -19,15 +26,13 @@ const actionFields = [ | |||||||
|  * @param {Object} params.uid - uid defined by the developer |  * @param {Object} params.uid - uid defined by the developer | ||||||
|  */ |  */ | ||||||
| const getActionId = ({ pluginName, uid }) => { | const getActionId = ({ pluginName, uid }) => { | ||||||
|   let id = ''; |  | ||||||
|   if (pluginName === 'admin') { |   if (pluginName === 'admin') { | ||||||
|     id = `admin::${uid}`; |     return `admin::${uid}`; | ||||||
|   } else if (pluginName) { |   } else if (pluginName) { | ||||||
|     id = `plugins::${pluginName}.${uid}`; |     return `plugins::${pluginName}.${uid}`; | ||||||
|   } else { |  | ||||||
|     id = `application::${uid}`; |  | ||||||
|   } |   } | ||||||
|   return id; | 
 | ||||||
|  |   return `application::${uid}`; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -42,7 +47,7 @@ function createAction(attributes) { | |||||||
|     action.subCategory = attributes.subCategory || 'general'; |     action.subCategory = attributes.subCategory || 'general'; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return action; |   return _.merge(action, defaultAction); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | module.exports = { | ||||||
|  | |||||||
| @ -1,10 +1,9 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| const _ = require('lodash'); | const _ = require('lodash'); | ||||||
|  | const domain = require('../../domain/action'); | ||||||
| const actionProviderService = require('../permission/action-provider'); | const actionProviderService = require('../permission/action-provider'); | ||||||
| 
 | 
 | ||||||
| describe('Action Provider Service', () => { | describe('Action Provider Service', () => { | ||||||
|   const createdActions = []; |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |   beforeEach(() => { | ||||||
|     global.strapi = { |     global.strapi = { | ||||||
|       plugins: { aPlugin: {} }, |       plugins: { aPlugin: {} }, | ||||||
| @ -37,8 +36,6 @@ describe('Action Provider Service', () => { | |||||||
|         ..._.omit(readAction, ['uid']), |         ..._.omit(readAction, ['uid']), | ||||||
|         actionId: 'admin::marketplace.read', |         actionId: 'admin::marketplace.read', | ||||||
|       }); |       }); | ||||||
| 
 |  | ||||||
|       createdActions.push(createdAction); |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     test('Can register a settings action without subCategory', async () => { |     test('Can register a settings action without subCategory', async () => { | ||||||
| @ -50,7 +47,6 @@ describe('Action Provider Service', () => { | |||||||
|         actionId: 'admin::marketplace.create', |         actionId: 'admin::marketplace.create', | ||||||
|         subCategory: 'general', |         subCategory: 'general', | ||||||
|       }); |       }); | ||||||
|       createdActions.push(createdAction); |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     test('Can get all registered entries (array)', () => { |     test('Can get all registered entries (array)', () => { | ||||||
| @ -61,6 +57,12 @@ describe('Action Provider Service', () => { | |||||||
|       expect(actionProviderService.getAllByMap().size).toBe(2); |       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 () => { |     test('Can register a settings action with a pluginName other than "admin"', async () => { | ||||||
|       const action = { |       const action = { | ||||||
|         uid: 'marketplace.update', |         uid: 'marketplace.update', | ||||||
|  | |||||||
| @ -110,24 +110,20 @@ const getNestedFieldsWithIntermediate = ( | |||||||
|  * @param {array} actions array of actions |  * @param {array} actions array of actions | ||||||
|  * @param {object} options |  * @param {object} options | ||||||
|  * @param {number} options.nestingLevel level of nesting |  * @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 |  * @param {array} options.restrictedSubjects subjectsId to ignore | ||||||
|  * @returns {array<permissions>} |  * @returns {array<permissions>} | ||||||
|  */ |  */ | ||||||
| const getPermissionsWithNestedFields = ( | const getPermissionsWithNestedFields = (actions, { nestingLevel, restrictedSubjects = [] } = {}) => | ||||||
|   actions, |  | ||||||
|   { nestingLevel, fieldsNullFor = [], restrictedSubjects = [] } = {} |  | ||||||
| ) => |  | ||||||
|   actions.reduce((perms, action) => { |   actions.reduce((perms, action) => { | ||||||
|     action.subjects |     action.subjects | ||||||
|       .filter(subject => !restrictedSubjects.includes(subject)) |       .filter(subject => !restrictedSubjects.includes(subject)) | ||||||
|       .forEach(contentTypeUid => { |       .forEach(contentTypeUid => { | ||||||
|         const fields = fieldsNullFor.includes(action.actionId) |         const fields = action.options.fieldsGranularity | ||||||
|           ? null |           ? getNestedFields(strapi.contentTypes[contentTypeUid], { | ||||||
|           : getNestedFields(strapi.contentTypes[contentTypeUid], { |  | ||||||
|               components: strapi.components, |               components: strapi.components, | ||||||
|               nestingLevel, |               nestingLevel, | ||||||
|             }); |             }) | ||||||
|  |           : null; | ||||||
|         perms.push({ |         perms.push({ | ||||||
|           action: action.actionId, |           action: action.actionId, | ||||||
|           subject: contentTypeUid, |           subject: contentTypeUid, | ||||||
| @ -143,28 +139,30 @@ const getPermissionsWithNestedFields = ( | |||||||
|  * @param {object} permissions array of existing permissions in db |  * @param {object} permissions array of existing permissions in db | ||||||
|  * @param {object} options |  * @param {object} options | ||||||
|  * @param {number} options.nestingLevel level of nesting |  * @param {number} options.nestingLevel level of nesting | ||||||
|  * @param {array} options.fieldsNullFor actionIds where the fields should be null |  | ||||||
|  * @returns {array<permissions>} |  * @returns {array<permissions>} | ||||||
|  */ |  */ | ||||||
| const cleanPermissionFields = (permissions, { nestingLevel, fieldsNullFor = [] }) => | const cleanPermissionFields = (permissions, { nestingLevel }) => | ||||||
|   permissions.map(perm => { |   permissions.map(perm => { | ||||||
|     let newFields = perm.fields; |     const { action: actionId, fields, subject } = perm; | ||||||
|     if (fieldsNullFor.includes(perm.action)) { |     const action = strapi.admin.services.permission.actionProvider.getByActionId(actionId); | ||||||
|  |     let newFields = fields; | ||||||
|  | 
 | ||||||
|  |     if (!action.options.fieldsGranularity) { | ||||||
|       newFields = null; |       newFields = null; | ||||||
|     } else if (perm.subject && strapi.contentTypes[perm.subject]) { |     } else if (subject && strapi.contentTypes[subject]) { | ||||||
|       const possiblefields = getNestedFieldsWithIntermediate(strapi.contentTypes[perm.subject], { |       const possibleFields = getNestedFieldsWithIntermediate(strapi.contentTypes[subject], { | ||||||
|         components: strapi.components, |         components: strapi.components, | ||||||
|         nestingLevel, |         nestingLevel, | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       const requiredFields = getNestedFields(strapi.contentTypes[perm.subject], { |       const requiredFields = getNestedFields(strapi.contentTypes[subject], { | ||||||
|         components: strapi.components, |         components: strapi.components, | ||||||
|         requiredOnly: true, |         requiredOnly: true, | ||||||
|         nestingLevel, |         nestingLevel, | ||||||
|         existingFields: perm.fields, |         existingFields: fields, | ||||||
|       }); |       }); | ||||||
|       const badNestedFields = _.uniq([ |       const badNestedFields = _.uniq([ | ||||||
|         ..._.intersection(perm.fields, possiblefields), |         ..._.intersection(fields, possibleFields), | ||||||
|         ...requiredFields, |         ...requiredFields, | ||||||
|       ]); |       ]); | ||||||
|       newFields = badNestedFields.filter( |       newFields = badNestedFields.filter( | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ const arePermissionsEqual = (perm1, perm2) => | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Removes unwanted fields from a permission |  * Removes unwanted fields from a permission | ||||||
|  * @param permission |  * @param perm | ||||||
|  * @returns {*} |  * @returns {*} | ||||||
|  */ |  */ | ||||||
| const sanitizePermission = perm => ({ | const sanitizePermission = perm => ({ | ||||||
| @ -157,10 +157,7 @@ const cleanPermissionInDatabase = async () => { | |||||||
|     // Second, clean fields of permissions (add required ones, remove the non-existing anymore ones)
 |     // Second, clean fields of permissions (add required ones, remove the non-existing anymore ones)
 | ||||||
|     const permissionsInDb = dbPermissions.filter(perm => !permissionsToRemoveIds.includes(perm.id)); |     const permissionsInDb = dbPermissions.filter(perm => !permissionsToRemoveIds.includes(perm.id)); | ||||||
|     const permissionsWithCleanFields = strapi.admin.services['content-type'].cleanPermissionFields( |     const permissionsWithCleanFields = strapi.admin.services['content-type'].cleanPermissionFields( | ||||||
|       permissionsInDb, |       permissionsInDb | ||||||
|       { |  | ||||||
|         fieldsNullFor: ['plugins::content-manager.explorer.delete'], |  | ||||||
|       } |  | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     // Update only the ones that need to be updated
 |     // 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 contentTypesActions = allActions.filter(a => a.section === 'contentTypes'); | ||||||
| 
 | 
 | ||||||
|   const permissions = strapi.admin.services['content-type'].getPermissionsWithNestedFields( |   const permissions = strapi.admin.services['content-type'].getPermissionsWithNestedFields( | ||||||
|     contentTypesActions, |     contentTypesActions | ||||||
|     { |  | ||||||
|       fieldsNullFor: ['plugins::content-manager.explorer.delete'], |  | ||||||
|     } |  | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   const otherActions = allActions.filter(a => a.section !== 'contentTypes'); |   const otherActions = allActions.filter(a => a.section !== 'contentTypes'); | ||||||
|  | |||||||
| @ -16,8 +16,16 @@ const createActionProvider = () => { | |||||||
|      */ |      */ | ||||||
|     get(uid, pluginName) { |     get(uid, pluginName) { | ||||||
|       const actionId = getActionId({ pluginName, uid }); |       const actionId = getActionId({ pluginName, uid }); | ||||||
|       const action = actions.get(actionId); |       return actions.get(actionId); | ||||||
|       return action; |     }, | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Get an action by its actionId | ||||||
|  |      * @param {string} actionId | ||||||
|  |      * @returns {Action} | ||||||
|  |      */ | ||||||
|  |     getByActionId(actionId) { | ||||||
|  |       return actions.get(actionId); | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ const registerProviderActionSchema = yup | |||||||
|           then: yup |           then: yup | ||||||
|             .array() |             .array() | ||||||
|             .of(yup.string()) |             .of(yup.string()) | ||||||
|             .required(), |             .requiredAllowEmpty(), | ||||||
|           otherwise: yup |           otherwise: yup | ||||||
|             .mixed() |             .mixed() | ||||||
|             .oneOf([undefined], 'subjects should only be defined for the "contentTypes" section'), |             .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() |       .noUnknown() | ||||||
|   ); |   ); | ||||||
|  | |||||||
| @ -94,6 +94,8 @@ const registerPermissions = () => { | |||||||
|     'content-manager' |     'content-manager' | ||||||
|   ].services.contenttypes.getDisplayedContentTypesUids(); |   ].services.contenttypes.getDisplayedContentTypesUids(); | ||||||
| 
 | 
 | ||||||
|  |   const hasDraftAndPublish = uid => strapi.contentTypes[uid].options.draftAndPublish; | ||||||
|  | 
 | ||||||
|   const actions = [ |   const actions = [ | ||||||
|     { |     { | ||||||
|       section: 'contentTypes', |       section: 'contentTypes', | ||||||
| @ -122,6 +124,19 @@ const registerPermissions = () => { | |||||||
|       uid: 'explorer.delete', |       uid: 'explorer.delete', | ||||||
|       pluginName: 'content-manager', |       pluginName: 'content-manager', | ||||||
|       subjects: contentTypesUids, |       subjects: contentTypesUids, | ||||||
|  |       options: { | ||||||
|  |         fieldsGranularity: false, | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       section: 'contentTypes', | ||||||
|  |       displayName: 'Publish', | ||||||
|  |       uid: 'explorer.publish', | ||||||
|  |       pluginName: 'content-manager', | ||||||
|  |       subjects: contentTypesUids.filter(hasDraftAndPublish), | ||||||
|  |       options: { | ||||||
|  |         fieldsGranularity: false, | ||||||
|  |       }, | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       section: 'plugins', |       section: 'plugins', | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Convly
						Convly