Fix merge conflict

This commit is contained in:
Tuan Dang
2024-05-07 10:45:07 -07:00
73 changed files with 4219 additions and 158 deletions
@@ -0,0 +1,13 @@
export {
useCreateAccessApprovalPolicy,
useCreateAccessRequest,
useDeleteAccessApprovalPolicy,
useReviewAccessRequest,
useUpdateAccessApprovalPolicy
} from "./mutation";
export {
useGetAccessApprovalPolicies,
useGetAccessApprovalRequests,
useGetAccessPolicyApprovalCount,
useGetAccessRequestsCount
} from "./queries";
@@ -0,0 +1,123 @@
import { packRules } from "@casl/ability/extra";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { accessApprovalKeys } from "./queries";
import {
TAccessApproval,
TCreateAccessPolicyDTO,
TCreateAccessRequestDTO,
TDeleteSecretPolicyDTO,
TUpdateAccessPolicyDTO
} from "./types";
export const useCreateAccessApprovalPolicy = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TCreateAccessPolicyDTO>({
mutationFn: async ({ environment, projectSlug, approvals, approvers, name, secretPath }) => {
const { data } = await apiRequest.post("/api/v1/access-approvals/policies", {
environment,
projectSlug,
approvals,
approvers,
secretPath,
name
});
return data;
},
onSuccess: (_, { projectSlug }) => {
queryClient.invalidateQueries(accessApprovalKeys.getAccessApprovalPolicies(projectSlug));
}
});
};
export const useUpdateAccessApprovalPolicy = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TUpdateAccessPolicyDTO>({
mutationFn: async ({ id, approvers, approvals, name, secretPath }) => {
const { data } = await apiRequest.patch(`/api/v1/access-approvals/policies/${id}`, {
approvals,
approvers,
secretPath,
name
});
return data;
},
onSuccess: (_, { projectSlug }) => {
queryClient.invalidateQueries(accessApprovalKeys.getAccessApprovalPolicies(projectSlug));
}
});
};
export const useDeleteAccessApprovalPolicy = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TDeleteSecretPolicyDTO>({
mutationFn: async ({ id }) => {
const { data } = await apiRequest.delete(`/api/v1/access-approvals/policies/${id}`);
return data;
},
onSuccess: (_, { projectSlug }) => {
queryClient.invalidateQueries(accessApprovalKeys.getAccessApprovalPolicies(projectSlug));
}
});
};
export const useCreateAccessRequest = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TCreateAccessRequestDTO>({
mutationFn: async ({ projectSlug, ...request }) => {
const { data } = await apiRequest.post<TAccessApproval>(
"/api/v1/access-approvals/requests",
{
...request,
permissions: request.permissions ? packRules(request.permissions) : undefined
},
{
params: {
projectSlug
}
}
);
return data;
},
onSuccess: (_, { projectSlug }) => {
queryClient.invalidateQueries(accessApprovalKeys.getAccessApprovalRequestCount(projectSlug));
}
});
};
export const useReviewAccessRequest = () => {
const queryClient = useQueryClient();
return useMutation<
{},
{},
{
requestId: string;
status: "approved" | "rejected";
projectSlug: string;
envSlug?: string;
requestedBy?: string;
}
>({
mutationFn: async ({ requestId, status }) => {
const { data } = await apiRequest.post(
`/api/v1/access-approvals/requests/${requestId}/review`,
{
status
}
);
return data;
},
onSuccess: (_, { projectSlug, envSlug, requestedBy }) => {
queryClient.invalidateQueries(
accessApprovalKeys.getAccessApprovalRequests(projectSlug, envSlug, requestedBy)
);
queryClient.invalidateQueries(accessApprovalKeys.getAccessApprovalRequestCount(projectSlug));
}
});
};
@@ -0,0 +1,159 @@
import { PackRule, unpackRules } from "@casl/ability/extra";
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { TProjectPermission } from "../roles/types";
import {
TAccessApprovalPolicy,
TAccessApprovalRequest,
TAccessRequestCount,
TGetAccessApprovalRequestsDTO,
TGetAccessPolicyApprovalCountDTO
} from "./types";
export const accessApprovalKeys = {
getAccessApprovalPolicies: (projectSlug: string) =>
[{ projectSlug }, "access-approval-policies"] as const,
getAccessApprovalPolicyOfABoard: (workspaceId: string, environment: string) =>
[{ workspaceId, environment }, "access-approval-policy"] as const,
getAccessApprovalRequests: (projectSlug: string, envSlug?: string, requestedBy?: string) =>
[{ projectSlug, envSlug, requestedBy }, "access-approvals-requests"] as const,
getAccessApprovalRequestCount: (projectSlug: string) =>
[{ projectSlug }, "access-approval-request-count"] as const
};
export const fetchPolicyApprovalCount = async ({
projectSlug,
envSlug
}: TGetAccessPolicyApprovalCountDTO) => {
const { data } = await apiRequest.get<{ count: number }>(
"/api/v1/access-approvals/policies/count",
{
params: { projectSlug, envSlug }
}
);
return data.count;
};
export const useGetAccessPolicyApprovalCount = ({
projectSlug,
envSlug,
options = {}
}: TGetAccessPolicyApprovalCountDTO & {
options?: UseQueryOptions<
number,
unknown,
number,
ReturnType<typeof accessApprovalKeys.getAccessApprovalPolicies>
>;
}) =>
useQuery({
queryFn: () => fetchPolicyApprovalCount({ projectSlug, envSlug }),
...options,
enabled: Boolean(projectSlug) && (options?.enabled ?? true)
});
const fetchApprovalPolicies = async ({ projectSlug }: TGetAccessApprovalRequestsDTO) => {
const { data } = await apiRequest.get<{ approvals: TAccessApprovalPolicy[] }>(
"/api/v1/access-approvals/policies",
{ params: { projectSlug } }
);
return data.approvals;
};
const fetchApprovalRequests = async ({
projectSlug,
envSlug,
authorProjectMembershipId
}: TGetAccessApprovalRequestsDTO) => {
const { data } = await apiRequest.get<{ requests: TAccessApprovalRequest[] }>(
"/api/v1/access-approvals/requests",
{ params: { projectSlug, envSlug, authorProjectMembershipId } }
);
return data.requests.map((request) => ({
...request,
privilege: request.privilege
? {
...request.privilege,
permissions: unpackRules(
request.privilege.permissions as unknown as PackRule<TProjectPermission>[]
)
}
: null,
permissions: unpackRules(request.permissions as unknown as PackRule<TProjectPermission>[])
}));
};
const fetchAccessRequestsCount = async (projectSlug: string) => {
const { data } = await apiRequest.get<TAccessRequestCount>(
"/api/v1/access-approvals/requests/count",
{ params: { projectSlug } }
);
return data;
};
export const useGetAccessRequestsCount = ({
projectSlug,
options = {}
}: TGetAccessApprovalRequestsDTO & {
options?: UseQueryOptions<
TAccessRequestCount,
unknown,
{ pendingCount: number; finalizedCount: number },
ReturnType<typeof accessApprovalKeys.getAccessApprovalRequestCount>
>;
}) =>
useQuery({
queryKey: accessApprovalKeys.getAccessApprovalRequestCount(projectSlug),
queryFn: () => fetchAccessRequestsCount(projectSlug),
...options,
enabled: Boolean(projectSlug) && (options?.enabled ?? true)
});
export const useGetAccessApprovalPolicies = ({
projectSlug,
envSlug,
authorProjectMembershipId,
options = {}
}: TGetAccessApprovalRequestsDTO & {
options?: UseQueryOptions<
TAccessApprovalPolicy[],
unknown,
TAccessApprovalPolicy[],
ReturnType<typeof accessApprovalKeys.getAccessApprovalPolicies>
>;
}) =>
useQuery({
queryKey: accessApprovalKeys.getAccessApprovalPolicies(projectSlug),
queryFn: () => fetchApprovalPolicies({ projectSlug, envSlug, authorProjectMembershipId }),
...options,
enabled: Boolean(projectSlug) && (options?.enabled ?? true)
});
export const useGetAccessApprovalRequests = ({
projectSlug,
envSlug,
authorProjectMembershipId,
options = {}
}: TGetAccessApprovalRequestsDTO & {
options?: UseQueryOptions<
TAccessApprovalRequest[],
unknown,
TAccessApprovalRequest[],
ReturnType<typeof accessApprovalKeys.getAccessApprovalRequests>
>;
}) =>
useQuery({
queryKey: accessApprovalKeys.getAccessApprovalRequests(
projectSlug,
envSlug,
authorProjectMembershipId
),
queryFn: () => fetchApprovalRequests({ projectSlug, envSlug, authorProjectMembershipId }),
...options,
enabled: Boolean(projectSlug) && (options?.enabled ?? true)
});
@@ -0,0 +1,139 @@
import { TProjectPermission } from "../roles/types";
import { WorkspaceEnv } from "../workspace/types";
export type TAccessApprovalPolicy = {
id: string;
name: string;
approvals: number;
secretPath: string;
envId: string;
workspace: string;
environment: WorkspaceEnv;
projectId: string;
approvers: string[];
};
export type TAccessApprovalRequest = {
id: string;
policyId: string;
privilegeId: string | null;
requestedBy: string;
createdAt: Date;
updatedAt: Date;
isTemporary: boolean;
temporaryRange: string | null | undefined;
permissions: TProjectPermission[] | null;
// Computed
environmentName: string;
isApproved: boolean;
privilege: {
membershipId: string;
isTemporary: boolean;
temporaryMode?: string | null;
temporaryRange?: string | null;
temporaryAccessStartTime?: Date | null;
temporaryAccessEndTime?: Date | null;
permissions: TProjectPermission[];
isApproved: boolean;
} | null;
policy: {
id: string;
name: string;
approvals: number;
approvers: string[];
secretPath?: string | null;
envId: string;
};
reviewers: {
member: string;
status: string;
}[];
};
export type TAccessApproval = {
id: string;
policyId: string;
privilegeId: string;
requestedBy: string;
};
export type TAccessRequestCount = {
pendingCount: number;
finalizedCount: number;
};
export type TProjectUserPrivilege = {
projectMembershipId: string;
slug: string;
id: string;
createdAt: Date;
updatedAt: Date;
permissions?: TProjectPermission[];
} & (
| {
isTemporary: true;
temporaryMode: string;
temporaryRange: string;
temporaryAccessStartTime: string;
temporaryAccessEndTime?: string;
}
| {
isTemporary: false;
temporaryMode?: null;
temporaryRange?: null;
temporaryAccessStartTime?: null;
temporaryAccessEndTime?: null;
}
);
export type TCreateAccessRequestDTO = {
projectSlug: string;
} & Omit<TProjectUserPrivilege, "id" | "createdAt" | "updatedAt" | "slug" | "projectMembershipId">;
export type TGetAccessApprovalRequestsDTO = {
projectSlug: string;
envSlug?: string;
authorProjectMembershipId?: string;
};
export type TGetAccessPolicyApprovalCountDTO = {
projectSlug: string;
envSlug: string;
};
export type TGetSecretApprovalPolicyOfBoardDTO = {
workspaceId: string;
environment: string;
secretPath: string;
};
export type TCreateAccessPolicyDTO = {
projectSlug: string;
name?: string;
environment: string;
approvers?: string[];
approvals?: number;
secretPath?: string;
};
export type TUpdateAccessPolicyDTO = {
id: string;
name?: string;
approvers?: string[];
secretPath?: string;
environment?: string;
approvals?: number;
// for invalidating list
projectSlug: string;
};
export type TDeleteSecretPolicyDTO = {
id: string;
// for invalidating list
projectSlug: string;
};
+1
View File
@@ -1,3 +1,4 @@
export * from "./accessApproval";
export * from "./admin";
export * from "./apiKeys";
export * from "./auditLogs";
@@ -94,7 +94,21 @@ export const useGetFoldersByEnv = ({
[(folders || []).map((folder) => folder.data)]
);
return { folders, folderNames, isFolderPresentInEnv };
const getFolderByNameAndEnv = useCallback(
(name: string, env: string) => {
const selectedEnvIndex = environments.indexOf(env);
if (selectedEnvIndex !== -1) {
return folders?.[selectedEnvIndex]?.data?.find(
({ name: folderName }) => folderName === name
);
}
return undefined;
},
[(folders || []).map((folder) => folder.data)]
);
return { folders, folderNames, isFolderPresentInEnv, getFolderByNameAndEnv };
};
export const useCreateFolder = () => {
+9 -8
View File
@@ -1,5 +1,6 @@
import { ZodIssue } from "zod";
export type { TAccessApprovalPolicy } from "./accessApproval/types";
export type { TAuditLogStream } from "./auditLogStreams/types";
export type { GetAuthTokenAPI } from "./auth/types";
export type { IncidentContact } from "./incidentContacts/types";
@@ -49,13 +50,13 @@ export enum ApiErrorTypes {
export type TApiErrors =
| {
error: ApiErrorTypes.ValidationError;
message: ZodIssue[];
statusCode: 403;
}
error: ApiErrorTypes.ValidationError;
message: ZodIssue[];
statusCode: 403;
}
| { error: ApiErrorTypes.ForbiddenError; message: string; statusCode: 401 }
| {
statusCode: 400;
message: string;
error: ApiErrorTypes.BadRequestError;
};
statusCode: 400;
message: string;
error: ApiErrorTypes.BadRequestError;
};