Files
pole-book/server/node_modules/@strapi/content-manager/dist/admin/features/DocumentRBAC.mjs

105 lines
4.6 KiB
JavaScript

import { jsx } from 'react/jsx-runtime';
import * as React from 'react';
import { createContext, useQueryParams, useAuth, useRBAC, Page } from '@strapi/admin/strapi-admin';
import { useParams } from 'react-router-dom';
const [DocumentRBACProvider, useDocumentRBAC] = createContext('DocumentRBAC', {
canCreate: false,
canCreateFields: [],
canDelete: false,
canPublish: false,
canRead: false,
canReadFields: [],
canUpdate: false,
canUpdateFields: [],
canUserAction: ()=>false,
isLoading: false
});
/**
* @internal This component is not meant to be used outside of the Content Manager plugin.
* It depends on knowing the slug/model of the content-type using the params of the URL or the model if it is passed as arg.
* If you do use the hook outside of the context, we default to `false` for all actions.
*
* It then creates an list of `can{Action}` that are passed to the context for consumption
* within the app to enforce RBAC.
*/ const DocumentRBAC = ({ children, permissions, model })=>{
const { slug } = useParams();
if (!slug && !model) {
throw new Error('Cannot find the slug param in the URL or the model prop is not provided.');
}
const contentTypeUid = model ?? slug;
const [{ rawQuery }] = useQueryParams();
const userPermissions = useAuth('DocumentRBAC', (state)=>state.permissions);
const contentTypePermissions = React.useMemo(()=>{
const contentTypePermissions = userPermissions.filter((permission)=>permission.subject === contentTypeUid);
return contentTypePermissions.reduce((acc, permission)=>{
const [action] = permission.action.split('.').slice(-1);
return {
...acc,
[action]: [
permission
]
};
}, {});
}, [
contentTypeUid,
userPermissions
]);
const { isLoading, allowedActions } = useRBAC(contentTypePermissions, permissions ?? undefined, // TODO: useRBAC context should be typed and built differently
// We are passing raw query as context to the hook so that it can
// rely on the locale provided from DocumentRBAC for its permission calculations.
rawQuery);
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
/**
* @description Checks if the user can perform an action on a field based on the field names
* provided as the second argument.
*/ const canUserAction = React.useCallback((fieldName, fieldsUserCanAction, fieldType)=>{
const name = removeNumericalStrings(fieldName.split('.'));
const componentFieldNames = fieldsUserCanAction// filter out fields that aren't components (components are dot separated)
.filter((field)=>field.split('.').length > 1);
if (fieldType === 'component') {
// check if the field name is within any of those arrays
return componentFieldNames.some((field)=>{
return field.includes(name.join('.'));
});
}
/**
* The field is within a component.
*/ if (name.length > 1) {
return componentFieldNames.includes(name.join('.'));
}
/**
* just a regular field
*/ return fieldsUserCanAction.includes(fieldName);
}, []);
if (isLoading) {
return /*#__PURE__*/ jsx(Page.Loading, {});
}
return /*#__PURE__*/ jsx(DocumentRBACProvider, {
isLoading: isLoading,
canCreateFields: canCreateFields,
canReadFields: canReadFields,
canUpdateFields: canUpdateFields,
canUserAction: canUserAction,
...allowedActions,
children: children
});
};
/**
* @internal it's really small, but it's used three times in a row and DRY for something this straight forward.
*/ const extractAndDedupeFields = (permissions = [])=>permissions.flatMap((permission)=>permission.properties?.fields).filter((field, index, arr)=>arr.indexOf(field) === index && typeof field === 'string');
/**
* @internal removes numerical strings from arrays.
* @example
* ```ts
* const name = 'a.0.b';
* const res = removeNumericalStrings(name.split('.'));
* console.log(res); // ['a', 'b']
* ```
*/ const removeNumericalStrings = (arr)=>arr.filter((item)=>isNaN(Number(item)));
export { DocumentRBAC, useDocumentRBAC };
//# sourceMappingURL=DocumentRBAC.mjs.map