feat(rbac): implemented project based permission loading and role management

This commit is contained in:
Akhil Mohan
2023-09-08 21:22:36 +05:30
parent aac3168c80
commit 520a553ea1
63 changed files with 2237 additions and 488 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
export { useCreateRole, useDeleteRole, useUpdateRole } from "./mutation";
export { useGetRoles, useGetUserOrgPermissions } from "./queries";
export { useGetRoles, useGetUserOrgPermissions,useGetUserProjectPermissions } from "./queries";
+4 -4
View File
@@ -5,22 +5,22 @@ import { apiRequest } from "@app/config/request";
import { roleQueryKeys } from "./queries";
import { TCreateRoleDTO, TDeleteRoleDTO, TUpdateRoleDTO } from "./types";
export const useCreateRole = () => {
export const useCreateRole = <T extends string | undefined>() => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (dto: TCreateRoleDTO) => apiRequest.post("/api/v1/roles", dto),
mutationFn: (dto: TCreateRoleDTO<T>) => apiRequest.post("/api/v1/roles", dto),
onSuccess: (_, { orgId, workspaceId }) => {
queryClient.invalidateQueries(roleQueryKeys.getRoles({ orgId, workspaceId }));
}
});
};
export const useUpdateRole = () => {
export const useUpdateRole = <T extends string | undefined>() => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, ...dto }: TUpdateRoleDTO) => apiRequest.patch(`/api/v1/roles/${id}`, dto),
mutationFn: ({ id, ...dto }: TUpdateRoleDTO<T>) => apiRequest.patch(`/api/v1/roles/${id}`, dto),
onSuccess: (_, { orgId, workspaceId }) => {
queryClient.invalidateQueries(roleQueryKeys.getRoles({ orgId, workspaceId }));
}
+39 -8
View File
@@ -4,22 +4,33 @@ import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { OrgPermissionSet } from "@app/context/OrgPermissionContext/types";
import { ProjectPermissionSet } from "@app/context/ProjectPermissionContext/types";
import { TGetRolesDTO, TGetUserOrgPermissionsDTO, TRole } from "./types";
import {
TGetRolesDTO,
TGetUserOrgPermissionsDTO,
TGetUserProjectPermissionDTO,
TRole
} from "./types";
export const roleQueryKeys = {
getRoles: ({ orgId, workspaceId }: TGetRolesDTO) => ["roles", { orgId, workspaceId }] as const,
getUserOrgPermissions: ({ orgId }: TGetUserOrgPermissionsDTO) =>
["user-permissions", { orgId }] as const
["user-permissions", { orgId }] as const,
getUserProjectPermissions: ({ workspaceId }: TGetUserProjectPermissionDTO) =>
["user-project-permissions", { workspaceId }] as const
};
const getRoles = async ({ orgId, workspaceId }: TGetRolesDTO) => {
const { data } = await apiRequest.get<{ data: { roles: TRole[] } }>("/api/v1/roles", {
params: {
workspaceId,
orgId
const { data } = await apiRequest.get<{ data: { roles: TRole<typeof workspaceId>[] } }>(
"/api/v1/roles",
{
params: {
workspaceId,
orgId
}
}
});
);
return data.data.roles;
};
@@ -34,7 +45,7 @@ export const useGetRoles = ({ orgId, workspaceId }: TGetRolesDTO) =>
const getUserOrgPermissions = async ({ orgId }: TGetUserOrgPermissionsDTO) => {
const { data } = await apiRequest.get<{
data: { permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[] };
}>(`/api/v1/roles/${orgId}/permissions`, {});
}>(`/api/v1/roles/organization/${orgId}/permissions`, {});
return data.data.permissions;
};
@@ -50,3 +61,23 @@ export const useGetUserOrgPermissions = ({ orgId }: TGetUserOrgPermissionsDTO) =
return ability;
}
});
const getUserProjectPermissions = async ({ workspaceId }: TGetUserProjectPermissionDTO) => {
const { data } = await apiRequest.get<{
data: { permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[] };
}>(`/api/v1/roles/workspace/${workspaceId}/permissions`, {});
return data.data.permissions;
};
export const useGetUserProjectPermissions = ({ workspaceId }: TGetUserProjectPermissionDTO) =>
useQuery({
queryKey: roleQueryKeys.getUserProjectPermissions({ workspaceId }),
queryFn: () => getUserProjectPermissions({ workspaceId }),
enabled: Boolean(workspaceId),
select: (data) => {
const rule = unpackRules<RawRuleOf<MongoAbility<ProjectPermissionSet>>>(data);
const ability = createMongoAbility<ProjectPermissionSet>(rule);
return ability;
}
});
+35 -9
View File
@@ -3,14 +3,14 @@ export type TGetRolesDTO = {
workspaceId?: string;
};
export type TRole = {
export type TRole<T extends string | undefined> = {
_id: string;
organization: string;
workspace: string;
workspace: T;
name: string;
description: string;
slug: string;
permissions: TPermission[];
permissions: T extends string ? TProjectPermission[] : TPermission[];
createdAt: string;
updatedAt: string;
};
@@ -29,20 +29,42 @@ type TWorkspacePermission = {
subject: "workspace";
};
export type TCreateRoleDTO = {
export type TProjectPermission = TProjectGeneralPermission | TProjectWorkspacePermission;
type TProjectGeneralPermission = {
condition?: Record<string, any>;
action: "read" | "edit" | "create" | "delete";
subject:
| "member"
| "role"
| "settings"
| "secrets"
| "environments"
| "folders"
| "secret-imports"
| "service-tokens";
};
type TProjectWorkspacePermission = {
condition?: Record<string, any>;
action: "delete" | "edit";
subject: "workspace";
};
export type TCreateRoleDTO<T extends string | undefined> = {
orgId: string;
workspaceId?: string;
workspaceId?: T;
name: string;
description?: string;
slug: string;
permissions: TPermission[];
permissions: T extends string ? TProjectPermission[] : TPermission[];
};
export type TUpdateRoleDTO = {
export type TUpdateRoleDTO<T extends string | undefined> = {
orgId: string;
id: string;
workspaceId?: string;
} & Partial<Omit<TCreateRoleDTO, "orgId" | "workspaceId">>;
workspaceId?: T;
} & Partial<Omit<TCreateRoleDTO<T>, "orgId" | "workspaceId">>;
export type TDeleteRoleDTO = {
orgId: string;
@@ -53,3 +75,7 @@ export type TDeleteRoleDTO = {
export type TGetUserOrgPermissionsDTO = {
orgId: string;
};
export type TGetUserProjectPermissionDTO = {
workspaceId: string;
};