Update AccessPolicyModal.tsx

This commit is contained in:
Daniel Hougaard
2024-11-25 15:55:44 +04:00
parent 71c9c0fa1e
commit 464a3ccd53
@@ -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>