mirror of
https://github.com/strapi/strapi.git
synced 2025-09-17 04:17:21 +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 init from './init';
|
||||||
import reducer, { initialState } from './reducer';
|
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, () =>
|
const [{ layouts, modifiedData }, dispatch] = useReducer(reducer, initialState, () =>
|
||||||
init(layout)
|
init(layout, permissions)
|
||||||
);
|
);
|
||||||
|
|
||||||
useImperativeHandle(ref, () => {
|
useImperativeHandle(ref, () => {
|
||||||
@ -112,11 +112,13 @@ const Permissions = forwardRef(({ layout, isFormDisabled }, ref) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Permissions.defaultProps = {
|
Permissions.defaultProps = {
|
||||||
|
permissions: [],
|
||||||
layout,
|
layout,
|
||||||
};
|
};
|
||||||
Permissions.propTypes = {
|
Permissions.propTypes = {
|
||||||
layout: PropTypes.object,
|
layout: PropTypes.object,
|
||||||
isFormDisabled: PropTypes.bool.isRequired,
|
isFormDisabled: PropTypes.bool.isRequired,
|
||||||
|
permissions: PropTypes.array,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(Permissions);
|
export default memo(Permissions);
|
||||||
|
@ -2,7 +2,7 @@ import createDefaultCTFormFromLayout from './utils/createDefaultCTFormFromLayout
|
|||||||
import createDefaultPluginsFormFromLayout from './utils/createDefaultPluginsFormFromLayout';
|
import createDefaultPluginsFormFromLayout from './utils/createDefaultPluginsFormFromLayout';
|
||||||
import formatLayoutForSettingsAndPlugins from './utils/formatLayoutForSettingsAndPlugins';
|
import formatLayoutForSettingsAndPlugins from './utils/formatLayoutForSettingsAndPlugins';
|
||||||
|
|
||||||
const init = layout => {
|
const init = (layout, permissions) => {
|
||||||
const {
|
const {
|
||||||
conditions,
|
conditions,
|
||||||
sections: { collectionTypes, singleTypes, plugins, settings },
|
sections: { collectionTypes, singleTypes, plugins, settings },
|
||||||
@ -17,7 +17,8 @@ const init = layout => {
|
|||||||
collectionTypes: createDefaultCTFormFromLayout(
|
collectionTypes: createDefaultCTFormFromLayout(
|
||||||
collectionTypes,
|
collectionTypes,
|
||||||
collectionTypes.actions || [],
|
collectionTypes.actions || [],
|
||||||
conditions
|
conditions,
|
||||||
|
permissions
|
||||||
),
|
),
|
||||||
singleTypes: createDefaultCTFormFromLayout(singleTypes, singleTypes.actions || [], conditions),
|
singleTypes: createDefaultCTFormFromLayout(singleTypes, singleTypes.actions || [], conditions),
|
||||||
plugins: createDefaultPluginsFormFromLayout(layouts.plugins, 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 }
|
* Creates the default condition form: { [conditionId]: false }
|
||||||
* @param {object} conditions.id Id of the condition
|
* @param {object} conditions.id Id of the condition
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
const createDefaultConditionsForm = conditions =>
|
const createDefaultConditionsForm = (conditions, initialConditions = []) =>
|
||||||
conditions.reduce((acc, current) => {
|
conditions.reduce((acc, current) => {
|
||||||
acc[current.id] = false;
|
acc[current.id] = initialConditions.indexOf(current.id) !== -1;
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
@ -16,16 +16,26 @@ const createDefaultConditionsForm = conditions =>
|
|||||||
* Create the default form a property (fields, locales) with all the values
|
* Create the default form a property (fields, locales) with all the values
|
||||||
* set to false
|
* set to false
|
||||||
* @param {object} property.children ex: {children: [{value: 'foo',}]}
|
* @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 }
|
* @returns {object} ex: { foo: false }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const createDefaultPropertyForms = ({ children }) => {
|
const createDefaultPropertyForms = ({ children }, propertyValues, prefix = '') => {
|
||||||
return children.reduce((acc, current) => {
|
return children.reduce((acc, current) => {
|
||||||
if (current.children) {
|
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;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
@ -43,12 +53,16 @@ const createDefaultPropertyForms = ({ children }) => {
|
|||||||
* }
|
* }
|
||||||
* @returns {object} In this case it will return { fields: { name: false } }
|
* @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) => {
|
return propertiesArray.reduce((acc, currentPropertyName) => {
|
||||||
const foundProperty = ctLayout.properties.find(({ value }) => value === currentPropertyName);
|
const foundProperty = ctLayout.properties.find(({ value }) => value === currentPropertyName);
|
||||||
|
|
||||||
if (foundProperty) {
|
if (foundProperty) {
|
||||||
const propertyForm = createDefaultPropertyForms(foundProperty);
|
const matchingPermissionPropertyValues = get(matchingPermission, foundProperty.value, []);
|
||||||
|
const propertyForm = createDefaultPropertyForms(
|
||||||
|
foundProperty,
|
||||||
|
matchingPermissionPropertyValues
|
||||||
|
);
|
||||||
|
|
||||||
acc[currentPropertyName] = propertyForm;
|
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) => {
|
return actionArray.reduce((defaultForm, current) => {
|
||||||
const actionSubjects = current.subjects;
|
const actionSubjects = current.subjects;
|
||||||
|
|
||||||
@ -105,17 +124,26 @@ const createDefaultCTFormFromLayout = ({ subjects }, actionArray, conditionArray
|
|||||||
// The object has the following shape: { [ctUID]: { [actionId]: { [property]: { enabled: false } } } }
|
// The object has the following shape: { [ctUID]: { [actionId]: { [property]: { enabled: false } } } }
|
||||||
const contentTypesActions = Object.keys(subjectLayouts).reduce((acc, currentCTUID) => {
|
const contentTypesActions = Object.keys(subjectLayouts).reduce((acc, currentCTUID) => {
|
||||||
const { actionId, applyToProperties } = current;
|
const { actionId, applyToProperties } = current;
|
||||||
const conditionsForm = createDefaultConditionsForm(conditionArray);
|
|
||||||
|
const matchingPermission = findMatchingPermission(initialPermissions, actionId, currentCTUID);
|
||||||
|
const conditionsForm = createDefaultConditionsForm(
|
||||||
|
conditionArray,
|
||||||
|
get(matchingPermission, 'conditions', [])
|
||||||
|
);
|
||||||
|
|
||||||
if (isEmpty(applyToProperties)) {
|
if (isEmpty(applyToProperties)) {
|
||||||
set(acc, [currentCTUID, actionId], { enabled: false, conditions: conditionsForm });
|
set(acc, [currentCTUID, actionId], {
|
||||||
|
enabled: matchingPermission !== undefined,
|
||||||
|
conditions: conditionsForm,
|
||||||
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const propertiesForm = createDefaultPropertiesForm(
|
const propertiesForm = createDefaultPropertiesForm(
|
||||||
applyToProperties,
|
applyToProperties,
|
||||||
subjectLayouts[currentCTUID]
|
subjectLayouts[currentCTUID],
|
||||||
|
matchingPermission
|
||||||
);
|
);
|
||||||
|
|
||||||
set(acc, [currentCTUID, actionId], { ...propertiesForm, conditions: conditionsForm });
|
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 default createDefaultCTFormFromLayout;
|
||||||
export {
|
export {
|
||||||
createDefaultConditionsForm,
|
createDefaultConditionsForm,
|
||||||
|
@ -20,7 +20,7 @@ const conditions = [
|
|||||||
|
|
||||||
describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
||||||
describe('createConditionForm', () => {
|
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 = {
|
const expected = {
|
||||||
'admin::is-creator': false,
|
'admin::is-creator': false,
|
||||||
'admin::has-same-role-as-creator': false,
|
'admin::has-same-role-as-creator': false,
|
||||||
@ -28,10 +28,21 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
|||||||
|
|
||||||
expect(createDefaultConditionsForm(conditions)).toEqual(expected);
|
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,', () => {
|
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 = {
|
const data = {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@ -47,10 +58,10 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
|||||||
bar: false,
|
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 = {
|
const data = {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@ -74,17 +85,18 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
const propertyValues = ['foo', 'bar.foo.bar'];
|
||||||
const expected = {
|
const expected = {
|
||||||
foo: false,
|
foo: true,
|
||||||
bar: {
|
bar: {
|
||||||
name: false,
|
name: false,
|
||||||
foo: {
|
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 = [
|
const actions = [
|
||||||
{
|
{
|
||||||
label: 'Create',
|
label: 'Create',
|
||||||
@ -312,12 +325,12 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
|||||||
fields: {
|
fields: {
|
||||||
postal_coder: false,
|
postal_coder: false,
|
||||||
categories: false,
|
categories: false,
|
||||||
cover: false,
|
cover: true,
|
||||||
images: false,
|
images: false,
|
||||||
city: false,
|
city: false,
|
||||||
},
|
},
|
||||||
conditions: {
|
conditions: {
|
||||||
'admin::is-creator': false,
|
'admin::is-creator': true,
|
||||||
'admin::has-same-role-as-creator': false,
|
'admin::has-same-role-as-creator': false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -336,10 +349,10 @@ describe('ADMIN | COMPONENTS | Permissions | utils', () => {
|
|||||||
f2: false,
|
f2: false,
|
||||||
services: { name: false, media: false, closing: { name: { test: false } } },
|
services: { name: false, media: false, closing: { name: { test: false } } },
|
||||||
dz: false,
|
dz: false,
|
||||||
relation: false,
|
relation: true,
|
||||||
},
|
},
|
||||||
locales: {
|
locales: {
|
||||||
en: false,
|
en: true,
|
||||||
fr: false,
|
fr: false,
|
||||||
},
|
},
|
||||||
conditions: {
|
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,
|
isLoading: isRoleLoading,
|
||||||
onSubmitSucceeded,
|
onSubmitSucceeded,
|
||||||
} = useFetchRole(id);
|
} = useFetchRole(id);
|
||||||
console.log({ rolePermissions });
|
|
||||||
|
|
||||||
/* eslint-disable indent */
|
/* eslint-disable indent */
|
||||||
const headerActions = (handleSubmit, handleReset) =>
|
const headerActions = (handleSubmit, handleReset) =>
|
||||||
@ -177,7 +176,11 @@ const EditPage = () => {
|
|||||||
/>
|
/>
|
||||||
{!isLayoutLoading && !isRoleLoading && (
|
{!isLayoutLoading && !isRoleLoading && (
|
||||||
<Padded top bottom size="md">
|
<Padded top bottom size="md">
|
||||||
<Permissions isFormDisabled={isFormDisabled} ref={permissionsRef} />
|
<Permissions
|
||||||
|
isFormDisabled={isFormDisabled}
|
||||||
|
permissions={rolePermissions}
|
||||||
|
ref={permissionsRef}
|
||||||
|
/>
|
||||||
</Padded>
|
</Padded>
|
||||||
)}
|
)}
|
||||||
</ContainerFluid>
|
</ContainerFluid>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user