feat: more ui improvements

This commit is contained in:
=
2025-11-08 19:39:23 +05:30
parent 43c23bfa12
commit 8fe979ecc6
10 changed files with 63 additions and 11 deletions

View File

@@ -230,7 +230,7 @@ export const identityV2ServiceFactory = ({
const { scopeData } = dto;
const factory = scopeFactory[scopeData.scope];
await factory.onListIdentityGuard(dto);
const isIdentityAccessible = await factory.onListIdentityGuard(dto);
const identities = await identityDAL.listIdentities(dto.scopeData, {
search: dto.data.search,
@@ -238,7 +238,7 @@ export const identityV2ServiceFactory = ({
limit: dto.data.limit
});
return identities;
return { ...identities, docs: identities.docs.filter((el) => isIdentityAccessible({ identityId: el.id })) };
};
return {

View File

@@ -5,7 +5,7 @@ export interface TIdentityV2Factory {
onCreateIdentityGuard: (arg: TCreateIdentityV2DTO) => Promise<void>;
onUpdateIdentityGuard: (arg: TUpdateIdentityV2DTO) => Promise<void>;
onDeleteIdentityGuard: (arg: TDeleteIdentityV2DTO) => Promise<void>;
onListIdentityGuard: (arg: TListIdentityV2DTO) => Promise<void>;
onListIdentityGuard: (arg: TListIdentityV2DTO) => Promise<(arg: { identityId: string }) => boolean>;
onGetIdentityByIdGuard: (arg: TGetIdentityByIdV2DTO) => Promise<void>;
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
}

View File

@@ -65,6 +65,8 @@ export const newOrgIdentityFactory = ({ permissionService }: TOrgIdentityFactory
scope: OrganizationActionScope.Any
});
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return () => true;
};
const onGetIdentityByIdGuard: TIdentityV2Factory["onGetIdentityByIdGuard"] = async (dto) => {

View File

@@ -81,6 +81,12 @@ export const newProjectIdentityFactory = ({ permissionService }: TProjectIdentit
ProjectPermissionIdentityActions.Read,
ProjectPermissionSub.Identity
);
return (arg) =>
permission.can(
ProjectPermissionIdentityActions.Read,
subject(ProjectPermissionSub.Identity, { identityId: arg.identityId })
);
};
const onGetIdentityByIdGuard: TIdentityV2Factory["onGetIdentityByIdGuard"] = async (dto) => {

View File

@@ -6,7 +6,7 @@ export interface TMembershipIdentityScopeFactory {
onUpdateMembershipIdentityGuard: (arg: TUpdateMembershipIdentityDTO) => Promise<void>;
onDeleteMembershipIdentityGuard: (arg: TDeleteMembershipIdentityDTO) => Promise<void>;
onListMembershipIdentityGuard: (arg: TListMembershipIdentityDTO) => Promise<void>;
onListMembershipIdentityGuard: (arg: TListMembershipIdentityDTO) => Promise<(arg: { identityId: string }) => boolean>;
onGetMembershipIdentityByIdentityIdGuard: (arg: TGetMembershipIdentityByIdentityIdDTO) => Promise<void>;
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
getScopeDatabaseFields: (scope: AccessScopeData) => {

View File

@@ -180,6 +180,8 @@ export const newOrgMembershipIdentityFactory = ({
scope: OrganizationActionScope.Any
});
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return () => true;
};
const onGetMembershipIdentityByIdentityIdGuard: TMembershipIdentityScopeFactory["onGetMembershipIdentityByIdentityIdGuard"] =

View File

@@ -194,6 +194,12 @@ export const newProjectMembershipIdentityFactory = ({
ProjectPermissionIdentityActions.Read,
ProjectPermissionSub.Identity
);
return (arg) =>
permission.can(
ProjectPermissionIdentityActions.Read,
subject(ProjectPermissionSub.Identity, { identityId: arg.identityId })
);
};
const onGetMembershipIdentityByIdentityIdGuard: TMembershipIdentityScopeFactory["onGetMembershipIdentityByIdentityIdGuard"] =

View File

@@ -423,7 +423,9 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
isDisabled={!isAllowed}
icon={<FontAwesomeIcon icon={faTrash} />}
>
Delete Identity
{orgId !== currentOrg.id
? "Remove From Sub-organization"
: "Delete Identity"}
</DropdownMenuItem>
)}
</OrgPermissionCan>

View File

@@ -7,9 +7,14 @@ import { Link, useNavigate, useParams } from "@tanstack/react-router";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import { DeleteActionModal, Modal, ModalContent, PageHeader } from "@app/components/v2";
import { Button, DeleteActionModal, Modal, ModalContent, PageHeader } from "@app/components/v2";
import { ROUTE_PATHS } from "@app/const/routes";
import { OrgPermissionIdentityActions, OrgPermissionSubjects, useOrganization } from "@app/context";
import {
OrgPermissionActions,
OrgPermissionIdentityActions,
OrgPermissionSubjects,
useOrganization
} from "@app/context";
import { useDeleteOrgIdentity, useGetOrgIdentityMembershipById } from "@app/hooks/api";
import { usePopUp } from "@app/hooks/usePopUp";
import { ViewIdentityAuthModal } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal";
@@ -32,7 +37,7 @@ const Page = () => {
const { currentOrg, isSubOrganization } = useOrganization();
const orgId = currentOrg?.id || "";
const { data } = useGetOrgIdentityMembershipById(identityId);
const { mutateAsync: deleteIdentity } = useDeleteOrgIdentity();
const { mutateAsync: deleteIdentity, isPending: isDeletingIdentity } = useDeleteOrgIdentity();
const isAuthHidden = orgId !== data?.identity?.orgId;
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
@@ -81,7 +86,36 @@ const Page = () => {
scope={isSubOrganization ? "namespace" : "org"}
description={`${isSubOrganization ? "Sub-" : ""}Organization Identity`}
title={data.identity.name}
/>
>
<div className="flex items-center gap-2">
{isSubOrganization && data.identity.orgId !== currentOrg.id && (
<OrgPermissionCan
I={OrgPermissionActions.Delete}
a={OrgPermissionSubjects.Identity}
renderTooltip
allowedLabel="Remove from sub-organization"
>
{(isAllowed) => (
<Button
colorSchema="danger"
variant="outline_bg"
size="xs"
isDisabled={!isAllowed}
isLoading={isDeletingIdentity}
onClick={() =>
handlePopUpOpen("deleteIdentity", {
identityId: data.identity.id,
name: data.identity.name
})
}
>
Unlink Identity
</Button>
)}
</OrgPermissionCan>
)}
</div>
</PageHeader>
<div className="flex">
<div className="mr-4 w-96">
<IdentityDetailsSection

View File

@@ -86,7 +86,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
}}
disabled={!isAllowed}
>
Edit Identity
{isOrgIdentity ? "Edit Identity" : "Edit Identity Role"}
</DropdownMenuItem>
)}
</OrgPermissionCan>
@@ -110,7 +110,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
icon={<FontAwesomeIcon icon={faTrash} />}
disabled={!isAllowed}
>
Delete Identity
{!isOrgIdentity ? "Unlink Identity" : "Delete Identity"}
</DropdownMenuItem>
)}
</OrgPermissionCan>