mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 02:26:40 +00:00
Update AccessPolicyModal.tsx
This commit is contained in:
+81
-48
@@ -22,7 +22,11 @@ import {
|
|||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { policyDetails } from "@app/helpers/policies";
|
import { policyDetails } from "@app/helpers/policies";
|
||||||
import { useCreateSecretApprovalPolicy, useListWorkspaceGroups, useUpdateSecretApprovalPolicy } from "@app/hooks/api";
|
import {
|
||||||
|
useCreateSecretApprovalPolicy,
|
||||||
|
useListWorkspaceGroups,
|
||||||
|
useUpdateSecretApprovalPolicy
|
||||||
|
} from "@app/hooks/api";
|
||||||
import {
|
import {
|
||||||
useCreateAccessApprovalPolicy,
|
useCreateAccessApprovalPolicy,
|
||||||
useUpdateAccessApprovalPolicy
|
useUpdateAccessApprovalPolicy
|
||||||
@@ -46,7 +50,11 @@ const formSchema = z
|
|||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
secretPath: z.string().optional(),
|
secretPath: z.string().optional(),
|
||||||
approvals: z.number().min(1),
|
approvals: z.number().min(1),
|
||||||
approvers: z.object({type: z.nativeEnum(ApproverType), id: z.string()}).array().min(1).default([]),
|
approvers: z
|
||||||
|
.object({ type: z.nativeEnum(ApproverType), id: z.string() })
|
||||||
|
.array()
|
||||||
|
.min(1)
|
||||||
|
.default([]),
|
||||||
policyType: z.nativeEnum(PolicyType),
|
policyType: z.nativeEnum(PolicyType),
|
||||||
enforcementLevel: z.nativeEnum(EnforcementLevel)
|
enforcementLevel: z.nativeEnum(EnforcementLevel)
|
||||||
})
|
})
|
||||||
@@ -100,6 +108,8 @@ export const AccessPolicyForm = ({
|
|||||||
|
|
||||||
const policyName = policyDetails[watch("policyType")]?.name || "Policy";
|
const policyName = policyDetails[watch("policyType")]?.name || "Policy";
|
||||||
|
|
||||||
|
const approversRequired = watch("approvals") || 1;
|
||||||
|
|
||||||
const handleCreatePolicy = async (data: TFormSchema) => {
|
const handleCreatePolicy = async (data: TFormSchema) => {
|
||||||
if (!projectId) return;
|
if (!projectId) return;
|
||||||
|
|
||||||
@@ -169,12 +179,6 @@ export const AccessPolicyForm = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatEnforcementLevel = (level: EnforcementLevel) => {
|
|
||||||
if (level === EnforcementLevel.Hard) return "Hard";
|
|
||||||
if (level === EnforcementLevel.Soft) return "Soft";
|
|
||||||
return level;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onOpenChange={onToggle}>
|
<Modal isOpen={isOpen} onOpenChange={onToggle}>
|
||||||
<ModalContent title={isEditMode ? `Edit ${policyName}` : "Create Policy"}>
|
<ModalContent title={isEditMode ? `Edit ${policyName}` : "Create Policy"}>
|
||||||
@@ -257,14 +261,15 @@ export const AccessPolicyForm = ({
|
|||||||
name="secretPath"
|
name="secretPath"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Secret Path"
|
tooltipText="Secret paths support glob patterns. For example, '/**' will match all paths."
|
||||||
isError={Boolean(error)}
|
label="Secret Path"
|
||||||
errorText={error?.message}
|
isError={Boolean(error)}
|
||||||
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
<Input {...field} value={field.value || ""} />
|
<Input {...field} value={field.value || ""} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="approvals"
|
name="approvals"
|
||||||
@@ -295,9 +300,11 @@ export const AccessPolicyForm = ({
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
tooltipText="Determines the level of enforcement for required approvers of a request"
|
tooltipText="Determines the level of enforcement for required approvers of a request"
|
||||||
helperText={
|
helperText={
|
||||||
field.value === EnforcementLevel.Hard
|
<div className="ml-1">
|
||||||
? "All approvers must approve the request."
|
{field.value === EnforcementLevel.Hard
|
||||||
: "All approvers must approve the request; however, the requester can bypass approval requirements in emergencies."
|
? `Hard enforcement requires at least ${approversRequired} approver(s) to approve the request.`
|
||||||
|
: `At least ${approversRequired} approver(s) must approve the request; however, the requester can bypass approval requirements in emergencies.`}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
@@ -307,12 +314,8 @@ export const AccessPolicyForm = ({
|
|||||||
>
|
>
|
||||||
{Object.values(EnforcementLevel).map((level) => {
|
{Object.values(EnforcementLevel).map((level) => {
|
||||||
return (
|
return (
|
||||||
<SelectItem
|
<SelectItem value={level} key={`enforcement-level-${level}`}>
|
||||||
value={level}
|
<span className="capitalize">{level}</span>
|
||||||
key={`enforcement-level-${level}`}
|
|
||||||
className="text-xs"
|
|
||||||
>
|
|
||||||
{formatEnforcementLevel(level)}
|
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -320,7 +323,12 @@ export const AccessPolicyForm = ({
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<p>Approvers</p>
|
<div className="mb-2">
|
||||||
|
<p>Approvers</p>
|
||||||
|
<p className="font-inter text-xs text-mineshaft-300 opacity-90">
|
||||||
|
Select members or groups that are allowed to approve requests from this policy.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="approvers"
|
name="approvers"
|
||||||
@@ -334,7 +342,11 @@ export const AccessPolicyForm = ({
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Input
|
<Input
|
||||||
isReadOnly
|
isReadOnly
|
||||||
value={value?.filter((e) => e.type=== ApproverType.User).length ? `${value.filter((e) => e.type=== ApproverType.User).length} selected` : "None"}
|
value={
|
||||||
|
value?.filter((e) => e.type === ApproverType.User).length
|
||||||
|
? `${value.filter((e) => e.type === ApproverType.User).length} selected`
|
||||||
|
: "None"
|
||||||
|
}
|
||||||
className="text-left"
|
className="text-left"
|
||||||
/>
|
/>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
@@ -347,15 +359,22 @@ export const AccessPolicyForm = ({
|
|||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
{members.map(({ user }) => {
|
{members.map(({ user }) => {
|
||||||
const { id: userId } = user;
|
const { id: userId } = user;
|
||||||
const isChecked = value?.filter((el: {id: string, type: ApproverType}) => el.id === userId && el.type === ApproverType.User).length > 0;
|
const isChecked =
|
||||||
|
value?.filter(
|
||||||
|
(el: { id: string; type: ApproverType }) =>
|
||||||
|
el.id === userId && el.type === ApproverType.User
|
||||||
|
).length > 0;
|
||||||
return (
|
return (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={(evt) => {
|
onClick={(evt) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
onChange(
|
onChange(
|
||||||
isChecked
|
isChecked
|
||||||
? value?.filter((el: {id: string, type: ApproverType}) => el.id !== userId && el.type !== ApproverType.User)
|
? value?.filter(
|
||||||
: [...(value || []), {id:userId, type: ApproverType.User}]
|
(el: { id: string; type: ApproverType }) =>
|
||||||
|
el.id !== userId && el.type !== ApproverType.User
|
||||||
|
)
|
||||||
|
: [...(value || []), { id: userId, type: ApproverType.User }]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
key={`create-policy-members-${userId}`}
|
key={`create-policy-members-${userId}`}
|
||||||
@@ -384,7 +403,13 @@ export const AccessPolicyForm = ({
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Input
|
<Input
|
||||||
isReadOnly
|
isReadOnly
|
||||||
value={value?.filter((e) => e.type=== ApproverType.Group).length ? `${value?.filter((e) => e.type=== ApproverType.Group).length} selected` : "None"}
|
value={
|
||||||
|
value?.filter((e) => e.type === ApproverType.Group).length
|
||||||
|
? `${
|
||||||
|
value?.filter((e) => e.type === ApproverType.Group).length
|
||||||
|
} selected`
|
||||||
|
: "None"
|
||||||
|
}
|
||||||
className="text-left"
|
className="text-left"
|
||||||
/>
|
/>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
@@ -395,28 +420,36 @@ export const AccessPolicyForm = ({
|
|||||||
<DropdownMenuLabel>
|
<DropdownMenuLabel>
|
||||||
Select groups that are allowed to approve requests
|
Select groups that are allowed to approve requests
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
{groups && groups.map(({ group }) => {
|
{groups &&
|
||||||
const { id } = group;
|
groups.map(({ group }) => {
|
||||||
const isChecked = value?.filter((el: {id: string, type: ApproverType}) => el.id === id && el.type === ApproverType.Group).length > 0;
|
const { id } = group;
|
||||||
|
const isChecked =
|
||||||
|
value?.filter(
|
||||||
|
(el: { id: string; type: ApproverType }) =>
|
||||||
|
el.id === id && el.type === ApproverType.Group
|
||||||
|
).length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={(evt) => {
|
onClick={(evt) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
onChange(
|
onChange(
|
||||||
isChecked
|
isChecked
|
||||||
? value?.filter((el: {id: string, type: ApproverType}) => el.id !== id && el.type !== ApproverType.Group)
|
? value?.filter(
|
||||||
: [...(value || []), {id, type: ApproverType.Group}]
|
(el: { id: string; type: ApproverType }) =>
|
||||||
);
|
el.id !== id && el.type !== ApproverType.Group
|
||||||
}}
|
)
|
||||||
key={`create-policy-members-${id}`}
|
: [...(value || []), { id, type: ApproverType.Group }]
|
||||||
iconPos="right"
|
);
|
||||||
icon={isChecked && <FontAwesomeIcon icon={faCheckCircle} />}
|
}}
|
||||||
>
|
key={`create-policy-members-${id}`}
|
||||||
{group.name}
|
iconPos="right"
|
||||||
</DropdownMenuItem>
|
icon={isChecked && <FontAwesomeIcon icon={faCheckCircle} />}
|
||||||
);
|
>
|
||||||
})}
|
{group.name}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|||||||
Reference in New Issue
Block a user