mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: more ui improvements
This commit is contained in:
@@ -230,7 +230,7 @@ export const identityV2ServiceFactory = ({
|
|||||||
const { scopeData } = dto;
|
const { scopeData } = dto;
|
||||||
const factory = scopeFactory[scopeData.scope];
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
|
||||||
await factory.onListIdentityGuard(dto);
|
const isIdentityAccessible = await factory.onListIdentityGuard(dto);
|
||||||
|
|
||||||
const identities = await identityDAL.listIdentities(dto.scopeData, {
|
const identities = await identityDAL.listIdentities(dto.scopeData, {
|
||||||
search: dto.data.search,
|
search: dto.data.search,
|
||||||
@@ -238,7 +238,7 @@ export const identityV2ServiceFactory = ({
|
|||||||
limit: dto.data.limit
|
limit: dto.data.limit
|
||||||
});
|
});
|
||||||
|
|
||||||
return identities;
|
return { ...identities, docs: identities.docs.filter((el) => isIdentityAccessible({ identityId: el.id })) };
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export interface TIdentityV2Factory {
|
|||||||
onCreateIdentityGuard: (arg: TCreateIdentityV2DTO) => Promise<void>;
|
onCreateIdentityGuard: (arg: TCreateIdentityV2DTO) => Promise<void>;
|
||||||
onUpdateIdentityGuard: (arg: TUpdateIdentityV2DTO) => Promise<void>;
|
onUpdateIdentityGuard: (arg: TUpdateIdentityV2DTO) => Promise<void>;
|
||||||
onDeleteIdentityGuard: (arg: TDeleteIdentityV2DTO) => 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>;
|
onGetIdentityByIdGuard: (arg: TGetIdentityByIdV2DTO) => Promise<void>;
|
||||||
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
|
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ export const newOrgIdentityFactory = ({ permissionService }: TOrgIdentityFactory
|
|||||||
scope: OrganizationActionScope.Any
|
scope: OrganizationActionScope.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
|
||||||
|
|
||||||
|
return () => true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onGetIdentityByIdGuard: TIdentityV2Factory["onGetIdentityByIdGuard"] = async (dto) => {
|
const onGetIdentityByIdGuard: TIdentityV2Factory["onGetIdentityByIdGuard"] = async (dto) => {
|
||||||
|
|||||||
@@ -81,6 +81,12 @@ export const newProjectIdentityFactory = ({ permissionService }: TProjectIdentit
|
|||||||
ProjectPermissionIdentityActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
ProjectPermissionSub.Identity
|
ProjectPermissionSub.Identity
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return (arg) =>
|
||||||
|
permission.can(
|
||||||
|
ProjectPermissionIdentityActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Identity, { identityId: arg.identityId })
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onGetIdentityByIdGuard: TIdentityV2Factory["onGetIdentityByIdGuard"] = async (dto) => {
|
const onGetIdentityByIdGuard: TIdentityV2Factory["onGetIdentityByIdGuard"] = async (dto) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export interface TMembershipIdentityScopeFactory {
|
|||||||
|
|
||||||
onUpdateMembershipIdentityGuard: (arg: TUpdateMembershipIdentityDTO) => Promise<void>;
|
onUpdateMembershipIdentityGuard: (arg: TUpdateMembershipIdentityDTO) => Promise<void>;
|
||||||
onDeleteMembershipIdentityGuard: (arg: TDeleteMembershipIdentityDTO) => 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>;
|
onGetMembershipIdentityByIdentityIdGuard: (arg: TGetMembershipIdentityByIdentityIdDTO) => Promise<void>;
|
||||||
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
|
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
|
||||||
getScopeDatabaseFields: (scope: AccessScopeData) => {
|
getScopeDatabaseFields: (scope: AccessScopeData) => {
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ export const newOrgMembershipIdentityFactory = ({
|
|||||||
scope: OrganizationActionScope.Any
|
scope: OrganizationActionScope.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
|
||||||
|
|
||||||
|
return () => true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onGetMembershipIdentityByIdentityIdGuard: TMembershipIdentityScopeFactory["onGetMembershipIdentityByIdentityIdGuard"] =
|
const onGetMembershipIdentityByIdentityIdGuard: TMembershipIdentityScopeFactory["onGetMembershipIdentityByIdentityIdGuard"] =
|
||||||
|
|||||||
@@ -194,6 +194,12 @@ export const newProjectMembershipIdentityFactory = ({
|
|||||||
ProjectPermissionIdentityActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
ProjectPermissionSub.Identity
|
ProjectPermissionSub.Identity
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return (arg) =>
|
||||||
|
permission.can(
|
||||||
|
ProjectPermissionIdentityActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Identity, { identityId: arg.identityId })
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onGetMembershipIdentityByIdentityIdGuard: TMembershipIdentityScopeFactory["onGetMembershipIdentityByIdentityIdGuard"] =
|
const onGetMembershipIdentityByIdentityIdGuard: TMembershipIdentityScopeFactory["onGetMembershipIdentityByIdentityIdGuard"] =
|
||||||
|
|||||||
@@ -423,7 +423,9 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||||
>
|
>
|
||||||
Delete Identity
|
{orgId !== currentOrg.id
|
||||||
|
? "Remove From Sub-organization"
|
||||||
|
: "Delete Identity"}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
|
|||||||
@@ -7,9 +7,14 @@ import { Link, useNavigate, useParams } from "@tanstack/react-router";
|
|||||||
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
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 { 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 { useDeleteOrgIdentity, useGetOrgIdentityMembershipById } from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
import { ViewIdentityAuthModal } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal";
|
import { ViewIdentityAuthModal } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal";
|
||||||
@@ -32,7 +37,7 @@ const Page = () => {
|
|||||||
const { currentOrg, isSubOrganization } = useOrganization();
|
const { currentOrg, isSubOrganization } = useOrganization();
|
||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
const { data } = useGetOrgIdentityMembershipById(identityId);
|
const { data } = useGetOrgIdentityMembershipById(identityId);
|
||||||
const { mutateAsync: deleteIdentity } = useDeleteOrgIdentity();
|
const { mutateAsync: deleteIdentity, isPending: isDeletingIdentity } = useDeleteOrgIdentity();
|
||||||
const isAuthHidden = orgId !== data?.identity?.orgId;
|
const isAuthHidden = orgId !== data?.identity?.orgId;
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||||
@@ -81,7 +86,36 @@ const Page = () => {
|
|||||||
scope={isSubOrganization ? "namespace" : "org"}
|
scope={isSubOrganization ? "namespace" : "org"}
|
||||||
description={`${isSubOrganization ? "Sub-" : ""}Organization Identity`}
|
description={`${isSubOrganization ? "Sub-" : ""}Organization Identity`}
|
||||||
title={data.identity.name}
|
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="flex">
|
||||||
<div className="mr-4 w-96">
|
<div className="mr-4 w-96">
|
||||||
<IdentityDetailsSection
|
<IdentityDetailsSection
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
|
|||||||
}}
|
}}
|
||||||
disabled={!isAllowed}
|
disabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Edit Identity
|
{isOrgIdentity ? "Edit Identity" : "Edit Identity Role"}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
@@ -110,7 +110,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
|
|||||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||||
disabled={!isAllowed}
|
disabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Delete Identity
|
{!isOrgIdentity ? "Unlink Identity" : "Delete Identity"}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
|
|||||||
Reference in New Issue
Block a user