mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 11:27:47 +00:00
feat(frontend): send bypass reason on bypassed merges
This commit is contained in:
@@ -46,8 +46,10 @@ export const usePerformSecretApprovalRequestMerge = () => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation<{}, {}, TPerformSecretApprovalRequestMerge>({
|
return useMutation<{}, {}, TPerformSecretApprovalRequestMerge>({
|
||||||
mutationFn: async ({ id }) => {
|
mutationFn: async ({ id, bypassReason }) => {
|
||||||
const { data } = await apiRequest.post(`/api/v1/secret-approval-requests/${id}/merge`);
|
const { data } = await apiRequest.post(`/api/v1/secret-approval-requests/${id}/merge`, {
|
||||||
|
bypassReason
|
||||||
|
});
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
onSuccess: (_, { id, workspaceId }) => {
|
onSuccess: (_, { id, workspaceId }) => {
|
||||||
|
|||||||
@@ -133,4 +133,5 @@ export type TUpdateSecretApprovalRequestStatusDTO = {
|
|||||||
export type TPerformSecretApprovalRequestMerge = {
|
export type TPerformSecretApprovalRequestMerge = {
|
||||||
id: string;
|
id: string;
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
bypassReason?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
+30
-7
@@ -6,12 +6,13 @@ import {
|
|||||||
faLockOpen,
|
faLockOpen,
|
||||||
faSquareCheck,
|
faSquareCheck,
|
||||||
faSquareXmark,
|
faSquareXmark,
|
||||||
|
faTriangleExclamation,
|
||||||
faUserLock} from "@fortawesome/free-solid-svg-icons";
|
faUserLock} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, Checkbox } from "@app/components/v2";
|
import { Button, Checkbox, FormControl, Input } from "@app/components/v2";
|
||||||
import {
|
import {
|
||||||
usePerformSecretApprovalRequestMerge,
|
usePerformSecretApprovalRequestMerge,
|
||||||
useUpdateSecretApprovalRequestStatus
|
useUpdateSecretApprovalRequestStatus
|
||||||
@@ -48,12 +49,19 @@ export const SecretApprovalRequestAction = ({
|
|||||||
useUpdateSecretApprovalRequestStatus();
|
useUpdateSecretApprovalRequestStatus();
|
||||||
|
|
||||||
const [byPassApproval, setByPassApproval] = useState(false);
|
const [byPassApproval, setByPassApproval] = useState(false);
|
||||||
|
const [bypassReason, setBypassReason] = useState("");
|
||||||
|
|
||||||
|
const isValidBypassReason = (value: string) => {
|
||||||
|
const trimmedValue = value.trim();
|
||||||
|
return trimmedValue.length >= 10;
|
||||||
|
};
|
||||||
|
|
||||||
const handleSecretApprovalRequestMerge = async () => {
|
const handleSecretApprovalRequestMerge = async () => {
|
||||||
try {
|
try {
|
||||||
await performSecretApprovalMerge({
|
await performSecretApprovalMerge({
|
||||||
id: approvalRequestId,
|
id: approvalRequestId,
|
||||||
workspaceId
|
workspaceId,
|
||||||
|
bypassReason: byPassApproval ? bypassReason : undefined
|
||||||
});
|
});
|
||||||
createNotification({
|
createNotification({
|
||||||
type: "success",
|
type: "success",
|
||||||
@@ -92,7 +100,7 @@ export const SecretApprovalRequestAction = ({
|
|||||||
|
|
||||||
if (!hasMerged && status === "open") {
|
if (!hasMerged && status === "open") {
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full items-center justify-between">
|
<div className="flex w-full items-start justify-between transition-all">
|
||||||
<div className="flex items-start space-x-4">
|
<div className="flex items-start space-x-4">
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={isMergable ? faSquareCheck : faSquareXmark}
|
icon={isMergable ? faSquareCheck : faSquareXmark}
|
||||||
@@ -105,18 +113,33 @@ export const SecretApprovalRequestAction = ({
|
|||||||
{Boolean(statusChangeByEmail) && `. Reopened by ${statusChangeByEmail}`}
|
{Boolean(statusChangeByEmail) && `. Reopened by ${statusChangeByEmail}`}
|
||||||
</span>
|
</span>
|
||||||
{!canApprove && isSoftEnforcement && (
|
{!canApprove && isSoftEnforcement && (
|
||||||
<div className="mt-1">
|
<div className="mt-2 flex flex-col space-y-2">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
onCheckedChange={(checked) => setByPassApproval(checked === true)}
|
onCheckedChange={(checked) => setByPassApproval(checked === true)}
|
||||||
isChecked={byPassApproval}
|
isChecked={byPassApproval}
|
||||||
id="byPassApproval"
|
id="byPassApproval"
|
||||||
checkIndicatorBg="text-white"
|
checkIndicatorBg="text-white"
|
||||||
className={byPassApproval ? "bg-red hover:bg-red-600 border-red" : ""}
|
className={twMerge("mr-2", byPassApproval ? "bg-red hover:bg-red-600 border-red" : "")}
|
||||||
>
|
>
|
||||||
<span className="text-red text-sm">
|
<span className="text-red text-xs">
|
||||||
Merge without waiting for approval (bypass secret change policy)
|
Merge without waiting for approval (bypass secret change policy)
|
||||||
</span>
|
</span>
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
{byPassApproval && (
|
||||||
|
<FormControl
|
||||||
|
label="Reason for Bypass"
|
||||||
|
className="mt-2"
|
||||||
|
isRequired
|
||||||
|
tooltipText="Enter a reason for bypassing the secret change policy"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
value={bypassReason}
|
||||||
|
onChange={(e) => setBypassReason(e.target.value)}
|
||||||
|
placeholder="Enter reason for bypass (min 10 chars)"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faTriangleExclamation} />}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
@@ -137,7 +160,7 @@ export const SecretApprovalRequestAction = ({
|
|||||||
leftIcon={<FontAwesomeIcon icon={!canApprove ? faLandMineOn : faCheck} />}
|
leftIcon={<FontAwesomeIcon icon={!canApprove ? faLandMineOn : faCheck} />}
|
||||||
isDisabled={
|
isDisabled={
|
||||||
(!isMergable && canApprove)
|
(!isMergable && canApprove)
|
||||||
|| (!canApprove && isSoftEnforcement && !byPassApproval)
|
|| (!canApprove && isSoftEnforcement && (!byPassApproval || !isValidBypassReason(bypassReason)))
|
||||||
}
|
}
|
||||||
isLoading={isMerging}
|
isLoading={isMerging}
|
||||||
onClick={handleSecretApprovalRequestMerge}
|
onClick={handleSecretApprovalRequestMerge}
|
||||||
|
|||||||
Reference in New Issue
Block a user