utopia-ui/src/Components/Map/hooks/usePermissions.tsx

166 lines
5.3 KiB
TypeScript

import { useCallback, useReducer, createContext, useContext } from "react";
import * as React from "react";
import { Item, ItemsApi, LayerProps, Permission, PermissionAction } from "../../../types";
import { useAuth } from "../../Auth";
type ActionType =
| { type: "ADD"; permission: Permission }
| { type: "REMOVE"; id: string };
type UsePermissionManagerResult = ReturnType<typeof usePermissionsManager>;
const PermissionContext = createContext<UsePermissionManagerResult>({
permissions: [],
setPermissionApi: () => { },
setPermissionData: () => { },
setAdminRole: () => { },
hasUserPermission: () => true
});
function usePermissionsManager(initialPermissions: Permission[]): {
permissions: Permission[];
// eslint-disable-next-line no-unused-vars
setPermissionApi: (api: ItemsApi<any>) => void;
// eslint-disable-next-line no-unused-vars
setPermissionData: (data: Permission[]) => void;
// eslint-disable-next-line no-unused-vars
setAdminRole: (adminRole: string) => void;
// eslint-disable-next-line no-unused-vars
hasUserPermission: (collectionName: string, action: PermissionAction, item?: Item, layer?: LayerProps) => boolean;
} {
const [permissions, dispatch] = useReducer((state: Permission[], action: ActionType) => {
switch (action.type) {
case "ADD":
// eslint-disable-next-line no-case-declarations
const exist = state.find((permission) =>
permission.id === action.permission.id ? true : false
);
if (!exist) return [
...state,
action.permission,
];
else return state;
case "REMOVE":
return state.filter(({ id }) => id !== action.id);
default:
throw new Error();
}
}, initialPermissions);
const [adminRole, setAdminRole] = React.useState<string | null>(null);
const { user } = useAuth();
const setPermissionApi = useCallback(async (api: ItemsApi<Permission>) => {
const result = await api.getItems();
if (result) {
result.map(permission => {
dispatch({ type: "ADD", permission })
})
}
}, [])
const setPermissionData = useCallback((data: Permission[]) => {
data.map(permission => {
dispatch({ type: "ADD", permission })
})
}, []);
const hasUserPermission = useCallback(
(
collectionName: string,
action: PermissionAction,
item?: Item,
layer?: LayerProps
) => {
const evaluateCondition = (condition: any) => {
if (condition.user_created?._eq === "$CURRENT_USER") {
return item?.user_created?.id === user?.id;
}
if (condition.public_edit?._eq === true) {
return item?.public_edit === true;
}
return false;
};
const evaluatePermissions = (permissionConditions: any) => {
if (!permissionConditions || !permissionConditions._and) {
return true;
}
return permissionConditions._and.every((andCondition: any) =>
andCondition._or
? andCondition._or.some((orCondition: any) => evaluateCondition(orCondition))
: evaluateCondition(andCondition)
);
};
// Bedingung für leere Berechtigungen nur, wenn NICHT item und create
if (permissions.length === 0 && !(collectionName === "item" && action === "create")) return true;
else if (user && user.role.id === adminRole) return true;
else {
return permissions.some(p =>
p.action === action &&
p.collection === collectionName &&
(
// Neue Bedingung für "item" und "create"
(collectionName === "item" && action === "create" && layer?.public_edit_items === true) ||
(
(p.policy.name === user?.role.name &&
(
!item || evaluatePermissions(p.permissions)
)) ||
(p.policy == null &&
(
(layer?.public_edit_items || item?.layer?.public_edit_items) &&
(!item || evaluatePermissions(p.permissions))
))
)
)
);
}
},
[permissions, user, adminRole]
);
return { permissions, setPermissionApi, setPermissionData, setAdminRole, hasUserPermission };
}
export const PermissionsProvider: React.FunctionComponent<{
initialPermissions: Permission[], children?: React.ReactNode
}> = ({ initialPermissions, children }) => (
<PermissionContext.Provider value={usePermissionsManager(initialPermissions)}>
{children}
</PermissionContext.Provider>
);
export const usePermissions = (): Permission[] => {
const { permissions } = useContext(PermissionContext);
return permissions;
};
export const useSetPermissionApi = (): UsePermissionManagerResult["setPermissionApi"] => {
const { setPermissionApi } = useContext(PermissionContext);
return setPermissionApi;
}
export const useSetPermissionData = (): UsePermissionManagerResult["setPermissionData"] => {
const { setPermissionData } = useContext(PermissionContext);
return setPermissionData;
}
export const useHasUserPermission = (): UsePermissionManagerResult["hasUserPermission"] => {
const { hasUserPermission } = useContext(PermissionContext);
return hasUserPermission;
}
export const useSetAdminRole = (): UsePermissionManagerResult["setAdminRole"] => {
const { setAdminRole } = useContext(PermissionContext);
return setAdminRole;
}