mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 11:29:42 +00:00
feat(secret-approval): resolved infinite query bug and added support for closing, re-opening request, stale req ui
This commit is contained in:
@@ -35,7 +35,7 @@ export const getSecretApprovalRequests = async (req: Request, res: Response) =>
|
||||
.skip(offset)
|
||||
.populate("policy")
|
||||
.lean();
|
||||
if (!approvalRequests.length) return res.send({ requests: [] });
|
||||
if (!approvalRequests.length) return res.send({ approvals: [] });
|
||||
|
||||
const unqiueEnvs = environment ?? {
|
||||
$in: [...new Set(approvalRequests.map(({ environment }) => environment))]
|
||||
@@ -64,7 +64,7 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
|
||||
params: { id }
|
||||
} = await validateRequest(reqValidator.getSecretApprovalRequestDetails, req);
|
||||
const secretApprovalRequest = await SecretApprovalRequest.findById(id)
|
||||
.populate("policy")
|
||||
.populate<{ policy: ISecretApprovalPolicy }>("policy")
|
||||
.populate({
|
||||
path: "commits.secretVersion",
|
||||
populate: {
|
||||
@@ -84,7 +84,9 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
|
||||
if (
|
||||
membership.role !== "admin" &&
|
||||
secretApprovalRequest.committer !== membership.id &&
|
||||
secretApprovalRequest.reviewers.find(({ member }) => member === membership.id)
|
||||
!secretApprovalRequest.policy.approvers.find(
|
||||
(approverId) => approverId.toString() === membership._id.toString()
|
||||
)
|
||||
) {
|
||||
throw UnauthorizedRequestError({ message: "User has no access" });
|
||||
}
|
||||
@@ -94,11 +96,11 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
|
||||
});
|
||||
};
|
||||
|
||||
export const updateSecretApprovalRequestStatus = async (req: Request, res: Response) => {
|
||||
export const updateSecretApprovalReviewStatus = async (req: Request, res: Response) => {
|
||||
const {
|
||||
body: { status },
|
||||
params: { id }
|
||||
} = await validateRequest(reqValidator.updateSecretApprovalRequestStatus, req);
|
||||
} = await validateRequest(reqValidator.updateSecretApprovalReviewStatus, req);
|
||||
const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{
|
||||
policy: ISecretApprovalPolicy;
|
||||
}>("policy");
|
||||
@@ -132,7 +134,7 @@ export const updateSecretApprovalRequestStatus = async (req: Request, res: Respo
|
||||
|
||||
export const mergeSecretApprovalRequest = async (req: Request, res: Response) => {
|
||||
const {
|
||||
body: { id }
|
||||
params: { id }
|
||||
} = await validateRequest(reqValidator.mergeSecretApprovalRequest, req);
|
||||
|
||||
const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{
|
||||
@@ -149,7 +151,7 @@ export const mergeSecretApprovalRequest = async (req: Request, res: Response) =>
|
||||
if (
|
||||
membership.role !== "admin" &&
|
||||
secretApprovalRequest.committer !== membership.id &&
|
||||
!secretApprovalRequest.policy.approvers.find((approverId) => approverId === membership.id)
|
||||
!secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership.id))
|
||||
) {
|
||||
throw UnauthorizedRequestError({ message: "User has no access" });
|
||||
}
|
||||
@@ -166,6 +168,51 @@ export const mergeSecretApprovalRequest = async (req: Request, res: Response) =>
|
||||
|
||||
if (!hasMinApproval) throw BadRequestError({ message: "Doesn't have minimum approvals needed" });
|
||||
|
||||
const approval = await performSecretApprovalRequestMerge(id, req.authData);
|
||||
const approval = await performSecretApprovalRequestMerge(
|
||||
id,
|
||||
req.authData,
|
||||
membership._id.toString()
|
||||
);
|
||||
return res.send({ approval });
|
||||
};
|
||||
|
||||
export const updateSecretApprovalRequestStatus = async (req: Request, res: Response) => {
|
||||
const {
|
||||
body: { status },
|
||||
params: { id }
|
||||
} = await validateRequest(reqValidator.updateSecretApprovalRequestStatus, req);
|
||||
|
||||
const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{
|
||||
policy: ISecretApprovalPolicy;
|
||||
}>("policy");
|
||||
|
||||
if (!secretApprovalRequest)
|
||||
throw BadRequestError({ message: "Secret approval request not found" });
|
||||
|
||||
const { membership } = await getUserProjectPermissions(
|
||||
req.user._id,
|
||||
secretApprovalRequest.workspace.toString()
|
||||
);
|
||||
|
||||
if (
|
||||
membership.role !== "admin" &&
|
||||
secretApprovalRequest.committer !== membership.id &&
|
||||
!secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership._id))
|
||||
) {
|
||||
throw UnauthorizedRequestError({ message: "User has no access" });
|
||||
}
|
||||
|
||||
if (secretApprovalRequest.hasMerged)
|
||||
throw BadRequestError({ message: "Approval request has been merged" });
|
||||
if (secretApprovalRequest.status === "close" && status === "close")
|
||||
throw BadRequestError({ message: "Approval request is already closed" });
|
||||
if (secretApprovalRequest.status === "open" && status === "open")
|
||||
throw BadRequestError({ message: "Approval request is already open" });
|
||||
|
||||
const updatedRequest = await SecretApprovalRequest.findByIdAndUpdate(
|
||||
id,
|
||||
{ status, statusChangeBy: membership._id },
|
||||
{ new: true }
|
||||
);
|
||||
return res.send({ approval: updatedRequest });
|
||||
};
|
||||
|
||||
@@ -54,6 +54,7 @@ export type ISecretCommits<T = Types.ObjectId, J = Types.ObjectId> = Array<
|
||||
export interface ISecretApprovalRequest {
|
||||
_id: Types.ObjectId;
|
||||
committer: Types.ObjectId;
|
||||
statusChangeBy: Types.ObjectId;
|
||||
reviewers: {
|
||||
member: Types.ObjectId;
|
||||
status: ApprovalStatus;
|
||||
@@ -159,6 +160,7 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||
hasMerged: { type: Boolean, default: false },
|
||||
status: { type: String, enum: ["close", "open"], default: "open" },
|
||||
committer: { type: Schema.Types.ObjectId, ref: "Membership" },
|
||||
statusChangeBy: { type: Schema.Types.ObjectId, ref: "Membership" },
|
||||
commits: [
|
||||
{
|
||||
secret: { type: Types.ObjectId, ref: "Secret" },
|
||||
|
||||
@@ -21,7 +21,7 @@ router.get(
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/merge",
|
||||
"/:id/merge",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT]
|
||||
}),
|
||||
@@ -29,7 +29,15 @@ router.post(
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/:id",
|
||||
"/:id/review",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT]
|
||||
}),
|
||||
secretApprovalRequestController.updateSecretApprovalReviewStatus
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/:id/status",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT]
|
||||
}),
|
||||
|
||||
@@ -317,7 +317,11 @@ export const generateSecretApprovalRequest = async ({
|
||||
};
|
||||
|
||||
// validation for a merge conditions happen in another function in controller
|
||||
export const performSecretApprovalRequestMerge = async (id: string, authData: AuthData) => {
|
||||
export const performSecretApprovalRequestMerge = async (
|
||||
id: string,
|
||||
authData: AuthData,
|
||||
userMembershipId: string
|
||||
) => {
|
||||
const secretApprovalRequest = await SecretApprovalRequest.findById(id)
|
||||
.populate<{ commits: ISecretCommits<ISecret> }>({
|
||||
path: "commits.secret",
|
||||
@@ -636,7 +640,8 @@ export const performSecretApprovalRequestMerge = async (id: string, authData: Au
|
||||
{
|
||||
conflicts,
|
||||
hasMerged: true,
|
||||
status: "close"
|
||||
status: "close",
|
||||
statusChangeBy: userMembershipId
|
||||
},
|
||||
{ new: true }
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ export const getSecretApprovalRequestDetails = z.object({
|
||||
})
|
||||
});
|
||||
|
||||
export const updateSecretApprovalRequestStatus = z.object({
|
||||
export const updateSecretApprovalReviewStatus = z.object({
|
||||
body: z.object({
|
||||
status: z.enum([ApprovalStatus.APPROVED, ApprovalStatus.REJECTED])
|
||||
}),
|
||||
@@ -28,7 +28,16 @@ export const updateSecretApprovalRequestStatus = z.object({
|
||||
});
|
||||
|
||||
export const mergeSecretApprovalRequest = z.object({
|
||||
body: z.object({
|
||||
params: z.object({
|
||||
id: z.string().trim()
|
||||
})
|
||||
});
|
||||
|
||||
export const updateSecretApprovalRequestStatus = z.object({
|
||||
params: z.object({
|
||||
id: z.string().trim()
|
||||
}),
|
||||
body: z.object({
|
||||
status: z.enum(["open", "close"])
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user