mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 06:26:27 +00:00
improvements: address feedback
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
/* eslint-disable react/prop-types */
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||||
|
import { ChevronDownIcon } from "lucide-react";
|
||||||
|
|
||||||
|
import { cn } from "../../utils";
|
||||||
|
|
||||||
|
function UnstableAccordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<AccordionPrimitive.Root
|
||||||
|
data-slot="accordion"
|
||||||
|
className="border border-border bg-container"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function UnstableAccordionItem({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
||||||
|
return (
|
||||||
|
<AccordionPrimitive.Item
|
||||||
|
data-slot="accordion-item"
|
||||||
|
className={cn("border-b border-border last:border-b-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function UnstableAccordionTrigger({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
||||||
|
return (
|
||||||
|
<AccordionPrimitive.Header className="flex">
|
||||||
|
<AccordionPrimitive.Trigger
|
||||||
|
data-slot="accordion-trigger"
|
||||||
|
className={cn(
|
||||||
|
"flex min-h-12 flex-1 items-center gap-4 border-border bg-container px-4 text-left text-sm font-medium",
|
||||||
|
"transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
||||||
|
"disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
|
||||||
|
"cursor-pointer hover:bg-foreground/5",
|
||||||
|
"data-[state=open]:bg-foreground/5",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronDownIcon className="pointer-events-none size-4 shrink-0 translate-y-0 text-label transition-transform duration-200" />
|
||||||
|
{children}
|
||||||
|
</AccordionPrimitive.Trigger>
|
||||||
|
</AccordionPrimitive.Header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function UnstableAccordionContent({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<AccordionPrimitive.Content
|
||||||
|
data-slot="accordion-content"
|
||||||
|
className="overflow-hidden text-sm transition data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div className={cn("p-6", className)}>{children}</div>
|
||||||
|
</AccordionPrimitive.Content>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
UnstableAccordion,
|
||||||
|
UnstableAccordionContent,
|
||||||
|
UnstableAccordionItem,
|
||||||
|
UnstableAccordionTrigger
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./Accordion";
|
||||||
@@ -25,8 +25,8 @@ const badgeVariants = cva(
|
|||||||
},
|
},
|
||||||
variant: {
|
variant: {
|
||||||
ghost: "text-foreground border-none",
|
ghost: "text-foreground border-none",
|
||||||
default: "bg-foreground text-background [a&,button&]:hover:bg-primary/35",
|
default: "bg-label text-background border-label [a&,button&]:hover:bg-primary/35",
|
||||||
outline: "text-foreground border-foreground border",
|
outline: "text-label border-label border",
|
||||||
neutral: "bg-neutral/15 border-neutral/10 text-neutral [a&,button&]:hover:bg-neutral/35",
|
neutral: "bg-neutral/15 border-neutral/10 text-neutral [a&,button&]:hover:bg-neutral/35",
|
||||||
success: "bg-success/15 border-success/10 text-success [a&,button&]:hover:bg-success/35",
|
success: "bg-success/15 border-success/10 text-success [a&,button&]:hover:bg-success/35",
|
||||||
info: "bg-info/15 border-info/10 border text-info [a&,button&]:hover:bg-info/35",
|
info: "bg-info/15 border-info/10 border text-info [a&,button&]:hover:bg-info/35",
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ function UnstableCard({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card"
|
data-slot="card"
|
||||||
className={cn("flex h-fit flex-col gap-6 rounded-[6px] text-foreground shadow-sm", className)}
|
className={cn(
|
||||||
|
"flex h-fit flex-col gap-6 rounded-md border border-border bg-card p-5 text-foreground shadow-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -19,7 +22,8 @@ function UnstableCardHeader({ className, ...props }: React.ComponentProps<"div">
|
|||||||
<div
|
<div
|
||||||
data-slot="card-header"
|
data-slot="card-header"
|
||||||
className={cn(
|
className={cn(
|
||||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-center gap-1 border-mineshaft-400/60 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-center gap-1",
|
||||||
|
"border-border has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -31,10 +35,7 @@ function UnstableCardTitle({ className, ...props }: React.ComponentProps<"div">)
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-title"
|
data-slot="card-title"
|
||||||
className={cn(
|
className={cn("text-lg leading-none font-semibold", className)}
|
||||||
"flex items-center gap-1.5 leading-none font-semibold [&>svg]:inline-block [&>svg]:size-[18px]",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -42,14 +43,7 @@ function UnstableCardTitle({ className, ...props }: React.ComponentProps<"div">)
|
|||||||
|
|
||||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div data-slot="card-description" className={cn("text-sm text-accent", className)} {...props} />
|
||||||
data-slot="card-description"
|
|
||||||
className={cn(
|
|
||||||
"flex items-center gap-1 text-sm text-accent [&>svg]:inline-block [&>svg]:size-[12px]",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ function UnstableDropdownMenuContent({
|
|||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin)",
|
"max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin)",
|
||||||
"z-50 overflow-x-hidden overflow-y-auto rounded-[6px] border border-border/50 bg-popover p-1 text-xs text-foreground shadow-md",
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
||||||
|
"z-50 overflow-x-hidden overflow-y-auto rounded-[6px] border border-border bg-popover p-1 text-xs text-foreground shadow-md",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function UnstableEmptyDescription({ className, ...props }: React.ComponentProps<
|
|||||||
<div
|
<div
|
||||||
data-slot="empty-description"
|
data-slot="empty-description"
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-xs/relaxed text-muted [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
|
"text-xs/relaxed text-muted [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-project",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ const iconButtonVariants = cva(
|
|||||||
"border-danger/75 bg-danger/40 text-foreground hover:bg-danger/50 hover:border-danger"
|
"border-danger/75 bg-danger/40 text-foreground hover:bg-danger/50 hover:border-danger"
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
xs: "h-6 w-6 [&>svg]:size-4 rounded-[5px] [&>svg]:stroke-[1.75]",
|
xs: "h-7 w-7 [&>svg]:size-3.5 [&>svg]:stroke-[1.75]",
|
||||||
sm: "h-8 w-8 [&>svg]:size-5 [&>svg]:stroke-[1.5]",
|
sm: "h-8 w-8 [&>svg]:size-4 [&>svg]:stroke-[1.5]",
|
||||||
md: "h-9 w-9 [&>svg]:size-6 [&>svg]:stroke-[1.5]",
|
md: "h-9 w-9 [&>svg]:size-6 [&>svg]:stroke-[1.5]",
|
||||||
lg: "h-10 w-10 [&>svg]:size-7 [&>svg]:stroke-[1.5]"
|
lg: "h-10 w-10 [&>svg]:size-7 [&>svg]:stroke-[1.5]"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ function UnstableTable({ className, ...props }: React.ComponentProps<"table">) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="table-container"
|
data-slot="table-container"
|
||||||
className="relative w-full overflow-x-auto border border-border/50 bg-mineshaft-800/50"
|
className="relative w-full overflow-x-auto border border-border bg-container"
|
||||||
>
|
>
|
||||||
<table
|
<table
|
||||||
data-slot="table"
|
data-slot="table"
|
||||||
@@ -39,10 +39,7 @@ function UnstableTableFooter({ className, ...props }: React.ComponentProps<"tfoo
|
|||||||
return (
|
return (
|
||||||
<tfoot
|
<tfoot
|
||||||
data-slot="table-footer"
|
data-slot="table-footer"
|
||||||
className={cn(
|
className={cn("border-t border-border font-medium [&>tr]:last:border-b-0", className)}
|
||||||
"border-t border-border/50 bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -53,7 +50,7 @@ function UnstableTableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|||||||
<tr
|
<tr
|
||||||
data-slot="table-row"
|
data-slot="table-row"
|
||||||
className={cn(
|
className={cn(
|
||||||
"border-b border-border/50 transition-colors hover:bg-foreground/5 data-[state=selected]:bg-foreground/5",
|
"border-b border-border transition-colors hover:bg-foreground/5 data-[state=selected]:bg-foreground/5",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -66,7 +63,7 @@ function UnstableTableHead({ className, ...props }: React.ComponentProps<"th">)
|
|||||||
<th
|
<th
|
||||||
data-slot="table-head"
|
data-slot="table-head"
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-[30px] border-x-0 border-t-0 border-b border-border/50 px-3 text-left align-middle text-xs whitespace-nowrap text-accent text-mineshaft-400 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
"h-[30px] border-x-0 border-t-0 border-b border-border px-3 text-left align-middle text-xs whitespace-nowrap text-accent [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -91,7 +88,7 @@ function UnstableTableCaption({ className, ...props }: React.ComponentProps<"cap
|
|||||||
return (
|
return (
|
||||||
<caption
|
<caption
|
||||||
data-slot="table-caption"
|
data-slot="table-caption"
|
||||||
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from "./Accordion";
|
||||||
export * from "./Alert";
|
export * from "./Alert";
|
||||||
export * from "./Badge";
|
export * from "./Badge";
|
||||||
export * from "./Button";
|
export * from "./Button";
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export type TIdentity = {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
hasDeleteProtection: boolean;
|
hasDeleteProtection: boolean;
|
||||||
authMethods: IdentityAuthMethod[];
|
authMethods: IdentityAuthMethod[];
|
||||||
activeLockoutAuthMethods: string[];
|
activeLockoutAuthMethods: IdentityAuthMethod[];
|
||||||
metadata?: Array<TMetadata & { id: string }>;
|
metadata?: Array<TMetadata & { id: string }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -49,14 +49,14 @@
|
|||||||
--color-sub-org: #96ff59;
|
--color-sub-org: #96ff59;
|
||||||
--color-project: #e0ed34;
|
--color-project: #e0ed34;
|
||||||
--color-neutral: #adaeb0;
|
--color-neutral: #adaeb0;
|
||||||
--color-border: #323439;
|
--color-border: #2b2c30;
|
||||||
--color-label: #adaeb0;
|
--color-label: #adaeb0;
|
||||||
--color-muted: #707174;
|
--color-muted: #707174;
|
||||||
--color-popover: #111419;
|
--color-popover: #141617;
|
||||||
--color-ring: #2d2f33;
|
--color-ring: #2d2f33;
|
||||||
--color-container: #16181a;
|
--color-card: #16181a;
|
||||||
--color-accent: #7d7f80;
|
--color-accent: #7d7f80;
|
||||||
--color-muted-foreground: ;
|
--color-container: #1a1c1e;
|
||||||
|
|
||||||
/*legacy color schema */
|
/*legacy color schema */
|
||||||
--color-org-v1: #30b3ff;
|
--color-org-v1: #30b3ff;
|
||||||
|
|||||||
+3
-10
@@ -17,7 +17,6 @@ import {
|
|||||||
} from "@app/context";
|
} 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 { OrgAccessControlTabSections } from "@app/types/org";
|
import { OrgAccessControlTabSections } from "@app/types/org";
|
||||||
|
|
||||||
import { IdentityAuthMethodModal } from "../AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
import { IdentityAuthMethodModal } from "../AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
||||||
@@ -125,14 +124,16 @@ const Page = () => {
|
|||||||
identityId={identityId}
|
identityId={identityId}
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
handlePopUpOpen={handlePopUpOpen}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-1 flex-col gap-y-4">
|
||||||
{!isAuthHidden && (
|
{!isAuthHidden && (
|
||||||
<IdentityAuthenticationSection
|
<IdentityAuthenticationSection
|
||||||
identityId={identityId}
|
identityId={identityId}
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
handlePopUpOpen={handlePopUpOpen}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<IdentityProjectsSection identityId={identityId} />
|
||||||
</div>
|
</div>
|
||||||
<IdentityProjectsSection identityId={identityId} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -171,14 +172,6 @@ const Page = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ViewIdentityAuthModal
|
|
||||||
isOpen={popUp.viewAuthMethod.isOpen}
|
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("viewAuthMethod", isOpen)}
|
|
||||||
authMethod={popUp.viewAuthMethod.data?.authMethod}
|
|
||||||
lockedOut={popUp.viewAuthMethod.data?.lockedOut || false}
|
|
||||||
identityId={identityId}
|
|
||||||
onResetAllLockouts={popUp.viewAuthMethod.data?.refetchIdentity}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+38
-59
@@ -1,16 +1,14 @@
|
|||||||
import { faCog, faLock, faPlus } from "@fortawesome/free-solid-svg-icons";
|
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import { Button, Tooltip } from "@app/components/v2";
|
import { Button } from "@app/components/v2";
|
||||||
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/context";
|
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/context";
|
||||||
import {
|
import { IdentityAuthMethod, useGetOrgIdentityMembershipById } from "@app/hooks/api";
|
||||||
IdentityAuthMethod,
|
|
||||||
identityAuthToNameMap,
|
|
||||||
useGetOrgIdentityMembershipById
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
|
import { ViewIdentityAuth } from "../ViewIdentityAuth";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
handlePopUpOpen: (
|
handlePopUpOpen: (
|
||||||
@@ -23,37 +21,42 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P
|
|||||||
const { data, refetch } = useGetOrgIdentityMembershipById(identityId);
|
const { data, refetch } = useGetOrgIdentityMembershipById(identityId);
|
||||||
|
|
||||||
return data ? (
|
return data ? (
|
||||||
<div className="mt-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
<div className="mb-4 flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||||
<h3 className="text-lg font-medium text-mineshaft-100">Authentication</h3>
|
<h3 className="text-lg font-medium text-mineshaft-100">Authentication</h3>
|
||||||
|
{!Object.values(IdentityAuthMethod).every((method) =>
|
||||||
|
data.identity.authMethods.includes(method)
|
||||||
|
) && (
|
||||||
|
<OrgPermissionCan
|
||||||
|
I={OrgPermissionIdentityActions.Edit}
|
||||||
|
a={OrgPermissionSubjects.Identity}
|
||||||
|
>
|
||||||
|
{(isAllowed) => (
|
||||||
|
<Button
|
||||||
|
isDisabled={!isAllowed}
|
||||||
|
onClick={() => {
|
||||||
|
handlePopUpOpen("identityAuthMethod", {
|
||||||
|
identityId,
|
||||||
|
name: data.identity.name,
|
||||||
|
allAuthMethods: data.identity.authMethods
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
variant="outline_bg"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
|
>
|
||||||
|
{data.identity.authMethods.length ? "Add" : "Create"} Auth Method
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</OrgPermissionCan>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{data.identity.authMethods.length > 0 ? (
|
{data.identity.authMethods.length > 0 ? (
|
||||||
<div className="flex flex-col divide-y divide-mineshaft-400/50">
|
<ViewIdentityAuth
|
||||||
{data.identity.authMethods.map((authMethod) => (
|
activeLockoutAuthMethods={data.identity.activeLockoutAuthMethods}
|
||||||
<button
|
identityId={identityId}
|
||||||
key={authMethod}
|
authMethods={data.identity.authMethods}
|
||||||
onClick={() =>
|
onResetAllLockouts={refetch}
|
||||||
handlePopUpOpen("viewAuthMethod", {
|
/>
|
||||||
authMethod,
|
|
||||||
lockedOut: data.identity.activeLockoutAuthMethods.includes(authMethod),
|
|
||||||
refetchIdentity: refetch
|
|
||||||
})
|
|
||||||
}
|
|
||||||
type="button"
|
|
||||||
className="flex w-full items-center justify-between bg-mineshaft-900 px-4 py-2 text-sm hover:bg-mineshaft-700 data-[state=open]:bg-mineshaft-600"
|
|
||||||
>
|
|
||||||
<span>{identityAuthToNameMap[authMethod]}</span>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
{data.identity.activeLockoutAuthMethods.includes(authMethod) && (
|
|
||||||
<Tooltip content="Auth method has active lockouts">
|
|
||||||
<FontAwesomeIcon icon={faLock} size="xs" className="text-red-400/50" />
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
<FontAwesomeIcon icon={faCog} size="xs" className="text-mineshaft-400" />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full space-y-2 pt-2">
|
<div className="w-full space-y-2 pt-2">
|
||||||
<p className="text-sm text-mineshaft-300">
|
<p className="text-sm text-mineshaft-300">
|
||||||
@@ -61,30 +64,6 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!Object.values(IdentityAuthMethod).every((method) =>
|
|
||||||
data.identity.authMethods.includes(method)
|
|
||||||
) && (
|
|
||||||
<OrgPermissionCan I={OrgPermissionIdentityActions.Edit} a={OrgPermissionSubjects.Identity}>
|
|
||||||
{(isAllowed) => (
|
|
||||||
<Button
|
|
||||||
isDisabled={!isAllowed}
|
|
||||||
onClick={() => {
|
|
||||||
handlePopUpOpen("identityAuthMethod", {
|
|
||||||
identityId,
|
|
||||||
name: data.identity.name,
|
|
||||||
allAuthMethods: data.identity.authMethods
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
variant="outline_bg"
|
|
||||||
className="mt-3 w-full"
|
|
||||||
size="xs"
|
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
|
||||||
>
|
|
||||||
{data.identity.authMethods.length ? "Add" : "Create"} Auth Method
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</OrgPermissionCan>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div />
|
<div />
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
import { Detail, DetailLabel, DetailValue } from "@app/components/v3";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
label: string;
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IdentityAuthFieldDisplay = ({ label, children, className }: Props) => {
|
||||||
|
return (
|
||||||
|
<Detail className={className}>
|
||||||
|
<DetailLabel>{label}</DetailLabel>
|
||||||
|
<DetailValue>
|
||||||
|
{children ? (
|
||||||
|
<p className="break-words">{children}</p>
|
||||||
|
) : (
|
||||||
|
<p className="text-muted italic">Not set</p>
|
||||||
|
)}
|
||||||
|
</DetailValue>
|
||||||
|
</Detail>
|
||||||
|
);
|
||||||
|
};
|
||||||
+3
-21
@@ -2,7 +2,6 @@ import { faBan } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import { EmptyState, Spinner } from "@app/components/v2";
|
import { EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { useGetIdentityAliCloudAuth } from "@app/hooks/api";
|
import { useGetIdentityAliCloudAuth } from "@app/hooks/api";
|
||||||
import { IdentityAliCloudAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAliCloudAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -10,10 +9,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityAliCloudAuthContent = ({
|
export const ViewIdentityAliCloudAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityAliCloudAuth(identityId);
|
const { data, isPending } = useGetIdentityAliCloudAuth(identityId);
|
||||||
|
|
||||||
@@ -34,23 +31,8 @@ export const ViewIdentityAliCloudAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityAliCloudAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+276
@@ -0,0 +1,276 @@
|
|||||||
|
import { useParams } from "@tanstack/react-router";
|
||||||
|
import { EllipsisIcon, LockIcon } from "lucide-react";
|
||||||
|
|
||||||
|
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
|
import { DeleteActionModal, Modal, ModalContent, Tooltip } from "@app/components/v2";
|
||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
UnstableAccordion,
|
||||||
|
UnstableAccordionContent,
|
||||||
|
UnstableAccordionItem,
|
||||||
|
UnstableAccordionTrigger,
|
||||||
|
UnstableDropdownMenu,
|
||||||
|
UnstableDropdownMenuContent,
|
||||||
|
UnstableDropdownMenuItem,
|
||||||
|
UnstableDropdownMenuTrigger,
|
||||||
|
UnstableIconButton
|
||||||
|
} from "@app/components/v3";
|
||||||
|
import { useOrganization } from "@app/context";
|
||||||
|
import { usePopUp } from "@app/hooks";
|
||||||
|
import {
|
||||||
|
IdentityAuthMethod,
|
||||||
|
identityAuthToNameMap,
|
||||||
|
useDeleteIdentityAliCloudAuth,
|
||||||
|
useDeleteIdentityAwsAuth,
|
||||||
|
useDeleteIdentityAzureAuth,
|
||||||
|
useDeleteIdentityGcpAuth,
|
||||||
|
useDeleteIdentityJwtAuth,
|
||||||
|
useDeleteIdentityKubernetesAuth,
|
||||||
|
useDeleteIdentityLdapAuth,
|
||||||
|
useDeleteIdentityOciAuth,
|
||||||
|
useDeleteIdentityOidcAuth,
|
||||||
|
useDeleteIdentityTlsCertAuth,
|
||||||
|
useDeleteIdentityTokenAuth,
|
||||||
|
useDeleteIdentityUniversalAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
|
import { IdentityAliCloudAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAliCloudAuthForm";
|
||||||
|
import { IdentityAwsAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAwsAuthForm";
|
||||||
|
import { IdentityAzureAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAzureAuthForm";
|
||||||
|
import { IdentityGcpAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityGcpAuthForm";
|
||||||
|
import { IdentityJwtAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityJwtAuthForm";
|
||||||
|
import { IdentityKubernetesAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm";
|
||||||
|
import { IdentityLdapAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityLdapAuthForm";
|
||||||
|
import { IdentityOciAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityOciAuthForm";
|
||||||
|
import { IdentityOidcAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityOidcAuthForm";
|
||||||
|
import { IdentityTlsCertAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityTlsCertAuthForm";
|
||||||
|
import { IdentityTokenAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityTokenAuthForm";
|
||||||
|
import { IdentityUniversalAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm";
|
||||||
|
|
||||||
|
import { ViewIdentityAliCloudAuthContent } from "./ViewIdentityAliCloudAuthContent";
|
||||||
|
import { ViewIdentityAwsAuthContent } from "./ViewIdentityAwsAuthContent";
|
||||||
|
import { ViewIdentityAzureAuthContent } from "./ViewIdentityAzureAuthContent";
|
||||||
|
import { ViewIdentityGcpAuthContent } from "./ViewIdentityGcpAuthContent";
|
||||||
|
import { ViewIdentityJwtAuthContent } from "./ViewIdentityJwtAuthContent";
|
||||||
|
import { ViewIdentityKubernetesAuthContent } from "./ViewIdentityKubernetesAuthContent";
|
||||||
|
import { ViewIdentityLdapAuthContent } from "./ViewIdentityLdapAuthContent";
|
||||||
|
import { ViewIdentityOciAuthContent } from "./ViewIdentityOciAuthContent";
|
||||||
|
import { ViewIdentityOidcAuthContent } from "./ViewIdentityOidcAuthContent";
|
||||||
|
import { ViewIdentityTlsCertAuthContent } from "./ViewIdentityTlsCertAuthContent";
|
||||||
|
import { ViewIdentityTokenAuthContent } from "./ViewIdentityTokenAuthContent";
|
||||||
|
import { ViewIdentityUniversalAuthContent } from "./ViewIdentityUniversalAuthContent";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
identityId: string;
|
||||||
|
authMethods: IdentityAuthMethod[];
|
||||||
|
onResetAllLockouts: () => void;
|
||||||
|
activeLockoutAuthMethods: IdentityAuthMethod[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const AuthMethodComponentMap = {
|
||||||
|
[IdentityAuthMethod.UNIVERSAL_AUTH]: ViewIdentityUniversalAuthContent,
|
||||||
|
[IdentityAuthMethod.TOKEN_AUTH]: ViewIdentityTokenAuthContent,
|
||||||
|
[IdentityAuthMethod.TLS_CERT_AUTH]: ViewIdentityTlsCertAuthContent,
|
||||||
|
[IdentityAuthMethod.KUBERNETES_AUTH]: ViewIdentityKubernetesAuthContent,
|
||||||
|
[IdentityAuthMethod.LDAP_AUTH]: ViewIdentityLdapAuthContent,
|
||||||
|
[IdentityAuthMethod.OCI_AUTH]: ViewIdentityOciAuthContent,
|
||||||
|
[IdentityAuthMethod.OIDC_AUTH]: ViewIdentityOidcAuthContent,
|
||||||
|
[IdentityAuthMethod.GCP_AUTH]: ViewIdentityGcpAuthContent,
|
||||||
|
[IdentityAuthMethod.AWS_AUTH]: ViewIdentityAwsAuthContent,
|
||||||
|
[IdentityAuthMethod.ALICLOUD_AUTH]: ViewIdentityAliCloudAuthContent,
|
||||||
|
[IdentityAuthMethod.AZURE_AUTH]: ViewIdentityAzureAuthContent,
|
||||||
|
[IdentityAuthMethod.JWT_AUTH]: ViewIdentityJwtAuthContent
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditAuthMethodMap = {
|
||||||
|
[IdentityAuthMethod.KUBERNETES_AUTH]: IdentityKubernetesAuthForm,
|
||||||
|
[IdentityAuthMethod.GCP_AUTH]: IdentityGcpAuthForm,
|
||||||
|
[IdentityAuthMethod.TLS_CERT_AUTH]: IdentityTlsCertAuthForm,
|
||||||
|
[IdentityAuthMethod.AWS_AUTH]: IdentityAwsAuthForm,
|
||||||
|
[IdentityAuthMethod.AZURE_AUTH]: IdentityAzureAuthForm,
|
||||||
|
[IdentityAuthMethod.ALICLOUD_AUTH]: IdentityAliCloudAuthForm,
|
||||||
|
[IdentityAuthMethod.UNIVERSAL_AUTH]: IdentityUniversalAuthForm,
|
||||||
|
[IdentityAuthMethod.TOKEN_AUTH]: IdentityTokenAuthForm,
|
||||||
|
[IdentityAuthMethod.OCI_AUTH]: IdentityOciAuthForm,
|
||||||
|
[IdentityAuthMethod.OIDC_AUTH]: IdentityOidcAuthForm,
|
||||||
|
[IdentityAuthMethod.JWT_AUTH]: IdentityJwtAuthForm,
|
||||||
|
[IdentityAuthMethod.LDAP_AUTH]: IdentityLdapAuthForm
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Content = ({
|
||||||
|
identityId,
|
||||||
|
authMethods,
|
||||||
|
onResetAllLockouts,
|
||||||
|
activeLockoutAuthMethods
|
||||||
|
}: Pick<
|
||||||
|
Props,
|
||||||
|
"authMethods" | "identityId" | "onResetAllLockouts" | "activeLockoutAuthMethods"
|
||||||
|
>) => {
|
||||||
|
const { currentOrg } = useOrganization();
|
||||||
|
const orgId = currentOrg?.id || "";
|
||||||
|
const { projectId } = useParams({
|
||||||
|
strict: false
|
||||||
|
});
|
||||||
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
||||||
|
"revokeAuthMethod",
|
||||||
|
"identityAuthMethod",
|
||||||
|
"upgradePlan"
|
||||||
|
] as const);
|
||||||
|
|
||||||
|
const { mutateAsync: revokeUniversalAuth } = useDeleteIdentityUniversalAuth();
|
||||||
|
const { mutateAsync: revokeTokenAuth } = useDeleteIdentityTokenAuth();
|
||||||
|
const { mutateAsync: revokeKubernetesAuth } = useDeleteIdentityKubernetesAuth();
|
||||||
|
const { mutateAsync: revokeGcpAuth } = useDeleteIdentityGcpAuth();
|
||||||
|
const { mutateAsync: revokeTlsCertAuth } = useDeleteIdentityTlsCertAuth();
|
||||||
|
const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth();
|
||||||
|
const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth();
|
||||||
|
const { mutateAsync: revokeAliCloudAuth } = useDeleteIdentityAliCloudAuth();
|
||||||
|
const { mutateAsync: revokeOciAuth } = useDeleteIdentityOciAuth();
|
||||||
|
const { mutateAsync: revokeOidcAuth } = useDeleteIdentityOidcAuth();
|
||||||
|
const { mutateAsync: revokeJwtAuth } = useDeleteIdentityJwtAuth();
|
||||||
|
const { mutateAsync: revokeLdapAuth } = useDeleteIdentityLdapAuth();
|
||||||
|
|
||||||
|
const RemoveAuthMethodMap = {
|
||||||
|
[IdentityAuthMethod.KUBERNETES_AUTH]: revokeKubernetesAuth,
|
||||||
|
[IdentityAuthMethod.GCP_AUTH]: revokeGcpAuth,
|
||||||
|
[IdentityAuthMethod.TLS_CERT_AUTH]: revokeTlsCertAuth,
|
||||||
|
[IdentityAuthMethod.AWS_AUTH]: revokeAwsAuth,
|
||||||
|
[IdentityAuthMethod.AZURE_AUTH]: revokeAzureAuth,
|
||||||
|
[IdentityAuthMethod.ALICLOUD_AUTH]: revokeAliCloudAuth,
|
||||||
|
[IdentityAuthMethod.UNIVERSAL_AUTH]: revokeUniversalAuth,
|
||||||
|
[IdentityAuthMethod.TOKEN_AUTH]: revokeTokenAuth,
|
||||||
|
[IdentityAuthMethod.OCI_AUTH]: revokeOciAuth,
|
||||||
|
[IdentityAuthMethod.OIDC_AUTH]: revokeOidcAuth,
|
||||||
|
[IdentityAuthMethod.JWT_AUTH]: revokeJwtAuth,
|
||||||
|
[IdentityAuthMethod.LDAP_AUTH]: revokeLdapAuth
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteAuthMethod = async (authMethod: IdentityAuthMethod) => {
|
||||||
|
await RemoveAuthMethodMap[authMethod]({
|
||||||
|
identityId,
|
||||||
|
...(projectId
|
||||||
|
? { projectId }
|
||||||
|
: {
|
||||||
|
organizationId: orgId
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Successfully removed auth method",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
handlePopUpToggle("revokeAuthMethod", false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditForm = popUp.identityAuthMethod?.data
|
||||||
|
? EditAuthMethodMap[popUp.identityAuthMethod.data as IdentityAuthMethod]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<UnstableAccordion type={authMethods.length === 1 ? "single" : "multiple"} collapsible>
|
||||||
|
{authMethods.map((authMethod) => {
|
||||||
|
const Component = AuthMethodComponentMap[authMethod];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UnstableAccordionItem key={authMethod} value={authMethod}>
|
||||||
|
<UnstableAccordionTrigger>
|
||||||
|
<span className="mr-auto">{identityAuthToNameMap[authMethod]}</span>
|
||||||
|
{activeLockoutAuthMethods?.includes(authMethod) && (
|
||||||
|
<Tooltip content="Auth method has active lockouts">
|
||||||
|
<Badge isSquare variant="danger">
|
||||||
|
<LockIcon />
|
||||||
|
</Badge>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
<UnstableDropdownMenu>
|
||||||
|
<UnstableDropdownMenuTrigger asChild>
|
||||||
|
<UnstableIconButton variant="ghost" size="xs">
|
||||||
|
<EllipsisIcon />
|
||||||
|
</UnstableIconButton>
|
||||||
|
</UnstableDropdownMenuTrigger>
|
||||||
|
<UnstableDropdownMenuContent align="end">
|
||||||
|
<UnstableDropdownMenuItem
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePopUpOpen("identityAuthMethod", authMethod);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Edit Auth Method
|
||||||
|
</UnstableDropdownMenuItem>
|
||||||
|
<UnstableDropdownMenuItem
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePopUpOpen("revokeAuthMethod", authMethod);
|
||||||
|
}}
|
||||||
|
variant="danger"
|
||||||
|
>
|
||||||
|
Remove Auth Method
|
||||||
|
</UnstableDropdownMenuItem>
|
||||||
|
</UnstableDropdownMenuContent>
|
||||||
|
</UnstableDropdownMenu>
|
||||||
|
</UnstableAccordionTrigger>
|
||||||
|
<UnstableAccordionContent>
|
||||||
|
<Component
|
||||||
|
identityId={identityId}
|
||||||
|
onEdit={() => handlePopUpOpen("identityAuthMethod", authMethod)}
|
||||||
|
onDelete={() => handlePopUpOpen("revokeAuthMethod", authMethod)}
|
||||||
|
onResetAllLockouts={onResetAllLockouts}
|
||||||
|
lockedOut={activeLockoutAuthMethods?.includes(authMethod)}
|
||||||
|
/>
|
||||||
|
</UnstableAccordionContent>
|
||||||
|
</UnstableAccordionItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</UnstableAccordion>
|
||||||
|
<DeleteActionModal
|
||||||
|
isOpen={popUp?.revokeAuthMethod?.isOpen}
|
||||||
|
title={`Are you sure you want to remove ${popUp?.revokeAuthMethod?.data ? identityAuthToNameMap[popUp?.revokeAuthMethod?.data as IdentityAuthMethod] : "this auth method"} on this identity?`}
|
||||||
|
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
|
||||||
|
deleteKey="confirm"
|
||||||
|
buttonText="Remove"
|
||||||
|
onDeleteApproved={() =>
|
||||||
|
handleDeleteAuthMethod(popUp?.revokeAuthMethod?.data as IdentityAuthMethod)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Modal
|
||||||
|
isOpen={popUp?.identityAuthMethod?.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("identityAuthMethod", isOpen)}
|
||||||
|
>
|
||||||
|
<ModalContent
|
||||||
|
title={`Edit ${popUp?.identityAuthMethod?.data ? identityAuthToNameMap[popUp?.identityAuthMethod?.data as IdentityAuthMethod] : "this auth method"}`}
|
||||||
|
>
|
||||||
|
{EditForm && (
|
||||||
|
<EditForm
|
||||||
|
identityId={identityId}
|
||||||
|
isUpdate
|
||||||
|
handlePopUpOpen={handlePopUpOpen}
|
||||||
|
handlePopUpToggle={handlePopUpToggle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
text={`Your current plan does not include access to ${popUp.upgradePlan.data?.featureName}. To unlock this feature, please upgrade to Infisical ${popUp.upgradePlan.data?.isEnterpriseFeature ? "Enterprise" : "Pro"} plan.`}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewIdentityAuth = ({
|
||||||
|
authMethods,
|
||||||
|
identityId,
|
||||||
|
onResetAllLockouts,
|
||||||
|
activeLockoutAuthMethods
|
||||||
|
}: Props) => {
|
||||||
|
return (
|
||||||
|
<Content
|
||||||
|
identityId={identityId}
|
||||||
|
authMethods={authMethods}
|
||||||
|
activeLockoutAuthMethods={activeLockoutAuthMethods}
|
||||||
|
onResetAllLockouts={() => onResetAllLockouts()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
+3
-21
@@ -2,7 +2,6 @@ import { faBan } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import { EmptyState, Spinner } from "@app/components/v2";
|
import { EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { useGetIdentityAwsAuth } from "@app/hooks/api";
|
import { useGetIdentityAwsAuth } from "@app/hooks/api";
|
||||||
import { IdentityAwsAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAwsAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -10,10 +9,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityAwsAuthContent = ({
|
export const ViewIdentityAwsAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityAwsAuth(identityId);
|
const { data, isPending } = useGetIdentityAwsAuth(identityId);
|
||||||
|
|
||||||
@@ -31,23 +28,8 @@ export const ViewIdentityAwsAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityAwsAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+3
-21
@@ -2,7 +2,6 @@ import { faBan } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import { EmptyState, Spinner } from "@app/components/v2";
|
import { EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { useGetIdentityAzureAuth } from "@app/hooks/api";
|
import { useGetIdentityAzureAuth } from "@app/hooks/api";
|
||||||
import { IdentityAzureAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAzureAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -10,10 +9,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityAzureAuthContent = ({
|
export const ViewIdentityAzureAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityAzureAuth(identityId);
|
const { data, isPending } = useGetIdentityAzureAuth(identityId);
|
||||||
|
|
||||||
@@ -31,23 +28,8 @@ export const ViewIdentityAzureAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityAzureAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+3
-21
@@ -2,7 +2,6 @@ import { faBan } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import { EmptyState, Spinner } from "@app/components/v2";
|
import { EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { useGetIdentityGcpAuth } from "@app/hooks/api";
|
import { useGetIdentityGcpAuth } from "@app/hooks/api";
|
||||||
import { IdentityGcpAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityGcpAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -10,10 +9,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityGcpAuthContent = ({
|
export const ViewIdentityGcpAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityGcpAuth(identityId);
|
const { data, isPending } = useGetIdentityGcpAuth(identityId);
|
||||||
|
|
||||||
@@ -31,23 +28,8 @@ export const ViewIdentityGcpAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityGcpAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+4
-22
@@ -5,18 +5,15 @@ import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
|||||||
import { Badge } from "@app/components/v3";
|
import { Badge } from "@app/components/v3";
|
||||||
import { useGetIdentityJwtAuth } from "@app/hooks/api";
|
import { useGetIdentityJwtAuth } from "@app/hooks/api";
|
||||||
import { IdentityJwtConfigurationType } from "@app/hooks/api/identities/enums";
|
import { IdentityJwtConfigurationType } from "@app/hooks/api/identities/enums";
|
||||||
import { IdentityJwtAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityJwtAuthForm";
|
import { ViewIdentityContentWrapper } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuth/ViewIdentityContentWrapper";
|
||||||
import { ViewIdentityContentWrapper } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityContentWrapper";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
|
|
||||||
export const ViewIdentityJwtAuthContent = ({
|
export const ViewIdentityJwtAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityJwtAuth(identityId);
|
const { data, isPending } = useGetIdentityJwtAuth(identityId);
|
||||||
|
|
||||||
@@ -34,23 +31,8 @@ export const ViewIdentityJwtAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityJwtAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+3
-21
@@ -6,7 +6,6 @@ import { EyeIcon } from "lucide-react";
|
|||||||
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
||||||
import { Badge } from "@app/components/v3";
|
import { Badge } from "@app/components/v3";
|
||||||
import { gatewaysQueryKeys, useGetIdentityKubernetesAuth } from "@app/hooks/api";
|
import { gatewaysQueryKeys, useGetIdentityKubernetesAuth } from "@app/hooks/api";
|
||||||
import { IdentityKubernetesAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -14,10 +13,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityKubernetesAuthContent = ({
|
export const ViewIdentityKubernetesAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data: gateways } = useQuery(gatewaysQueryKeys.list());
|
const { data: gateways } = useQuery(gatewaysQueryKeys.list());
|
||||||
|
|
||||||
@@ -44,23 +41,8 @@ export const ViewIdentityKubernetesAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityKubernetesAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+3
-21
@@ -4,8 +4,7 @@ import { EyeIcon } from "lucide-react";
|
|||||||
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
||||||
import { Badge } from "@app/components/v3";
|
import { Badge } from "@app/components/v3";
|
||||||
import { useClearIdentityLdapAuthLockouts, useGetIdentityLdapAuth } from "@app/hooks/api";
|
import { useClearIdentityLdapAuthLockouts, useGetIdentityLdapAuth } from "@app/hooks/api";
|
||||||
import { IdentityLdapAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityLdapAuthForm";
|
import { ViewIdentityContentWrapper } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuth/ViewIdentityContentWrapper";
|
||||||
import { ViewIdentityContentWrapper } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityContentWrapper";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { LockoutFields } from "./IdentityAuthLockoutFields";
|
import { LockoutFields } from "./IdentityAuthLockoutFields";
|
||||||
@@ -13,10 +12,8 @@ import { ViewAuthMethodProps } from "./types";
|
|||||||
|
|
||||||
export const ViewIdentityLdapAuthContent = ({
|
export const ViewIdentityLdapAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
|
||||||
handlePopUpOpen,
|
|
||||||
onDelete,
|
onDelete,
|
||||||
popUp,
|
onEdit,
|
||||||
lockedOut,
|
lockedOut,
|
||||||
onResetAllLockouts
|
onResetAllLockouts
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
@@ -37,23 +34,8 @@ export const ViewIdentityLdapAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityLdapAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+3
-21
@@ -2,7 +2,6 @@ import { faBan } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import { EmptyState, Spinner } from "@app/components/v2";
|
import { EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { useGetIdentityOciAuth } from "@app/hooks/api";
|
import { useGetIdentityOciAuth } from "@app/hooks/api";
|
||||||
import { IdentityOciAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityOciAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -10,10 +9,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityOciAuthContent = ({
|
export const ViewIdentityOciAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityOciAuth(identityId);
|
const { data, isPending } = useGetIdentityOciAuth(identityId);
|
||||||
|
|
||||||
@@ -31,23 +28,8 @@ export const ViewIdentityOciAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityOciAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+4
-22
@@ -4,18 +4,15 @@ import { EyeIcon } from "lucide-react";
|
|||||||
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
||||||
import { Badge } from "@app/components/v3";
|
import { Badge } from "@app/components/v3";
|
||||||
import { useGetIdentityOidcAuth } from "@app/hooks/api";
|
import { useGetIdentityOidcAuth } from "@app/hooks/api";
|
||||||
import { IdentityOidcAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityOidcAuthForm";
|
import { ViewIdentityContentWrapper } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuth/ViewIdentityContentWrapper";
|
||||||
import { ViewIdentityContentWrapper } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityContentWrapper";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
|
|
||||||
export const ViewIdentityOidcAuthContent = ({
|
export const ViewIdentityOidcAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityOidcAuth(identityId);
|
const { data, isPending } = useGetIdentityOidcAuth(identityId);
|
||||||
|
|
||||||
@@ -33,23 +30,8 @@ export const ViewIdentityOidcAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityOidcAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+3
-21
@@ -4,7 +4,6 @@ import { EyeIcon } from "lucide-react";
|
|||||||
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
import { EmptyState, Spinner, Tooltip } from "@app/components/v2";
|
||||||
import { Badge } from "@app/components/v3";
|
import { Badge } from "@app/components/v3";
|
||||||
import { useGetIdentityTlsCertAuth } from "@app/hooks/api";
|
import { useGetIdentityTlsCertAuth } from "@app/hooks/api";
|
||||||
import { IdentityTlsCertAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityTlsCertAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { ViewAuthMethodProps } from "./types";
|
import { ViewAuthMethodProps } from "./types";
|
||||||
@@ -12,10 +11,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityTlsCertAuthContent = ({
|
export const ViewIdentityTlsCertAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
onEdit,
|
||||||
handlePopUpOpen,
|
onDelete
|
||||||
onDelete,
|
|
||||||
popUp
|
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityTlsCertAuth(identityId);
|
const { data, isPending } = useGetIdentityTlsCertAuth(identityId);
|
||||||
|
|
||||||
@@ -36,23 +33,8 @@ export const ViewIdentityTlsCertAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityTlsCertAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+2
-20
@@ -2,7 +2,6 @@ import { faBan } from "@fortawesome/free-solid-svg-icons";
|
|||||||
|
|
||||||
import { EmptyState, Spinner } from "@app/components/v2";
|
import { EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { useGetIdentityTokenAuth, useGetIdentityTokensTokenAuth } from "@app/hooks/api";
|
import { useGetIdentityTokenAuth, useGetIdentityTokensTokenAuth } from "@app/hooks/api";
|
||||||
import { IdentityTokenAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityTokenAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { IdentityTokenAuthTokensTable } from "./IdentityTokenAuthTokensTable";
|
import { IdentityTokenAuthTokensTable } from "./IdentityTokenAuthTokensTable";
|
||||||
@@ -11,10 +10,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityTokenAuthContent = ({
|
export const ViewIdentityTokenAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
|
||||||
handlePopUpOpen,
|
|
||||||
onDelete,
|
onDelete,
|
||||||
popUp
|
onEdit
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
const { data, isPending } = useGetIdentityTokenAuth(identityId);
|
const { data, isPending } = useGetIdentityTokenAuth(identityId);
|
||||||
const { data: tokens = [], isPending: clientSecretsPending } =
|
const { data: tokens = [], isPending: clientSecretsPending } =
|
||||||
@@ -34,23 +31,8 @@ export const ViewIdentityTokenAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityTokenAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token TTL (seconds)">
|
||||||
{data.accessTokenTTL}
|
{data.accessTokenTTL}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
+2
-20
@@ -8,7 +8,6 @@ import {
|
|||||||
useGetIdentityUniversalAuth,
|
useGetIdentityUniversalAuth,
|
||||||
useGetIdentityUniversalAuthClientSecrets
|
useGetIdentityUniversalAuthClientSecrets
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { IdentityUniversalAuthForm } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm";
|
|
||||||
|
|
||||||
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
import { IdentityAuthFieldDisplay } from "./IdentityAuthFieldDisplay";
|
||||||
import { LockoutFields } from "./IdentityAuthLockoutFields";
|
import { LockoutFields } from "./IdentityAuthLockoutFields";
|
||||||
@@ -18,10 +17,8 @@ import { ViewIdentityContentWrapper } from "./ViewIdentityContentWrapper";
|
|||||||
|
|
||||||
export const ViewIdentityUniversalAuthContent = ({
|
export const ViewIdentityUniversalAuthContent = ({
|
||||||
identityId,
|
identityId,
|
||||||
handlePopUpToggle,
|
|
||||||
handlePopUpOpen,
|
|
||||||
onDelete,
|
onDelete,
|
||||||
popUp,
|
onEdit,
|
||||||
lockedOut,
|
lockedOut,
|
||||||
onResetAllLockouts
|
onResetAllLockouts
|
||||||
}: ViewAuthMethodProps) => {
|
}: ViewAuthMethodProps) => {
|
||||||
@@ -51,23 +48,8 @@ export const ViewIdentityUniversalAuthContent = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popUp.identityAuthMethod.isOpen) {
|
|
||||||
return (
|
|
||||||
<IdentityUniversalAuthForm
|
|
||||||
identityId={identityId}
|
|
||||||
isUpdate
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewIdentityContentWrapper
|
<ViewIdentityContentWrapper onEdit={onEdit} onDelete={onDelete} identityId={identityId}>
|
||||||
onEdit={() => handlePopUpOpen("identityAuthMethod")}
|
|
||||||
onDelete={onDelete}
|
|
||||||
identityId={identityId}
|
|
||||||
>
|
|
||||||
{Number(data.accessTokenPeriod) > 0 ? (
|
{Number(data.accessTokenPeriod) > 0 ? (
|
||||||
<IdentityAuthFieldDisplay label="Access Token Period (seconds)">
|
<IdentityAuthFieldDisplay label="Access Token Period (seconds)">
|
||||||
{data.accessTokenPeriod}
|
{data.accessTokenPeriod}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
export * from "./ViewIdentityAuth";
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
export type ViewAuthMethodProps = {
|
||||||
|
identityId: string;
|
||||||
|
onDelete: () => void;
|
||||||
|
onEdit: () => void;
|
||||||
|
lockedOut: boolean;
|
||||||
|
onResetAllLockouts: () => void;
|
||||||
|
};
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
import { ReactNode } from "react";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
label: string;
|
|
||||||
children: ReactNode;
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IdentityAuthFieldDisplay = ({ label, children, className }: Props) => {
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
<span className="text-sm text-mineshaft-400">{label}</span>
|
|
||||||
{children ? (
|
|
||||||
<p className="text-base leading-4 break-words">{children}</p>
|
|
||||||
) : (
|
|
||||||
<p className="text-base leading-4 text-bunker-400 italic">Not set</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
-214
@@ -1,214 +0,0 @@
|
|||||||
import { useParams } from "@tanstack/react-router";
|
|
||||||
|
|
||||||
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
|
||||||
import { DeleteActionModal, Modal, ModalContent } from "@app/components/v2";
|
|
||||||
import { useOrganization } from "@app/context";
|
|
||||||
import { usePopUp } from "@app/hooks";
|
|
||||||
import {
|
|
||||||
IdentityAuthMethod,
|
|
||||||
identityAuthToNameMap,
|
|
||||||
useDeleteIdentityAliCloudAuth,
|
|
||||||
useDeleteIdentityAwsAuth,
|
|
||||||
useDeleteIdentityAzureAuth,
|
|
||||||
useDeleteIdentityGcpAuth,
|
|
||||||
useDeleteIdentityJwtAuth,
|
|
||||||
useDeleteIdentityKubernetesAuth,
|
|
||||||
useDeleteIdentityLdapAuth,
|
|
||||||
useDeleteIdentityOciAuth,
|
|
||||||
useDeleteIdentityOidcAuth,
|
|
||||||
useDeleteIdentityTlsCertAuth,
|
|
||||||
useDeleteIdentityTokenAuth,
|
|
||||||
useDeleteIdentityUniversalAuth
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
|
|
||||||
import { ViewAuthMethodProps } from "./types";
|
|
||||||
import { ViewIdentityAliCloudAuthContent } from "./ViewIdentityAliCloudAuthContent";
|
|
||||||
import { ViewIdentityAwsAuthContent } from "./ViewIdentityAwsAuthContent";
|
|
||||||
import { ViewIdentityAzureAuthContent } from "./ViewIdentityAzureAuthContent";
|
|
||||||
import { ViewIdentityGcpAuthContent } from "./ViewIdentityGcpAuthContent";
|
|
||||||
import { ViewIdentityJwtAuthContent } from "./ViewIdentityJwtAuthContent";
|
|
||||||
import { ViewIdentityKubernetesAuthContent } from "./ViewIdentityKubernetesAuthContent";
|
|
||||||
import { ViewIdentityLdapAuthContent } from "./ViewIdentityLdapAuthContent";
|
|
||||||
import { ViewIdentityOciAuthContent } from "./ViewIdentityOciAuthContent";
|
|
||||||
import { ViewIdentityOidcAuthContent } from "./ViewIdentityOidcAuthContent";
|
|
||||||
import { ViewIdentityTlsCertAuthContent } from "./ViewIdentityTlsCertAuthContent";
|
|
||||||
import { ViewIdentityTokenAuthContent } from "./ViewIdentityTokenAuthContent";
|
|
||||||
import { ViewIdentityUniversalAuthContent } from "./ViewIdentityUniversalAuthContent";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
identityId: string;
|
|
||||||
authMethod?: IdentityAuthMethod;
|
|
||||||
lockedOut: boolean;
|
|
||||||
isOpen: boolean;
|
|
||||||
onOpenChange: (isOpen: boolean) => void;
|
|
||||||
onDeleteAuthMethod: () => void;
|
|
||||||
onResetAllLockouts: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TRevokeOptions = {
|
|
||||||
identityId: string;
|
|
||||||
} & ({ projectId: string } | { organizationId: string });
|
|
||||||
|
|
||||||
export const Content = ({
|
|
||||||
identityId,
|
|
||||||
authMethod,
|
|
||||||
lockedOut,
|
|
||||||
onDeleteAuthMethod,
|
|
||||||
onResetAllLockouts
|
|
||||||
}: Pick<
|
|
||||||
Props,
|
|
||||||
"authMethod" | "lockedOut" | "identityId" | "onDeleteAuthMethod" | "onResetAllLockouts"
|
|
||||||
>) => {
|
|
||||||
const { currentOrg } = useOrganization();
|
|
||||||
const orgId = currentOrg?.id || "";
|
|
||||||
const { projectId } = useParams({
|
|
||||||
strict: false
|
|
||||||
});
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
|
||||||
"revokeAuthMethod",
|
|
||||||
"upgradePlan",
|
|
||||||
"identityAuthMethod"
|
|
||||||
] as const);
|
|
||||||
|
|
||||||
const { mutateAsync: revokeUniversalAuth } = useDeleteIdentityUniversalAuth();
|
|
||||||
const { mutateAsync: revokeTokenAuth } = useDeleteIdentityTokenAuth();
|
|
||||||
const { mutateAsync: revokeKubernetesAuth } = useDeleteIdentityKubernetesAuth();
|
|
||||||
const { mutateAsync: revokeGcpAuth } = useDeleteIdentityGcpAuth();
|
|
||||||
const { mutateAsync: revokeTlsCertAuth } = useDeleteIdentityTlsCertAuth();
|
|
||||||
const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth();
|
|
||||||
const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth();
|
|
||||||
const { mutateAsync: revokeAliCloudAuth } = useDeleteIdentityAliCloudAuth();
|
|
||||||
const { mutateAsync: revokeOciAuth } = useDeleteIdentityOciAuth();
|
|
||||||
const { mutateAsync: revokeOidcAuth } = useDeleteIdentityOidcAuth();
|
|
||||||
const { mutateAsync: revokeJwtAuth } = useDeleteIdentityJwtAuth();
|
|
||||||
const { mutateAsync: revokeLdapAuth } = useDeleteIdentityLdapAuth();
|
|
||||||
|
|
||||||
let Component: (props: ViewAuthMethodProps) => JSX.Element;
|
|
||||||
let revokeMethod: (revokeOptions: TRevokeOptions) => Promise<any>;
|
|
||||||
|
|
||||||
const handleDelete = () => handlePopUpOpen("revokeAuthMethod");
|
|
||||||
|
|
||||||
switch (authMethod) {
|
|
||||||
case IdentityAuthMethod.UNIVERSAL_AUTH:
|
|
||||||
revokeMethod = revokeUniversalAuth;
|
|
||||||
Component = ViewIdentityUniversalAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.TOKEN_AUTH:
|
|
||||||
revokeMethod = revokeTokenAuth;
|
|
||||||
Component = ViewIdentityTokenAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.KUBERNETES_AUTH:
|
|
||||||
revokeMethod = revokeKubernetesAuth;
|
|
||||||
Component = ViewIdentityKubernetesAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.GCP_AUTH:
|
|
||||||
revokeMethod = revokeGcpAuth;
|
|
||||||
Component = ViewIdentityGcpAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.TLS_CERT_AUTH:
|
|
||||||
revokeMethod = revokeTlsCertAuth;
|
|
||||||
Component = ViewIdentityTlsCertAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.AWS_AUTH:
|
|
||||||
revokeMethod = revokeAwsAuth;
|
|
||||||
Component = ViewIdentityAwsAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.AZURE_AUTH:
|
|
||||||
revokeMethod = revokeAzureAuth;
|
|
||||||
Component = ViewIdentityAzureAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.OCI_AUTH:
|
|
||||||
revokeMethod = revokeOciAuth;
|
|
||||||
Component = ViewIdentityOciAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.ALICLOUD_AUTH:
|
|
||||||
revokeMethod = revokeAliCloudAuth;
|
|
||||||
Component = ViewIdentityAliCloudAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.OIDC_AUTH:
|
|
||||||
revokeMethod = revokeOidcAuth;
|
|
||||||
Component = ViewIdentityOidcAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.JWT_AUTH:
|
|
||||||
revokeMethod = revokeJwtAuth;
|
|
||||||
Component = ViewIdentityJwtAuthContent;
|
|
||||||
break;
|
|
||||||
case IdentityAuthMethod.LDAP_AUTH:
|
|
||||||
revokeMethod = revokeLdapAuth;
|
|
||||||
Component = ViewIdentityLdapAuthContent;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`Unhandled Auth Method: ${authMethod}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeleteAuthMethod = async () => {
|
|
||||||
await revokeMethod({
|
|
||||||
identityId,
|
|
||||||
...(projectId
|
|
||||||
? { projectId }
|
|
||||||
: {
|
|
||||||
organizationId: orgId
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
createNotification({
|
|
||||||
text: "Successfully removed auth method",
|
|
||||||
type: "success"
|
|
||||||
});
|
|
||||||
handlePopUpToggle("revokeAuthMethod", false);
|
|
||||||
onDeleteAuthMethod();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Component
|
|
||||||
identityId={identityId}
|
|
||||||
onDelete={handleDelete}
|
|
||||||
onResetAllLockouts={onResetAllLockouts}
|
|
||||||
popUp={popUp}
|
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
|
||||||
lockedOut={lockedOut}
|
|
||||||
/>
|
|
||||||
<DeleteActionModal
|
|
||||||
isOpen={popUp?.revokeAuthMethod?.isOpen}
|
|
||||||
title={`Are you sure you want to remove ${identityAuthToNameMap[authMethod]} on this identity?`}
|
|
||||||
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
|
|
||||||
deleteKey="confirm"
|
|
||||||
buttonText="Remove"
|
|
||||||
onDeleteApproved={handleDeleteAuthMethod}
|
|
||||||
/>
|
|
||||||
<UpgradePlanModal
|
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
|
||||||
text={`Your current plan does not include access to ${popUp.upgradePlan.data?.featureName}. To unlock this feature, please upgrade to Infisical ${popUp.upgradePlan.data?.isEnterpriseFeature ? "Enterprise" : "Pro"} plan.`}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ViewIdentityAuthModal = ({
|
|
||||||
isOpen,
|
|
||||||
onOpenChange,
|
|
||||||
authMethod,
|
|
||||||
identityId,
|
|
||||||
lockedOut,
|
|
||||||
onResetAllLockouts
|
|
||||||
}: Omit<Props, "onDeleteAuthMethod">) => {
|
|
||||||
if (!identityId || !authMethod) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
|
||||||
<ModalContent className="max-w-2xl" title={identityAuthToNameMap[authMethod]}>
|
|
||||||
<Content
|
|
||||||
identityId={identityId}
|
|
||||||
authMethod={authMethod}
|
|
||||||
lockedOut={lockedOut}
|
|
||||||
onDeleteAuthMethod={() => onOpenChange(false)}
|
|
||||||
onResetAllLockouts={() => onResetAllLockouts()}
|
|
||||||
/>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
export * from "./ViewIdentityAuthModal";
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
|
||||||
|
|
||||||
export type ViewAuthMethodProps = {
|
|
||||||
identityId: string;
|
|
||||||
onDelete: () => void;
|
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan", "identityAuthMethod"]>) => void;
|
|
||||||
handlePopUpToggle: (
|
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
|
||||||
state?: boolean
|
|
||||||
) => void;
|
|
||||||
popUp: UsePopUpState<["revokeAuthMethod", "upgradePlan", "identityAuthMethod"]>;
|
|
||||||
lockedOut: boolean;
|
|
||||||
onResetAllLockouts: () => void;
|
|
||||||
};
|
|
||||||
@@ -179,14 +179,13 @@ const Page = () => {
|
|||||||
search={{
|
search={{
|
||||||
selectedTab: ProjectAccessControlTabs.Identities
|
selectedTab: ProjectAccessControlTabs.Identities
|
||||||
}}
|
}}
|
||||||
className="mb-3 flex w-fit items-center gap-x-1 text-sm text-mineshaft-400 transition duration-100 hover:text-mineshaft-400/80"
|
className="mb-4 flex w-fit items-center gap-x-1 text-sm text-mineshaft-400 transition duration-100 hover:text-mineshaft-400/80"
|
||||||
>
|
>
|
||||||
<ChevronLeftIcon size={16} />
|
<ChevronLeftIcon size={16} />
|
||||||
Project Machine Identities
|
Project Machine Identities
|
||||||
</Link>
|
</Link>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
scope={currentProject.type}
|
scope={currentProject.type}
|
||||||
className="mb-20"
|
|
||||||
description={`Configure and manage${isProjectIdentity ? " machine identity and " : " "}project access control`}
|
description={`Configure and manage${isProjectIdentity ? " machine identity and " : " "}project access control`}
|
||||||
title={identityMembershipDetails.identity.name}
|
title={identityMembershipDetails.identity.name}
|
||||||
>
|
>
|
||||||
@@ -256,14 +255,14 @@ const Page = () => {
|
|||||||
</UnstableDropdownMenuContent>
|
</UnstableDropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<div className="flex flex-col gap-20 lg:flex-row">
|
<div className="flex flex-col gap-5 lg:flex-row">
|
||||||
<ProjectIdentityDetailsSection
|
<ProjectIdentityDetailsSection
|
||||||
identity={identity || { ...identityMembershipDetails?.identity, projectId: "" }}
|
identity={identity || { ...identityMembershipDetails?.identity, projectId: "" }}
|
||||||
isOrgIdentity={!isProjectIdentity}
|
isOrgIdentity={!isProjectIdentity}
|
||||||
membership={identityMembershipDetails!}
|
membership={identityMembershipDetails!}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex flex-1 flex-col gap-y-20">
|
<div className="flex flex-1 flex-col gap-y-5">
|
||||||
{identity ? (
|
{identity ? (
|
||||||
<ProjectIdentityAuthenticationSection
|
<ProjectIdentityAuthenticationSection
|
||||||
identity={identity}
|
identity={identity}
|
||||||
|
|||||||
+4
-2
@@ -81,7 +81,9 @@ export const IdentityProjectAdditionalPrivilegeSection = ({ identityMembershipDe
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UnstableCard>
|
<UnstableCard>
|
||||||
<UnstableCardHeader className="border-b">
|
<UnstableCardHeader
|
||||||
|
// className="border-b"
|
||||||
|
>
|
||||||
<UnstableCardTitle>Project Additional Privileges</UnstableCardTitle>
|
<UnstableCardTitle>Project Additional Privileges</UnstableCardTitle>
|
||||||
<UnstableCardDescription>
|
<UnstableCardDescription>
|
||||||
Assign one-off policies to this machine identity
|
Assign one-off policies to this machine identity
|
||||||
@@ -96,7 +98,7 @@ export const IdentityProjectAdditionalPrivilegeSection = ({ identityMembershipDe
|
|||||||
>
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<UnstableButton
|
<UnstableButton
|
||||||
variant="project"
|
variant="outline"
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handlePopUpOpen("modifyPrivilege");
|
handlePopUpOpen("modifyPrivilege");
|
||||||
|
|||||||
+4
-2
@@ -96,7 +96,9 @@ export const IdentityRoleDetailsSection = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UnstableCard>
|
<UnstableCard>
|
||||||
<UnstableCardHeader className="border-b">
|
<UnstableCardHeader
|
||||||
|
// className="border-b"
|
||||||
|
>
|
||||||
<UnstableCardTitle>Project Roles</UnstableCardTitle>
|
<UnstableCardTitle>Project Roles</UnstableCardTitle>
|
||||||
<UnstableCardDescription>
|
<UnstableCardDescription>
|
||||||
Manage roles assigned to this machine identity
|
Manage roles assigned to this machine identity
|
||||||
@@ -112,7 +114,7 @@ export const IdentityRoleDetailsSection = ({
|
|||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<UnstableButton
|
<UnstableButton
|
||||||
size="xs"
|
size="xs"
|
||||||
variant="project"
|
variant="outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handlePopUpOpen("modifyRole");
|
handlePopUpOpen("modifyRole");
|
||||||
}}
|
}}
|
||||||
|
|||||||
+82
-61
@@ -1,11 +1,11 @@
|
|||||||
import { subject } from "@casl/ability";
|
import { subject } from "@casl/ability";
|
||||||
import { EllipsisIcon, LockIcon, PlusIcon } from "lucide-react";
|
import { PlusIcon } from "lucide-react";
|
||||||
|
|
||||||
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||||
import { Tooltip } from "@app/components/v2";
|
import { DeleteActionModal } from "@app/components/v2";
|
||||||
import {
|
import {
|
||||||
Badge,
|
|
||||||
UnstableButton,
|
UnstableButton,
|
||||||
UnstableCard,
|
UnstableCard,
|
||||||
UnstableCardAction,
|
UnstableCardAction,
|
||||||
@@ -17,20 +17,29 @@ import {
|
|||||||
UnstableEmptyContent,
|
UnstableEmptyContent,
|
||||||
UnstableEmptyDescription,
|
UnstableEmptyDescription,
|
||||||
UnstableEmptyHeader,
|
UnstableEmptyHeader,
|
||||||
UnstableEmptyTitle,
|
UnstableEmptyTitle
|
||||||
UnstableIconButton,
|
|
||||||
UnstableTable,
|
|
||||||
UnstableTableBody,
|
|
||||||
UnstableTableCell,
|
|
||||||
UnstableTableHead,
|
|
||||||
UnstableTableHeader,
|
|
||||||
UnstableTableRow
|
|
||||||
} from "@app/components/v3";
|
} from "@app/components/v3";
|
||||||
import { ProjectPermissionIdentityActions, ProjectPermissionSub } from "@app/context";
|
import { ProjectPermissionIdentityActions, ProjectPermissionSub } from "@app/context";
|
||||||
import { IdentityAuthMethod, identityAuthToNameMap, TProjectIdentity } from "@app/hooks/api";
|
import {
|
||||||
|
IdentityAuthMethod,
|
||||||
|
identityAuthToNameMap,
|
||||||
|
TProjectIdentity,
|
||||||
|
useDeleteIdentityAliCloudAuth,
|
||||||
|
useDeleteIdentityAwsAuth,
|
||||||
|
useDeleteIdentityAzureAuth,
|
||||||
|
useDeleteIdentityGcpAuth,
|
||||||
|
useDeleteIdentityJwtAuth,
|
||||||
|
useDeleteIdentityKubernetesAuth,
|
||||||
|
useDeleteIdentityLdapAuth,
|
||||||
|
useDeleteIdentityOciAuth,
|
||||||
|
useDeleteIdentityOidcAuth,
|
||||||
|
useDeleteIdentityTlsCertAuth,
|
||||||
|
useDeleteIdentityTokenAuth,
|
||||||
|
useDeleteIdentityUniversalAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
import { IdentityAuthMethodModal } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
import { IdentityAuthMethodModal } from "@app/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
||||||
import { ViewIdentityAuthModal } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal";
|
import { ViewIdentityAuth } from "@app/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuth";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
identity: TProjectIdentity;
|
identity: TProjectIdentity;
|
||||||
@@ -39,17 +48,58 @@ type Props = {
|
|||||||
|
|
||||||
export const ProjectIdentityAuthenticationSection = ({ identity, refetchIdentity }: Props) => {
|
export const ProjectIdentityAuthenticationSection = ({ identity, refetchIdentity }: Props) => {
|
||||||
const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp([
|
const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp([
|
||||||
"viewAuthMethod",
|
|
||||||
"identityAuthMethod",
|
"identityAuthMethod",
|
||||||
"upgradePlan"
|
"upgradePlan",
|
||||||
|
"revokeAuthMethod"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const hasAuthMethods = Boolean(identity.authMethods.length);
|
const hasAuthMethods = Boolean(identity.authMethods.length);
|
||||||
|
|
||||||
|
const { mutateAsync: revokeUniversalAuth } = useDeleteIdentityUniversalAuth();
|
||||||
|
const { mutateAsync: revokeTokenAuth } = useDeleteIdentityTokenAuth();
|
||||||
|
const { mutateAsync: revokeKubernetesAuth } = useDeleteIdentityKubernetesAuth();
|
||||||
|
const { mutateAsync: revokeGcpAuth } = useDeleteIdentityGcpAuth();
|
||||||
|
const { mutateAsync: revokeTlsCertAuth } = useDeleteIdentityTlsCertAuth();
|
||||||
|
const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth();
|
||||||
|
const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth();
|
||||||
|
const { mutateAsync: revokeAliCloudAuth } = useDeleteIdentityAliCloudAuth();
|
||||||
|
const { mutateAsync: revokeOciAuth } = useDeleteIdentityOciAuth();
|
||||||
|
const { mutateAsync: revokeOidcAuth } = useDeleteIdentityOidcAuth();
|
||||||
|
const { mutateAsync: revokeJwtAuth } = useDeleteIdentityJwtAuth();
|
||||||
|
const { mutateAsync: revokeLdapAuth } = useDeleteIdentityLdapAuth();
|
||||||
|
|
||||||
|
const RemoveAuthMap = {
|
||||||
|
[IdentityAuthMethod.KUBERNETES_AUTH]: revokeKubernetesAuth,
|
||||||
|
[IdentityAuthMethod.GCP_AUTH]: revokeGcpAuth,
|
||||||
|
[IdentityAuthMethod.TLS_CERT_AUTH]: revokeTlsCertAuth,
|
||||||
|
[IdentityAuthMethod.AWS_AUTH]: revokeAwsAuth,
|
||||||
|
[IdentityAuthMethod.AZURE_AUTH]: revokeAzureAuth,
|
||||||
|
[IdentityAuthMethod.ALICLOUD_AUTH]: revokeAliCloudAuth,
|
||||||
|
[IdentityAuthMethod.UNIVERSAL_AUTH]: revokeUniversalAuth,
|
||||||
|
[IdentityAuthMethod.TOKEN_AUTH]: revokeTokenAuth,
|
||||||
|
[IdentityAuthMethod.OCI_AUTH]: revokeOciAuth,
|
||||||
|
[IdentityAuthMethod.OIDC_AUTH]: revokeOidcAuth,
|
||||||
|
[IdentityAuthMethod.JWT_AUTH]: revokeJwtAuth,
|
||||||
|
[IdentityAuthMethod.LDAP_AUTH]: revokeLdapAuth
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteAuthMethod = async (authMethod: IdentityAuthMethod) => {
|
||||||
|
await RemoveAuthMap[authMethod]({
|
||||||
|
identityId: identity.id,
|
||||||
|
projectId: identity.projectId!
|
||||||
|
});
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Successfully removed auth method",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
handlePopUpToggle("revokeAuthMethod", false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UnstableCard>
|
<UnstableCard>
|
||||||
<UnstableCardHeader className="border-b">
|
<UnstableCardHeader>
|
||||||
<UnstableCardTitle>Authentication</UnstableCardTitle>
|
<UnstableCardTitle>Authentication</UnstableCardTitle>
|
||||||
<UnstableCardDescription>Configure authentication methods</UnstableCardDescription>
|
<UnstableCardDescription>Configure authentication methods</UnstableCardDescription>
|
||||||
{hasAuthMethods &&
|
{hasAuthMethods &&
|
||||||
@@ -65,7 +115,7 @@ export const ProjectIdentityAuthenticationSection = ({ identity, refetchIdentity
|
|||||||
>
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<UnstableButton
|
<UnstableButton
|
||||||
variant="project"
|
variant="outline"
|
||||||
isFullWidth
|
isFullWidth
|
||||||
size="xs"
|
size="xs"
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
@@ -87,43 +137,12 @@ export const ProjectIdentityAuthenticationSection = ({ identity, refetchIdentity
|
|||||||
</UnstableCardHeader>
|
</UnstableCardHeader>
|
||||||
<UnstableCardContent>
|
<UnstableCardContent>
|
||||||
{identity.authMethods.length > 0 ? (
|
{identity.authMethods.length > 0 ? (
|
||||||
<UnstableTable>
|
<ViewIdentityAuth
|
||||||
<UnstableTableHeader>
|
authMethods={identity.authMethods}
|
||||||
<UnstableTableHead className="w-full">Method</UnstableTableHead>
|
identityId={identity.id}
|
||||||
<UnstableTableHead className="w-5" />
|
onResetAllLockouts={refetchIdentity}
|
||||||
</UnstableTableHeader>
|
activeLockoutAuthMethods={identity.activeLockoutAuthMethods}
|
||||||
<UnstableTableBody>
|
/>
|
||||||
{identity.authMethods.map((authMethod) => (
|
|
||||||
<UnstableTableRow
|
|
||||||
key={authMethod}
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() =>
|
|
||||||
handlePopUpOpen("viewAuthMethod", {
|
|
||||||
authMethod,
|
|
||||||
lockedOut: identity.activeLockoutAuthMethods?.includes(authMethod) ?? false,
|
|
||||||
refetchIdentity
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<UnstableTableCell>{identityAuthToNameMap[authMethod]}</UnstableTableCell>
|
|
||||||
<UnstableTableCell>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
{identity.activeLockoutAuthMethods?.includes(authMethod) && (
|
|
||||||
<Tooltip content="Auth method has active lockouts">
|
|
||||||
<Badge isSquare variant="danger">
|
|
||||||
<LockIcon />
|
|
||||||
</Badge>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
<UnstableIconButton variant="ghost" size="xs">
|
|
||||||
<EllipsisIcon />
|
|
||||||
</UnstableIconButton>
|
|
||||||
</div>
|
|
||||||
</UnstableTableCell>
|
|
||||||
</UnstableTableRow>
|
|
||||||
))}
|
|
||||||
</UnstableTableBody>
|
|
||||||
</UnstableTable>
|
|
||||||
) : (
|
) : (
|
||||||
<UnstableEmpty className="rounded-sm border bg-mineshaft-800/50">
|
<UnstableEmpty className="rounded-sm border bg-mineshaft-800/50">
|
||||||
<UnstableEmptyHeader>
|
<UnstableEmptyHeader>
|
||||||
@@ -175,13 +194,15 @@ export const ProjectIdentityAuthenticationSection = ({ identity, refetchIdentity
|
|||||||
text={(popUp.upgradePlan?.data as { description: string })?.description}
|
text={(popUp.upgradePlan?.data as { description: string })?.description}
|
||||||
isEnterpriseFeature={popUp.upgradePlan.data?.isEnterpriseFeature}
|
isEnterpriseFeature={popUp.upgradePlan.data?.isEnterpriseFeature}
|
||||||
/>
|
/>
|
||||||
<ViewIdentityAuthModal
|
<DeleteActionModal
|
||||||
isOpen={popUp.viewAuthMethod.isOpen}
|
isOpen={popUp?.revokeAuthMethod?.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("viewAuthMethod", isOpen)}
|
title={`Are you sure you want to remove ${popUp?.revokeAuthMethod?.data ? identityAuthToNameMap[popUp.revokeAuthMethod.data as IdentityAuthMethod] : "this auth method"} on this identity?`}
|
||||||
authMethod={popUp.viewAuthMethod.data?.authMethod}
|
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
|
||||||
lockedOut={popUp.viewAuthMethod.data?.lockedOut || false}
|
deleteKey="confirm"
|
||||||
identityId={identity.id}
|
buttonText="Remove"
|
||||||
onResetAllLockouts={popUp.viewAuthMethod.data?.refetchIdentity}
|
onDeleteApproved={() =>
|
||||||
|
handleDeleteAuthMethod(popUp.revokeAuthMethod.data as IdentityAuthMethod)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
+15
-10
@@ -12,7 +12,6 @@ import {
|
|||||||
DetailValue,
|
DetailValue,
|
||||||
OrgIcon,
|
OrgIcon,
|
||||||
ProjectIcon,
|
ProjectIcon,
|
||||||
UnstableButton,
|
|
||||||
UnstableButtonGroup,
|
UnstableButtonGroup,
|
||||||
UnstableCard,
|
UnstableCard,
|
||||||
UnstableCardAction,
|
UnstableCardAction,
|
||||||
@@ -44,8 +43,10 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<UnstableCard className="w-full max-w-84">
|
<UnstableCard className="w-full max-w-[22rem]">
|
||||||
<UnstableCardHeader className="border-b">
|
<UnstableCardHeader
|
||||||
|
// className="border-b"
|
||||||
|
>
|
||||||
<UnstableCardTitle>Details</UnstableCardTitle>
|
<UnstableCardTitle>Details</UnstableCardTitle>
|
||||||
<UnstableCardDescription>Machine identity details</UnstableCardDescription>
|
<UnstableCardDescription>Machine identity details</UnstableCardDescription>
|
||||||
{!isOrgIdentity && (
|
{!isOrgIdentity && (
|
||||||
@@ -57,17 +58,16 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<UnstableButton
|
<UnstableIconButton
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handlePopUpOpen("editIdentity");
|
handlePopUpOpen("editIdentity");
|
||||||
}}
|
}}
|
||||||
size="xs"
|
size="xs"
|
||||||
variant="project"
|
variant="outline"
|
||||||
>
|
>
|
||||||
<PencilIcon />
|
<PencilIcon />
|
||||||
Edit Details
|
</UnstableIconButton>
|
||||||
</UnstableButton>
|
|
||||||
)}
|
)}
|
||||||
</ProjectPermissionCan>
|
</ProjectPermissionCan>
|
||||||
</UnstableCardAction>
|
</UnstableCardAction>
|
||||||
@@ -92,6 +92,7 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="xs"
|
size="xs"
|
||||||
>
|
>
|
||||||
|
{/* TODO(scott): color this should be a button variant */}
|
||||||
{isCopyingId ? <CheckIcon /> : <ClipboardListIcon className="text-label" />}
|
{isCopyingId ? <CheckIcon /> : <ClipboardListIcon className="text-label" />}
|
||||||
</UnstableIconButton>
|
</UnstableIconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -118,9 +119,13 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
|||||||
<DetailValue className="flex flex-wrap gap-2">
|
<DetailValue className="flex flex-wrap gap-2">
|
||||||
{identity?.metadata?.length ? (
|
{identity?.metadata?.length ? (
|
||||||
identity.metadata?.map((el) => (
|
identity.metadata?.map((el) => (
|
||||||
<UnstableButtonGroup key={el.id}>
|
<UnstableButtonGroup className="min-w-0" key={el.id}>
|
||||||
<Badge>{el.key}</Badge>
|
<Badge isTruncatable>
|
||||||
<Badge variant="outline">{el.value}</Badge>
|
<span>{el.key}</span>
|
||||||
|
</Badge>
|
||||||
|
<Badge variant="outline" isTruncatable>
|
||||||
|
<span>{el.value}</span>
|
||||||
|
</Badge>
|
||||||
</UnstableButtonGroup>
|
</UnstableButtonGroup>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user