fix: secret approval loading failed for commiter on approval

This commit is contained in:
Akhil Mohan
2023-12-15 18:10:54 +05:30
parent 99c8dda4e1
commit 80e50d13ec
4 changed files with 70 additions and 60 deletions

View File

@@ -17,12 +17,12 @@ export const getSecretApprovalRequestCount = async (req: Request, res: Response)
} = await validateRequest(reqValidator.getSecretApprovalRequestCount, req);
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
const approvalRequestCount = await SecretApprovalRequest.aggregate([
@@ -73,12 +73,12 @@ export const getSecretApprovalRequests = async (req: Request, res: Response) =>
} = await validateRequest(reqValidator.getSecretApprovalRequests, req);
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
const query = {
@@ -168,13 +168,13 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
// allow to fetch only if its admin or is the committer or approver
if (
membership.role !== "admin" &&
secretApprovalRequest.committer !== membership.id &&
!secretApprovalRequest.committer.equals(membership.id) &&
!secretApprovalRequest.policy.approvers.find(
(approverId) => approverId.toString() === membership._id.toString()
)
@@ -215,7 +215,7 @@ export const updateSecretApprovalReviewStatus = async (req: Request, res: Respon
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
@@ -257,7 +257,7 @@ export const mergeSecretApprovalRequest = async (req: Request, res: Response) =>
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
@@ -307,7 +307,7 @@ export const updateSecretApprovalRequestStatus = async (req: Request, res: Respo
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (

View File

@@ -63,7 +63,7 @@ export const SecretApprovalRequest = () => {
(prev, curr) => ({ ...prev, [curr._id]: curr }),
{}
);
const myMembershipId = members?.find(({ user }) => user._id === presentUser._id)?._id;
const myMembershipId = members?.find(({ user }) => user._id === presentUser?._id)?._id;
const isSecretApprovalScreen = Boolean(selectedApproval);
const handleGoBackSecretRequestDetail = () => {
@@ -101,7 +101,7 @@ export const SecretApprovalRequest = () => {
exit={{ opacity: 0, translateX: 30 }}
className="rounded-md text-gray-300"
>
<div className="p-4 px-8 flex items-center space-x-8 bg-mineshaft-800 rounded-t-md border-t border-x border-mineshaft-600">
<div className="flex items-center space-x-8 rounded-t-md border-x border-t border-mineshaft-600 bg-mineshaft-800 p-4 px-8">
<div
role="button"
tabIndex={0}
@@ -110,7 +110,7 @@ export const SecretApprovalRequest = () => {
if (evt.key === "Enter") setStatusFilter("open");
}}
className={
statusFilter === "close" ? "text-gray-500 hover:text-gray-400 duration-100" : ""
statusFilter === "close" ? "text-gray-500 duration-100 hover:text-gray-400" : ""
}
>
<FontAwesomeIcon icon={faCodeBranch} className="mr-2" />
@@ -118,7 +118,7 @@ export const SecretApprovalRequest = () => {
</div>
<div
className={
statusFilter === "open" ? "text-gray-500 hover:text-gray-400 duration-100" : ""
statusFilter === "open" ? "text-gray-500 duration-100 hover:text-gray-400" : ""
}
role="button"
tabIndex={0}
@@ -130,7 +130,7 @@ export const SecretApprovalRequest = () => {
<FontAwesomeIcon icon={faCheck} className="mr-2" />
{isSecretApprovalReqCountSuccess && secretApprovalRequestCount.closed} Closed
</div>
<div className="flex-grow flex justify-end space-x-8">
<div className="flex flex-grow justify-end space-x-8">
<DropdownMenu>
<DropdownMenuTrigger>
<Button
@@ -185,7 +185,7 @@ export const SecretApprovalRequest = () => {
</DropdownMenu>
</div>
</div>
<div className="flex flex-col border-t border-mineshaft-600 bg-mineshaft-800 rounded-b-md border-b border-x border-mineshaft-600">
<div className="flex flex-col rounded-b-md border-x border-t border-b border-mineshaft-600 border-mineshaft-600 bg-mineshaft-800">
{isRequestListEmpty && (
<div className="py-12">
<EmptyState title="No more requests pending." />
@@ -246,9 +246,9 @@ export const SecretApprovalRequest = () => {
>
<div className="mb-2 flex items-center">
<FontAwesomeIcon icon={faCodeBranch} className="mr-2" />
<Skeleton className="bg-mineshaft-600 w-1/4" />
<Skeleton className="w-1/4 bg-mineshaft-600" />
</div>
<Skeleton className="bg-mineshaft-600 w-1/2" />
<Skeleton className="w-1/2 bg-mineshaft-600" />
</div>
))}
</div>

View File

@@ -22,6 +22,7 @@ type Props = {
isMergable?: boolean;
status: "close" | "open";
approvals: number;
canApprove?: boolean;
statusChangeByEmail: string;
workspaceId: string;
};
@@ -33,7 +34,8 @@ export const SecretApprovalRequestAction = ({
isMergable,
approvals,
statusChangeByEmail,
workspaceId
workspaceId,
canApprove
}: Props) => {
const { createNotification } = useNotificationContext();
const { mutateAsync: performSecretApprovalMerge, isLoading: isMerging } =
@@ -83,11 +85,11 @@ export const SecretApprovalRequestAction = ({
if (!hasMerged && status === "open") {
return (
<div className="flex justify-between items-center w-full">
<div className="flex space-x-4 items-start">
<div className="flex w-full items-center justify-between">
<div className="flex items-start space-x-4">
<FontAwesomeIcon
icon={isMergable ? faSquareCheck : faSquareXmark}
className={twMerge("text-2xl pt-1", isMergable ? "text-primary" : "text-red-600")}
className={twMerge("pt-1 text-2xl", isMergable ? "text-primary" : "text-red-600")}
/>
<span className="flex flex-col">
{isMergable ? "Good to merge" : "Review required"}
@@ -98,25 +100,31 @@ export const SecretApprovalRequestAction = ({
</span>
</div>
<div className="flex items-center space-x-2">
<Button
onClick={() => handleSecretApprovalStatusChange("close")}
isLoading={isStatusChanging}
variant="outline_bg"
colorSchema="secondary"
leftIcon={<FontAwesomeIcon icon={faClose} />}
>
Close request
</Button>
<Button
leftIcon={<FontAwesomeIcon icon={faCheck} />}
isDisabled={!isMergable}
isLoading={isMerging}
onClick={handleSecretApprovalRequestMerge}
colorSchema="primary"
variant="solid"
>
Merge
</Button>
{canApprove ? (
<>
<Button
onClick={() => handleSecretApprovalStatusChange("close")}
isLoading={isStatusChanging}
variant="outline_bg"
colorSchema="secondary"
leftIcon={<FontAwesomeIcon icon={faClose} />}
>
Close request
</Button>
<Button
leftIcon={<FontAwesomeIcon icon={faCheck} />}
isDisabled={!isMergable}
isLoading={isMerging}
onClick={handleSecretApprovalRequestMerge}
colorSchema="primary"
variant="solid"
>
Merge
</Button>
</>
) : (
<div>Only approvers can merge</div>
)}
</div>
</div>
);
@@ -124,9 +132,9 @@ export const SecretApprovalRequestAction = ({
if (hasMerged && status === "close")
return (
<div className="flex justify-between items-center w-full">
<div className="flex space-x-4 items-start">
<FontAwesomeIcon icon={faCheck} className="text-2xl text-primary pt-1" />
<div className="flex w-full items-center justify-between">
<div className="flex items-start space-x-4">
<FontAwesomeIcon icon={faCheck} className="pt-1 text-2xl text-primary" />
<span className="flex flex-col">
Change request merged
<span className="inline-block text-xs text-bunker-200">
@@ -138,9 +146,9 @@ export const SecretApprovalRequestAction = ({
);
return (
<div className="flex justify-between items-center w-full">
<div className="flex space-x-4 items-start">
<FontAwesomeIcon icon={faUserLock} className="text-2xl text-primary pt-1" />
<div className="flex w-full items-center justify-between">
<div className="flex items-start space-x-4">
<FontAwesomeIcon icon={faUserLock} className="pt-1 text-2xl text-primary" />
<span className="flex flex-col">
Change request has been closed
<span className="inline-block text-xs text-bunker-200">

View File

@@ -108,6 +108,7 @@ export const SecretApprovalRequestChanges = ({
({ user: membershipUser }) => membershipUser.email === user.email
);
const myMembershipId = myMembership?._id || "";
const canApprove = secretApprovalRequestDetails?.policy?.approvers?.includes(myMembershipId);
const reviewedMembers = secretApprovalRequestDetails?.reviewers?.reduce<
Record<string, ApprovalStatus>
>(
@@ -164,30 +165,30 @@ export const SecretApprovalRequestChanges = ({
return (
<div className="flex space-x-6">
<div className="flex-grow">
<div className="flex items-center space-x-4 pt-2 pb-6 sticky top-0 z-20 bg-bunker-800">
<div className="sticky top-0 z-20 flex items-center space-x-4 bg-bunker-800 pt-2 pb-6">
<IconButton variant="outline_bg" ariaLabel="go-back" onClick={onGoBack}>
<FontAwesomeIcon icon={faArrowLeft} />
</IconButton>
<div className="bg-red-600 text-white flex items-center space-x-2 px-4 py-2 rounded-3xl">
<div className="flex items-center space-x-2 rounded-3xl bg-red-600 px-4 py-2 text-white">
<FontAwesomeIcon icon={faCodeBranch} size="sm" />
<span>{secretApprovalRequestDetails.status}</span>
</div>
<div className="flex flex-col flex-grow">
<div className="text-lg mb-1">
<div className="flex flex-grow flex-col">
<div className="mb-1 text-lg">
{generateCommitText(secretApprovalRequestDetails.commits)}
</div>
<div className="text-sm text-bunker-300 flex items-center">
<div className="flex items-center text-sm text-bunker-300">
{committer?.user?.firstName}
{committer?.user?.lastName} ({committer?.user?.email}) wants to change{" "}
{secretApprovalRequestDetails.commits.length} secret values in
<span className="text-primary-300 bg-primary-600/60 px-1 mx-1 rounded">
<span className="mx-1 rounded bg-primary-600/60 px-1 text-primary-300">
{secretApprovalRequestDetails.environment}
</span>
<div className="flex items-center border border-mineshaft-500 pl-1 pr-2 rounded w-min">
<div className="flex w-min items-center rounded border border-mineshaft-500 pl-1 pr-2">
<div className="border-r border-mineshaft-500 pr-1">
<FontAwesomeIcon icon={faFolder} className="text-primary" size="sm" />
</div>
<div className="text-sm pl-2 pb-0.5">{secretApprovalRequestDetails.secretPath}</div>
<div className="pl-2 pb-0.5 text-sm">{secretApprovalRequestDetails.secretPath}</div>
</div>
</div>
</div>
@@ -198,7 +199,7 @@ export const SecretApprovalRequestChanges = ({
leftIcon={hasApproved && <FontAwesomeIcon icon={faCheck} />}
onClick={() => handleSecretApprovalStatusUpdate(ApprovalStatus.APPROVED)}
isLoading={isApproving}
isDisabled={isApproving || hasApproved}
isDisabled={isApproving || hasApproved || !canApprove}
>
{hasApproved ? "Approved" : "Approve"}
</Button>
@@ -208,7 +209,7 @@ export const SecretApprovalRequestChanges = ({
leftIcon={hasRejected && <FontAwesomeIcon icon={faCheck} />}
onClick={() => handleSecretApprovalStatusUpdate(ApprovalStatus.REJECTED)}
isLoading={isRejecting}
isDisabled={isRejecting || hasRejected}
isDisabled={isRejecting || hasRejected || !canApprove}
>
{hasRejected ? "Rejected" : "Reject"}
</Button>
@@ -230,8 +231,9 @@ export const SecretApprovalRequestChanges = ({
)
)}
</div>
<div className="flex items-center px-5 py-6 rounded-lg space-x-6 bg-mineshaft-800 mt-8">
<div className="mt-8 flex items-center space-x-6 rounded-lg bg-mineshaft-800 px-5 py-6">
<SecretApprovalRequestAction
canApprove={canApprove}
approvalRequestId={secretApprovalRequestDetails._id}
hasMerged={hasMerged}
approvals={secretApprovalRequestDetails.policy.approvals || 0}
@@ -244,7 +246,7 @@ export const SecretApprovalRequestChanges = ({
/>
</div>
</div>
<div className="w-1/5 pt-4 sticky top-0" style={{ minWidth: "240px" }}>
<div className="sticky top-0 w-1/5 pt-4" style={{ minWidth: "240px" }}>
<div className="text-sm text-bunker-300">Reviewers</div>
<div className="mt-2 flex flex-col space-y-2 text-sm">
{secretApprovalRequestDetails?.policy?.approvers.map((requiredApproverId) => {
@@ -252,7 +254,7 @@ export const SecretApprovalRequestChanges = ({
const status = reviewedMembers?.[requiredApproverId];
return (
<div
className="flex items-center space-x-2 flex-nowrap bg-mineshaft-800 px-2 py-1 rounded"
className="flex flex-nowrap items-center space-x-2 rounded bg-mineshaft-800 px-2 py-1"
key={`required-approver-${requiredApproverId}`}
>
<div className="flex-grow text-sm">
@@ -278,7 +280,7 @@ export const SecretApprovalRequestChanges = ({
const status = reviewedMembers?.[reviewer.status];
return (
<div
className="flex items-center space-x-2 flex-nowrap bg-mineshaft-800 px-2 py-1 rounded"
className="flex flex-nowrap items-center space-x-2 rounded bg-mineshaft-800 px-2 py-1"
key={`required-approver-${reviewer.member}`}
>
<div className="flex-grow text-sm">