From 882f6b22f52900eca0c153fdac305340b84ec948 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 5 Dec 2024 14:08:08 +0530 Subject: [PATCH] feat: updated frontend for review changes --- ...rojectAdditionalPrivilegeModifySection.tsx | 41 +- .../IdentityRoleDetailsSection.tsx | 9 +- .../IdentityRoleForm/IdentityRbacSection.tsx | 354 ------------------ .../IdentityRoleForm/IdentityRoleForm.tsx | 40 -- .../components/IdentityRoleForm/index.tsx | 1 - .../ProjectRoleModifySection.utils.tsx | 2 +- 6 files changed, 31 insertions(+), 416 deletions(-) delete mode 100644 frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRbacSection.tsx delete mode 100644 frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRoleForm.tsx delete mode 100644 frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/index.tsx diff --git a/frontend/src/views/Project/IdentityDetailsPage/components/IdentityProjectAdditionalPrivilegeSection/IdentityProjectAdditionalPrivilegeModifySection.tsx b/frontend/src/views/Project/IdentityDetailsPage/components/IdentityProjectAdditionalPrivilegeSection/IdentityProjectAdditionalPrivilegeModifySection.tsx index 586a1db7a..db1888a22 100644 --- a/frontend/src/views/Project/IdentityDetailsPage/components/IdentityProjectAdditionalPrivilegeSection/IdentityProjectAdditionalPrivilegeModifySection.tsx +++ b/frontend/src/views/Project/IdentityDetailsPage/components/IdentityProjectAdditionalPrivilegeSection/IdentityProjectAdditionalPrivilegeModifySection.tsx @@ -1,4 +1,5 @@ import { Controller, FormProvider, useForm } from "react-hook-form"; +import { subject } from "@casl/ability"; import { faCaretDown, faChevronLeft, @@ -28,7 +29,8 @@ import { PopoverContent, PopoverTrigger, Tag, - Tooltip} from "@app/components/v2"; + Tooltip +} from "@app/components/v2"; import { ProjectPermissionActions, ProjectPermissionSub, @@ -48,7 +50,8 @@ import { isConditionalSubjects, PROJECT_PERMISSION_OBJECT, projectRoleFormSchema, - rolePermission2Form} from "@app/views/Project/RolePage/components/RolePermissionsSection/ProjectRoleModifySection.utils"; + rolePermission2Form +} from "@app/views/Project/RolePage/components/RolePermissionsSection/ProjectRoleModifySection.utils"; import { renderConditionalComponents } from "@app/views/Project/RolePage/components/RolePermissionsSection/RolePermissionsSection"; type Props = { @@ -95,7 +98,7 @@ export const IdentityProjectAdditionalPrivilegeModifySection = ({ const { permission } = useProjectPermission(); const isIdentityEditDisabled = permission.cannot( ProjectPermissionActions.Edit, - ProjectPermissionSub.Identity + subject(ProjectPermissionSub.Identity, { identityId }) ); const form = useForm({ @@ -275,13 +278,13 @@ export const IdentityProjectAdditionalPrivilegeModifySection = ({ ].title.toLowerCase() ) ) - .map((subject) => ( + .map((permissionSubject) => ( onNewPolicy(subject as ProjectPermissionSub)} + onClick={() => onNewPolicy(permissionSubject as ProjectPermissionSub)} > - {PROJECT_PERMISSION_OBJECT[subject as ProjectPermissionSub].title} + {PROJECT_PERMISSION_OBJECT[permissionSubject as ProjectPermissionSub].title} ))} @@ -412,17 +415,19 @@ export const IdentityProjectAdditionalPrivilegeModifySection = ({
Policies
{(isCreate || !isLoading) && } - {(Object.keys(PROJECT_PERMISSION_OBJECT) as ProjectPermissionSub[]).map((subject) => ( - - {renderConditionalComponents(subject, isDisabled)} - - ))} + {(Object.keys(PROJECT_PERMISSION_OBJECT) as ProjectPermissionSub[]).map( + (permissionSubject) => ( + + {renderConditionalComponents(permissionSubject, isDisabled)} + + ) + )}
diff --git a/frontend/src/views/Project/IdentityDetailsPage/components/IdentityRoleDetailsSection/IdentityRoleDetailsSection.tsx b/frontend/src/views/Project/IdentityDetailsPage/components/IdentityRoleDetailsSection/IdentityRoleDetailsSection.tsx index 300114228..1fa98628e 100644 --- a/frontend/src/views/Project/IdentityDetailsPage/components/IdentityRoleDetailsSection/IdentityRoleDetailsSection.tsx +++ b/frontend/src/views/Project/IdentityDetailsPage/components/IdentityRoleDetailsSection/IdentityRoleDetailsSection.tsx @@ -1,3 +1,4 @@ +import { subject } from "@casl/ability"; import { faFolder, faPencil, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { format, formatDistance } from "date-fns"; @@ -93,7 +94,9 @@ export const IdentityRoleDetailsSection = ({

Project Roles

@@ -175,7 +178,9 @@ export const IdentityRoleDetailsSection = ({
diff --git a/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRbacSection.tsx b/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRbacSection.tsx deleted file mode 100644 index 47ce3f94b..000000000 --- a/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRbacSection.tsx +++ /dev/null @@ -1,354 +0,0 @@ -/* eslint-disable no-nested-ternary */ -import { Controller, useFieldArray, useForm } from "react-hook-form"; -import { faCaretDown, faClock, faPlus, faTrash } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { format, formatDistance } from "date-fns"; -import ms from "ms"; -import { twMerge } from "tailwind-merge"; -import { z } from "zod"; - -import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; -import { ProjectPermissionCan } from "@app/components/permissions"; -import { - Button, - FormControl, - IconButton, - Input, - Popover, - PopoverContent, - PopoverTrigger, - Select, - SelectItem, - Spinner, - Tag, - Tooltip -} from "@app/components/v2"; -import { - ProjectPermissionActions, - ProjectPermissionSub, - useProjectPermission, - useSubscription, - useWorkspace -} from "@app/context"; -import { useGetProjectRoles, useUpdateIdentityWorkspaceRole } from "@app/hooks/api"; -import { IdentityMembership } from "@app/hooks/api/identities/types"; -import { ProjectMembershipRole } from "@app/hooks/api/roles/types"; -import { ProjectUserMembershipTemporaryMode } from "@app/hooks/api/workspace/types"; - -const roleFormSchema = z.object({ - roles: z - .object({ - slug: z.string(), - temporaryAccess: z.discriminatedUnion("isTemporary", [ - z.object({ - isTemporary: z.literal(true), - temporaryRange: z.string().min(1), - temporaryAccessStartTime: z.string().datetime(), - temporaryAccessEndTime: z.string().datetime().nullable().optional() - }), - z.object({ - isTemporary: z.literal(false) - }) - ]) - }) - .array() -}); -type TRoleForm = z.infer; - -type Props = { - identityProjectMember: IdentityMembership; - onOpenUpgradeModal: (title: string) => void; -}; -export const IdentityRbacSection = ({ identityProjectMember, onOpenUpgradeModal }: Props) => { - const { subscription } = useSubscription(); - const { currentWorkspace } = useWorkspace(); - const workspaceId = currentWorkspace?.id || ""; - const { data: projectRoles, isLoading: isRolesLoading } = useGetProjectRoles(workspaceId); - const { permission } = useProjectPermission(); - const isMemberEditDisabled = permission.cannot( - ProjectPermissionActions.Edit, - ProjectPermissionSub.Identity - ); - - const roleForm = useForm({ - resolver: zodResolver(roleFormSchema), - values: { - roles: identityProjectMember?.roles?.map(({ customRoleSlug, role, ...dto }) => ({ - slug: customRoleSlug || role, - temporaryAccess: dto.isTemporary - ? { - isTemporary: true, - temporaryRange: dto.temporaryRange, - temporaryAccessEndTime: dto.temporaryAccessEndTime, - temporaryAccessStartTime: dto.temporaryAccessStartTime - } - : { - isTemporary: dto.isTemporary - } - })) - } - }); - const selectedRoleList = useFieldArray({ - name: "roles", - control: roleForm.control - }); - - const formRoleField = roleForm.watch("roles"); - - const updateMembershipRole = useUpdateIdentityWorkspaceRole(); - - const handleRoleUpdate = async (data: TRoleForm) => { - if (updateMembershipRole.isLoading) return; - - const sanitizedRoles = data.roles.map((el) => { - const { isTemporary } = el.temporaryAccess; - if (!isTemporary) { - return { role: el.slug, isTemporary: false as const }; - } - return { - role: el.slug, - isTemporary: true as const, - temporaryMode: ProjectUserMembershipTemporaryMode.Relative, - temporaryRange: el.temporaryAccess.temporaryRange, - temporaryAccessStartTime: el.temporaryAccess.temporaryAccessStartTime - }; - }); - - const hasCustomRoleSelected = sanitizedRoles.some( - (el) => !Object.values(ProjectMembershipRole).includes(el.role as ProjectMembershipRole) - ); - - if (hasCustomRoleSelected && subscription && !subscription?.rbac) { - onOpenUpgradeModal( - "You can assign custom roles to members if you upgrade your Infisical plan." - ); - return; - } - - try { - await updateMembershipRole.mutateAsync({ - workspaceId, - identityId: identityProjectMember.identity.id, - roles: sanitizedRoles - }); - createNotification({ text: "Successfully updated roles", type: "success" }); - roleForm.reset(undefined, { keepValues: true }); - } catch (err) { - createNotification({ text: "Failed to update role", type: "error" }); - } - }; - - if (isRolesLoading) - return ( -
- -
- ); - - return ( -
-
Roles
-

Select one of the pre-defined or custom roles.

-
-
-
- {selectedRoleList.fields.map(({ id }, index) => { - const { temporaryAccess } = formRoleField[index]; - const isTemporary = temporaryAccess?.isTemporary; - const isExpired = - temporaryAccess.isTemporary && - new Date() > new Date(temporaryAccess.temporaryAccessEndTime || ""); - - return ( -
- ( - - )} - /> - - -
- - - -
-
- -
-
- Configure timed access -
- {isExpired && Expired} - ( - } - isError={Boolean(error?.message)} - errorText={error?.message} - > - - - )} - /> -
- - {temporaryAccess.isTemporary && ( - - )} -
-
-
-
- { - if (selectedRoleList.fields.length > 1) { - selectedRoleList.remove(index); - } - }} - > - - -
- ); - })} -
-
- - {(isAllowed) => ( - - )} - - -
-
-
-
- ); -}; diff --git a/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRoleForm.tsx b/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRoleForm.tsx deleted file mode 100644 index 3640984cd..000000000 --- a/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRoleForm.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import Link from "next/link"; - -import { Alert, AlertDescription } from "@app/components/v2"; -import { useWorkspace } from "@app/context"; -import { IdentityMembership } from "@app/hooks/api/identities/types"; - -import { IdentityRbacSection } from "./IdentityRbacSection"; - -type Props = { - identityProjectMember: IdentityMembership; - onOpenUpgradeModal: (title: string) => void; -}; -export const IdentityRoleForm = ({ identityProjectMember, onOpenUpgradeModal }: Props) => { - const { currentWorkspace } = useWorkspace(); - - return ( -
- - - - - - Click here to access them now - - - - -
- ); -}; diff --git a/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/index.tsx b/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/index.tsx deleted file mode 100644 index f59675cb3..000000000 --- a/frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { IdentityRoleForm } from "./IdentityRoleForm"; diff --git a/frontend/src/views/Project/RolePage/components/RolePermissionsSection/ProjectRoleModifySection.utils.tsx b/frontend/src/views/Project/RolePage/components/RolePermissionsSection/ProjectRoleModifySection.utils.tsx index fd168d1d1..e7f4fc91a 100644 --- a/frontend/src/views/Project/RolePage/components/RolePermissionsSection/ProjectRoleModifySection.utils.tsx +++ b/frontend/src/views/Project/RolePage/components/RolePermissionsSection/ProjectRoleModifySection.utils.tsx @@ -494,7 +494,7 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = { title: "Machine Identity Management", actions: [ { label: "Read", value: "read" }, - { label: "Create", value: "create" }, + { label: "Add", value: "create" }, { label: "Modify", value: "edit" }, { label: "Remove", value: "delete" } ]