mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 09:28:36 +00:00
Merge pull request #3697 from Infisical/approvals-redesign
revamp UI for access requests
This commit is contained in:
+108
-32
@@ -1,11 +1,15 @@
|
||||
/* eslint-disable jsx-a11y/label-has-associated-control */
|
||||
import { useMemo } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { faEye, faTrashCan } from "@fortawesome/free-regular-svg-icons";
|
||||
import {
|
||||
faArrowRotateLeft,
|
||||
faCaretDown,
|
||||
faCheck,
|
||||
faClock,
|
||||
faLockOpen,
|
||||
faPencil,
|
||||
faPlus,
|
||||
faTrash
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@@ -205,7 +209,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
if (!data.secretPath) {
|
||||
createNotification({
|
||||
type: "error",
|
||||
text: "Please select a secret path",
|
||||
text: "Please select a secret path...",
|
||||
title: "Error"
|
||||
});
|
||||
return;
|
||||
@@ -264,18 +268,18 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mt-4 w-full">
|
||||
<div className="w-full">
|
||||
<form onSubmit={privilegeForm.handleSubmit(handleSubmit)}>
|
||||
<div className={twMerge("flex items-start gap-4", !privilege && "flex-wrap")}>
|
||||
<div className={twMerge("flex items-start", !privilege && "flex-col")}>
|
||||
<Controller
|
||||
control={privilegeForm.control}
|
||||
name="environmentSlug"
|
||||
render={({ field: { onChange, ...field } }) => (
|
||||
<FormControl label="Environment">
|
||||
<FormControl label="Environment" className="w-full">
|
||||
<Select
|
||||
{...field}
|
||||
isDisabled={isMemberEditDisabled}
|
||||
className="bg-mineshaft-600 hover:bg-mineshaft-500"
|
||||
className="w-full bg-mineshaft-900 hover:bg-mineshaft-800"
|
||||
onValueChange={(e) => onChange(e)}
|
||||
>
|
||||
{currentWorkspace?.environments?.map(({ slug, id, name }) => (
|
||||
@@ -297,12 +301,13 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
isDisabled={!!selectablePaths.length}
|
||||
content="The selected environment doesn't have any policies."
|
||||
>
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<FormControl label="Secret Path">
|
||||
<Select
|
||||
{...field}
|
||||
isDisabled={isMemberEditDisabled || !selectablePaths.length}
|
||||
className="w-48"
|
||||
className="w-full hover:bg-mineshaft-800"
|
||||
placeholder="Select a secret path"
|
||||
onValueChange={(e) => field.onChange(e)}
|
||||
>
|
||||
{selectablePaths.map((path) => (
|
||||
@@ -328,85 +333,151 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-grow justify-between">
|
||||
<FormControl label="Permissions" className="w-full">
|
||||
<div className="flex w-full flex-col justify-between">
|
||||
<div className="flex w-full flex-row gap-2">
|
||||
<Controller
|
||||
control={privilegeForm.control}
|
||||
name="read"
|
||||
render={({ field }) => (
|
||||
<div className="flex flex-col items-center">
|
||||
<FormLabel label="View" className="mb-4" />
|
||||
<label
|
||||
className={`group my-1 flex w-full cursor-pointer flex-row items-center justify-start gap-2 rounded-md border border-mineshaft-600 bg-mineshaft-900 p-3 duration-100 hover:border-primary/30 hover:bg-primary/10 ${field.value ? "border-primary/50 bg-primary/10 hover:border-primary/50" : ""}`}
|
||||
htmlFor="secret-read"
|
||||
>
|
||||
<Checkbox
|
||||
isDisabled={isMemberEditDisabled}
|
||||
id="secret-read"
|
||||
className="h-5 w-5"
|
||||
className={`mx-2 h-5 w-5 ${field.value ? "bg-primary hover:bg-primary/80" : ""}`}
|
||||
isChecked={field.value}
|
||||
onCheckedChange={(isChecked) => field.onChange(isChecked)}
|
||||
/>
|
||||
<div className="ml-1 flex flex-col text-mineshaft-300">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faEye}
|
||||
className={`text-sm ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
<FormLabel
|
||||
label="View"
|
||||
className={`ml-0.5 mt-0 text-mineshaft-300 ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-mineshaft-400">Read secret values</p>
|
||||
</div>
|
||||
</label>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={privilegeForm.control}
|
||||
name="create"
|
||||
render={({ field }) => (
|
||||
<div className="flex flex-col items-center">
|
||||
<FormLabel label="Create" className="mb-4" />
|
||||
<label
|
||||
className={`group my-1 flex w-full cursor-pointer flex-row items-center justify-start gap-2 rounded-md border border-mineshaft-600 bg-mineshaft-900 p-3 duration-100 hover:border-primary/30 hover:bg-primary/10 ${field.value ? "border-primary/50 bg-primary/10 hover:border-primary/50" : ""}`}
|
||||
htmlFor="secret-change"
|
||||
>
|
||||
<Checkbox
|
||||
isDisabled={isMemberEditDisabled}
|
||||
id="secret-create"
|
||||
className="h-5 w-5"
|
||||
id="secret-change"
|
||||
className={`mx-2 h-5 w-5 ${field.value ? "bg-primary hover:bg-primary/80" : ""}`}
|
||||
isChecked={field.value}
|
||||
onCheckedChange={(isChecked) => field.onChange(isChecked)}
|
||||
/>
|
||||
<div className="ml-1 flex flex-col text-mineshaft-300">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
className={`text-sm ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
<FormLabel
|
||||
label="Create"
|
||||
className={`ml-0.5 mt-0 text-mineshaft-300 ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-mineshaft-400">Create new secrets</p>
|
||||
</div>
|
||||
</label>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full flex-row gap-2">
|
||||
<Controller
|
||||
control={privilegeForm.control}
|
||||
name="edit"
|
||||
render={({ field }) => (
|
||||
<div className="flex flex-col items-center">
|
||||
<FormLabel label="Modify" className="mb-4" />
|
||||
<label
|
||||
className={`group my-1 flex w-full cursor-pointer flex-row items-center justify-start gap-2 rounded-md border border-mineshaft-600 bg-mineshaft-900 p-3 duration-100 hover:border-primary/30 hover:bg-primary/10 ${field.value ? "border-primary/50 bg-primary/10 hover:border-primary/50" : ""}`}
|
||||
htmlFor="secret-modify"
|
||||
>
|
||||
<Checkbox
|
||||
isDisabled={isMemberEditDisabled}
|
||||
id="secret-modify"
|
||||
className="h-5 w-5"
|
||||
className={`mx-2 h-5 w-5 ${field.value ? "bg-primary hover:bg-primary/80" : ""}`}
|
||||
isChecked={field.value}
|
||||
onCheckedChange={(isChecked) => field.onChange(isChecked)}
|
||||
/>
|
||||
<div className="ml-1 flex flex-col text-mineshaft-300">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faPencil}
|
||||
className={`text-sm ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
<FormLabel
|
||||
label="Modify"
|
||||
className={`ml-0.5 mt-0 text-mineshaft-300 ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-mineshaft-400">Update existing secrets</p>
|
||||
</div>
|
||||
</label>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={privilegeForm.control}
|
||||
name="delete"
|
||||
render={({ field }) => (
|
||||
<div className="flex flex-col items-center">
|
||||
<FormLabel label="Delete" className="mb-4" />
|
||||
<label
|
||||
className={`group my-1 flex w-full cursor-pointer flex-row items-center justify-start gap-2 rounded-md border border-mineshaft-600 bg-mineshaft-900 p-3 duration-100 hover:border-primary/30 hover:bg-primary/10 ${field.value ? "border-primary/50 bg-primary/10 hover:border-primary/50" : ""}`}
|
||||
htmlFor="secret-delete"
|
||||
>
|
||||
<Checkbox
|
||||
isDisabled={isMemberEditDisabled}
|
||||
id="secret-delete"
|
||||
className="h-5 w-5"
|
||||
className={`mx-2 h-5 w-5 ${field.value ? "bg-primary hover:bg-primary/80" : ""}`}
|
||||
isChecked={field.value}
|
||||
onCheckedChange={(isChecked) => field.onChange(isChecked)}
|
||||
/>
|
||||
<div className="ml-1 flex flex-col text-mineshaft-300">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
<FontAwesomeIcon
|
||||
icon={faTrashCan}
|
||||
className={`text-sm ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
<FormLabel
|
||||
label="Delete"
|
||||
className={`ml-0.5 mt-0 text-mineshaft-300 ${field.value ? "text-primary-200" : ""}`}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-mineshaft-400">Delete existing secrets</p>
|
||||
</div>
|
||||
</label>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6 flex items-center space-x-2">
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormControl label="Time Period" className="w-full">
|
||||
<div className="mt-1 flex w-full items-center space-x-2">
|
||||
<Popover>
|
||||
<PopoverTrigger disabled={isMemberEditDisabled}>
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<Tooltip content={getAccessLabel(true)}>
|
||||
<Button
|
||||
variant="outline_bg"
|
||||
leftIcon={isTemporary ? <FontAwesomeIcon icon={faClock} /> : undefined}
|
||||
rightIcon={<FontAwesomeIcon icon={faCaretDown} className="ml-2" />}
|
||||
rightIcon={<FontAwesomeIcon icon={faCaretDown} className="ml-4" />}
|
||||
isDisabled={isMemberEditDisabled}
|
||||
className={twMerge(
|
||||
"border-none bg-mineshaft-600 py-2.5 text-xs capitalize hover:bg-mineshaft-500",
|
||||
isTemporary && "text-primary",
|
||||
"w-full border-mineshaft-600 bg-mineshaft-900 py-2.5 text-sm capitalize text-mineshaft-300 hover:border-mineshaft-600 hover:bg-mineshaft-800",
|
||||
isExpired && "text-red-600"
|
||||
)}
|
||||
>
|
||||
@@ -416,16 +487,14 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
arrowClassName="fill-gray-600"
|
||||
arrowClassName="fill-mineshaft-600"
|
||||
side="right"
|
||||
sideOffset={12}
|
||||
hideCloseBtn
|
||||
className="border border-gray-600 pt-4"
|
||||
className="border border-mineshaft-600 bg-mineshaft-800 pt-4"
|
||||
>
|
||||
<div className="flex flex-col space-y-4">
|
||||
<div className="border-b border-b-gray-700 pb-2 text-sm text-mineshaft-300">
|
||||
Configure timed access
|
||||
</div>
|
||||
<div className="text-sm text-mineshaft-300">Configure timed access</div>
|
||||
{isExpired && <Tag colorSchema="red">Expired</Tag>}
|
||||
<Controller
|
||||
control={privilegeForm.control}
|
||||
@@ -544,6 +613,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
<div />
|
||||
)}
|
||||
</div>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className="mb-4 flex w-full">
|
||||
<Controller
|
||||
@@ -552,7 +622,13 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
render={({ field }) => (
|
||||
<div className="w-full">
|
||||
<FormLabel label="Note" className="mb-2" />
|
||||
<Input {...field} isDisabled={isMemberEditDisabled} maxLength={255} />
|
||||
<Input
|
||||
{...field}
|
||||
isDisabled={isMemberEditDisabled}
|
||||
maxLength={255}
|
||||
placeholder="Add the reason for this access request..."
|
||||
className="text-mineshaft-300"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
+2
-2
@@ -158,8 +158,8 @@ export const RolePermissionsSection = ({ roleSlug, isDisabled }: Props) => {
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
className={twMerge(
|
||||
"mr-4 h-10 border border-primary",
|
||||
isDirty && "bg-primary text-black"
|
||||
"mr-4 h-10 border",
|
||||
isDirty && "bg-primary text-black hover:bg-primary hover:opacity-80"
|
||||
)}
|
||||
isDisabled={isSubmitting || !isDirty}
|
||||
isLoading={isSubmitting}
|
||||
|
||||
+2
-2
@@ -14,9 +14,9 @@ export const RequestAccessModal = ({
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||
<ModalContent
|
||||
className="max-w-4xl"
|
||||
className="max-w-xl"
|
||||
title="Request Access"
|
||||
subTitle="Your role has limited permissions, please contact your administrator to gain access"
|
||||
subTitle="Request access to any secrets and resources based on the predefined policies."
|
||||
>
|
||||
<SpecificPrivilegeSecretForm onClose={() => onOpenChange(false)} policies={policies} />
|
||||
</ModalContent>
|
||||
|
||||
Reference in New Issue
Block a user