mirror of
https://github.com/strapi/strapi.git
synced 2025-09-17 12:27:33 +00:00
Add logic to set the correct leaf when in edition
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
b256776fbb
commit
d6e70a737d
@ -10,9 +10,9 @@ import formatPermissionsToAPI from './utils/formatPermissionsToAPI';
|
||||
import init from './init';
|
||||
import reducer, { initialState } from './reducer';
|
||||
|
||||
const Permissions = forwardRef(({ layout, isFormDisabled }, ref) => {
|
||||
const Permissions = forwardRef(({ layout, isFormDisabled, permissions }, ref) => {
|
||||
const [{ layouts, modifiedData }, dispatch] = useReducer(reducer, initialState, () =>
|
||||
init(layout)
|
||||
init(layout, permissions)
|
||||
);
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
@ -112,11 +112,13 @@ const Permissions = forwardRef(({ layout, isFormDisabled }, ref) => {
|
||||
});
|
||||
|
||||
Permissions.defaultProps = {
|
||||
permissions: [],
|
||||
layout,
|
||||
};
|
||||
Permissions.propTypes = {
|
||||
layout: PropTypes.object,
|
||||
isFormDisabled: PropTypes.bool.isRequired,
|
||||
permissions: PropTypes.array,
|
||||
};
|
||||
|
||||
export default memo(Permissions);
|
||||
|
@ -2,7 +2,7 @@ import createDefaultCTFormFromLayout from './utils/createDefaultCTFormFromLayout
|
||||
import createDefaultPluginsFormFromLayout from './utils/createDefaultPluginsFormFromLayout';
|
||||
import formatLayoutForSettingsAndPlugins from './utils/formatLayoutForSettingsAndPlugins';
|
||||
|
||||
const init = layout => {
|
||||
const init = (layout, permissions) => {
|
||||
const {
|
||||
conditions,
|
||||
sections: { collectionTypes, singleTypes, plugins, settings },
|
||||
@ -17,7 +17,8 @@ const init = layout => {
|
||||
collectionTypes: createDefaultCTFormFromLayout(
|
||||
collectionTypes,
|
||||
collectionTypes.actions || [],
|
||||
conditions
|
||||
conditions,
|
||||
permissions
|
||||
),
|
||||
singleTypes: createDefaultCTFormFromLayout(singleTypes, singleTypes.actions || [], conditions),
|
||||
plugins: createDefaultPluginsFormFromLayout(layouts.plugins, conditions),
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { merge, isEmpty, set } from 'lodash';
|
||||
import { merge, get, isEmpty, set } from 'lodash';
|
||||
|
||||
/**
|
||||
* Creates the default condition form: { [conditionId]: false }
|
||||
* @param {object} conditions.id Id of the condition
|
||||
* @returns {object}
|
||||
*/
|
||||
const createDefaultConditionsForm = conditions =>
|
||||
const createDefaultConditionsForm = (conditions, initialConditions = []) =>
|
||||
conditions.reduce((acc, current) => {
|
||||
acc[current.id] = false;
|
||||
acc[current.id] = initialConditions.indexOf(current.id) !== -1;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
@ -16,16 +16,26 @@ const createDefaultConditionsForm = conditions =>
|
||||
* Create the default form a property (fields, locales) with all the values
|
||||
* set to false
|
||||
* @param {object} property.children ex: {children: [{value: 'foo',}]}
|
||||
* @param {array<string>} The found property values retrieved from the role associated permissions
|
||||
* @returns {object} ex: { foo: false }
|
||||
*
|
||||
*/
|
||||
const createDefaultPropertyForms = ({ children }) => {
|
||||
const createDefaultPropertyForms = ({ children }, propertyValues, prefix = '') => {
|
||||
return children.reduce((acc, current) => {
|
||||
if (current.children) {
|
||||
return { ...acc, [current.value]: createDefaultPropertyForms(current) };
|
||||
return {
|
||||
...acc,
|
||||
[current.value]: createDefaultPropertyForms(
|
||||
current,
|
||||
propertyValues,
|
||||
`${prefix}${current.value}.`
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
acc[current.value] = false;
|
||||
const hasProperty = propertyValues.indexOf(`${prefix}${current.value}`) !== -1;
|
||||
|
||||
acc[current.value] = hasProperty;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
@ -43,12 +53,16 @@ const createDefaultPropertyForms = ({ children }) => {
|
||||
* }
|
||||
* @returns {object} In this case it will return { fields: { name: false } }
|
||||
*/
|
||||
const createDefaultPropertiesForm = (propertiesArray, ctLayout) => {
|
||||
const createDefaultPropertiesForm = (propertiesArray, ctLayout, matchingPermission) => {
|
||||
return propertiesArray.reduce((acc, currentPropertyName) => {
|
||||
const foundProperty = ctLayout.properties.find(({ value }) => value === currentPropertyName);
|
||||
|
||||
if (foundProperty) {
|
||||
const propertyForm = createDefaultPropertyForms(foundProperty);
|
||||
const matchingPermissionPropertyValues = get(matchingPermission, foundProperty.value, []);
|
||||
const propertyForm = createDefaultPropertyForms(
|
||||
foundProperty,
|
||||
matchingPermissionPropertyValues
|
||||
);
|
||||
|
||||
acc[currentPropertyName] = propertyForm;
|
||||
}
|
||||
@ -89,7 +103,12 @@ const findLayouts = (allLayouts, subjects) => {
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
const createDefaultCTFormFromLayout = ({ subjects }, actionArray, conditionArray) => {
|
||||
const createDefaultCTFormFromLayout = (
|
||||
{ subjects },
|
||||
actionArray,
|
||||
conditionArray,
|
||||
initialPermissions = []
|
||||
) => {
|
||||
return actionArray.reduce((defaultForm, current) => {
|
||||
const actionSubjects = current.subjects;
|
||||
|
||||
@ -105,17 +124,26 @@ const createDefaultCTFormFromLayout = ({ subjects }, actionArray, conditionArray
|
||||
// The object has the following shape: { [ctUID]: { [actionId]: { [property]: { enabled: false } } } }
|
||||
const contentTypesActions = Object.keys(subjectLayouts).reduce((acc, currentCTUID) => {
|
||||
const { actionId, applyToProperties } = current;
|
||||
const conditionsForm = createDefaultConditionsForm(conditionArray);
|
||||
|
||||
const matchingPermission = findMatchingPermission(initialPermissions, actionId, currentCTUID);
|
||||
const conditionsForm = createDefaultConditionsForm(
|
||||
conditionArray,
|
||||
get(matchingPermission, 'conditions', [])
|
||||
);
|
||||
|
||||
if (isEmpty(applyToProperties)) {
|
||||
set(acc, [currentCTUID, actionId], { enabled: false, conditions: conditionsForm });
|
||||
set(acc, [currentCTUID, actionId], {
|
||||
enabled: matchingPermission !== undefined,
|
||||
conditions: conditionsForm,
|
||||
});
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
const propertiesForm = createDefaultPropertiesForm(
|
||||
applyToProperties,
|
||||
subjectLayouts[currentCTUID]
|
||||
subjectLayouts[currentCTUID],
|
||||
matchingPermission
|
||||
);
|
||||
|
||||
set(acc, [currentCTUID, actionId], { ...propertiesForm, conditions: conditionsForm });
|
||||
@ -127,6 +155,9 @@ const createDefaultCTFormFromLayout = ({ subjects }, actionArray, conditionArray
|
||||
}, {});
|
||||
};
|
||||
|
||||
const findMatchingPermission = (permissions, action, subject) =>
|
||||
permissions.find(perm => perm.action === action && perm.subject === subject);
|
||||
|
||||
export default createDefaultCTFormFromLayout;
|
||||
export {
|
||||
createDefaultConditionsForm,
|
||||
|
@ -20,7 +20,7 @@ const conditions = [
|
||||
|
||||
describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
describe('createConditionForm', () => {
|
||||
it('should return an object with all the values set to false', () => {
|
||||
it('should return an object with all the leafs set to false', () => {
|
||||
const expected = {
|
||||
'admin::is-creator': false,
|
||||
'admin::has-same-role-as-creator': false,
|
||||
@ -28,10 +28,21 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
|
||||
expect(createDefaultConditionsForm(conditions)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should return an object with the leafs set to true when the initial conditions contains the condition', () => {
|
||||
const expected = {
|
||||
'admin::is-creator': false,
|
||||
'admin::has-same-role-as-creator': true,
|
||||
};
|
||||
|
||||
expect(
|
||||
createDefaultConditionsForm(conditions, ['test', 'admin::has-same-role-as-creator'])
|
||||
).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createDefaultPropertyForms,', () => {
|
||||
it('should return an object with keys corresponding to the property value and all the values set to false', () => {
|
||||
it('should return an object with keys corresponding to the property value and all the leafs set to false', () => {
|
||||
const data = {
|
||||
children: [
|
||||
{
|
||||
@ -47,10 +58,10 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
bar: false,
|
||||
};
|
||||
|
||||
expect(createDefaultPropertyForms(data)).toEqual(expected);
|
||||
expect(createDefaultPropertyForms(data, [])).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should create the default form for a complex object', () => {
|
||||
it('should create the default form for a complex object when the second argument is not an empty array', () => {
|
||||
const data = {
|
||||
children: [
|
||||
{
|
||||
@ -74,17 +85,18 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
const propertyValues = ['foo', 'bar.foo.bar'];
|
||||
const expected = {
|
||||
foo: false,
|
||||
foo: true,
|
||||
bar: {
|
||||
name: false,
|
||||
foo: {
|
||||
bar: false,
|
||||
bar: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(createDefaultPropertyForms(data)).toEqual(expected);
|
||||
expect(createDefaultPropertyForms(data, propertyValues)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@ -286,6 +298,7 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const actions = [
|
||||
{
|
||||
label: 'Create',
|
||||
@ -312,12 +325,12 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
fields: {
|
||||
postal_coder: false,
|
||||
categories: false,
|
||||
cover: false,
|
||||
cover: true,
|
||||
images: false,
|
||||
city: false,
|
||||
},
|
||||
conditions: {
|
||||
'admin::is-creator': false,
|
||||
'admin::is-creator': true,
|
||||
'admin::has-same-role-as-creator': false,
|
||||
},
|
||||
},
|
||||
@ -336,10 +349,10 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
f2: false,
|
||||
services: { name: false, media: false, closing: { name: { test: false } } },
|
||||
dz: false,
|
||||
relation: false,
|
||||
relation: true,
|
||||
},
|
||||
locales: {
|
||||
en: false,
|
||||
en: true,
|
||||
fr: false,
|
||||
},
|
||||
conditions: {
|
||||
@ -360,7 +373,25 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(createDefaultCTFormFromLayout({ subjects }, actions, conditions)).toEqual(expected);
|
||||
const permissions = [
|
||||
{
|
||||
action: 'content-manager.explorer.create',
|
||||
subject: 'restaurant',
|
||||
fields: ['relation'],
|
||||
locales: ['en'],
|
||||
},
|
||||
{
|
||||
action: 'content-manager.explorer.create',
|
||||
subject: 'address',
|
||||
fields: ['cover'],
|
||||
locales: ['fr'],
|
||||
conditions: ['admin::is-creator'],
|
||||
},
|
||||
];
|
||||
|
||||
expect(createDefaultCTFormFromLayout({ subjects }, actions, conditions, permissions)).toEqual(
|
||||
expected
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -36,7 +36,6 @@ const EditPage = () => {
|
||||
isLoading: isRoleLoading,
|
||||
onSubmitSucceeded,
|
||||
} = useFetchRole(id);
|
||||
console.log({ rolePermissions });
|
||||
|
||||
/* eslint-disable indent */
|
||||
const headerActions = (handleSubmit, handleReset) =>
|
||||
@ -177,7 +176,11 @@ const EditPage = () => {
|
||||
/>
|
||||
{!isLayoutLoading && !isRoleLoading && (
|
||||
<Padded top bottom size="md">
|
||||
<Permissions isFormDisabled={isFormDisabled} ref={permissionsRef} />
|
||||
<Permissions
|
||||
isFormDisabled={isFormDisabled}
|
||||
permissions={rolePermissions}
|
||||
ref={permissionsRef}
|
||||
/>
|
||||
</Padded>
|
||||
)}
|
||||
</ContainerFluid>
|
||||
|
Loading…
x
Reference in New Issue
Block a user