import { useFieldSchema } from '@formily/react'; import { useCookieState } from 'ahooks'; import { Spin } from 'antd'; import React, { createContext, useContext } from 'react'; import { Redirect } from 'react-router-dom'; import { useRequest } from '../api-client'; import { useCollection } from '../collection-manager'; import { useRecordIsOwn } from '../record-provider'; import { SchemaComponentOptions, useDesignable } from '../schema-component'; export const ACLContext = createContext(null); export const ACLProvider = (props) => { return ( {props.children} ); }; export const ACLRolesCheckProvider = (props) => { const { setDesignable } = useDesignable(); const [roleName, setRoleName] = useCookieState('currentRoleName'); const result = useRequest( { url: 'roles:check', }, { onSuccess(data) { if (!data?.data?.allowConfigure && !data?.data?.allowAll) { setDesignable(false); } if (data?.data?.role !== roleName) { setRoleName(data?.data?.role); } }, }, ); if (result.loading) { return ; } if (result.error) { return ; } return {props.children}; }; export const useRoleRecheck = () => { const ctx = useContext(ACLContext); const { allowAll, allowConfigure } = useACLRoleContext(); return () => { if (allowAll || allowConfigure) { return; } ctx.refresh(); }; }; export const useACLContext = () => { return useContext(ACLContext); }; export const useACLRoleContext = () => { const ctx = useContext(ACLContext); const data = ctx.data?.data; return { ...data, getActionParams(path: string, { skipOwnCheck, isOwn }) { const [resourceName, act] = path.split(':'); const currentAction = data?.actionAlias?.[act] || act; const hasResource = data?.resources?.includes(resourceName); const params = data?.actions?.[`${resourceName}:${currentAction}`]; if (hasResource) { if (!skipOwnCheck && params?.own) { return isOwn ? params : null; } return params; } const strategyActions = data?.strategy?.actions || []; const strategyAction = strategyActions?.find((action) => { const [value] = action.split(':'); return value === currentAction; }); if (!strategyAction) { return; } if (skipOwnCheck) { return {}; } const [, actionScope] = strategyAction.split(':'); if (actionScope === 'own') { return isOwn; } return {}; }, }; }; export const ACLAllowConfigure = (props) => { const { allowAll, allowConfigure } = useACLRoleContext(); if (allowAll || allowConfigure) { return <>{props.children}; } return null; }; const ACLActionParamsContext = createContext({}); export const ACLCollectionProvider = (props) => { const { allowAll, allowConfigure, getActionParams } = useACLRoleContext(); const fieldSchema = useFieldSchema(); const isOwn = useRecordIsOwn(); if (allowAll || allowConfigure) { return <>{props.children}; } const path = fieldSchema['x-acl-action']; const skipScopeCheck = fieldSchema['x-acl-action-props']?.skipScopeCheck; if (!path) { return <>{props.children}; } const params = getActionParams(path, { isOwn, skipOwnCheck: skipScopeCheck === false ? false : true }); if (!params) { return null; } return {props.children}; }; export const ACLActionProvider = (props) => { const { name } = useCollection(); const fieldSchema = useFieldSchema(); const isOwn = useRecordIsOwn(); const { allowAll, allowConfigure, getActionParams } = useACLRoleContext(); if (!name || allowAll || allowConfigure) { return <>{props.children}; } const actionName = fieldSchema['x-action']; const path = fieldSchema['x-acl-action'] || `${name}:${actionName}`; const skipScopeCheck = fieldSchema['x-acl-action-props']?.skipScopeCheck; const params = getActionParams(path, { skipOwnCheck: skipScopeCheck, isOwn }); if (!params) { return null; } return {props.children}; }; export const ACLCollectionFieldProvider = (props) => { return <>{props.children}; }; export const ACLMenuItemProvider = (props) => { const { allowAll, allowConfigure, allowMenuItemIds = [] } = useACLRoleContext(); const fieldSchema = useFieldSchema(); if (allowAll || allowConfigure) { return <>{props.children}; } if (!fieldSchema['x-uid']) { return <>{props.children}; } if (allowMenuItemIds.includes(fieldSchema['x-uid'])) { return <>{props.children}; } return null; }; export default ACLProvider;