mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 19:28:16 +00:00
feat: updated ui based on feedback
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { TProjectAssumePrivilegesDTO } from "./types";
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
|
import { TProjectAssumePrivilegesDTO } from "./types";
|
||||||
|
|
||||||
export const useAssumeProjectPrivileges = () =>
|
export const useAssumeProjectPrivileges = () =>
|
||||||
useMutation({
|
useMutation({
|
||||||
mutationFn: async ({ projectId, actorId, actorType }: TProjectAssumePrivilegesDTO) => {
|
mutationFn: async ({ projectId, actorId, actorType }: TProjectAssumePrivilegesDTO) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export * from "./accessApproval";
|
export * from "./accessApproval";
|
||||||
export * from "./assumePrivileges";
|
|
||||||
export * from "./admin";
|
export * from "./admin";
|
||||||
export * from "./apiKeys";
|
export * from "./apiKeys";
|
||||||
|
export * from "./assumePrivileges";
|
||||||
export * from "./auditLogs";
|
export * from "./auditLogs";
|
||||||
export * from "./auditLogStreams";
|
export * from "./auditLogStreams";
|
||||||
export * from "./auth";
|
export * from "./auth";
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { ProjectPermissionSet } from "@app/context/ProjectPermissionContext/type
|
|||||||
import { groupBy } from "@app/lib/fn/array";
|
import { groupBy } from "@app/lib/fn/array";
|
||||||
import { omit } from "@app/lib/fn/object";
|
import { omit } from "@app/lib/fn/object";
|
||||||
|
|
||||||
|
import { ActorType } from "../auditLogs/enums";
|
||||||
import { OrgUser, TProjectMembership } from "../users/types";
|
import { OrgUser, TProjectMembership } from "../users/types";
|
||||||
import {
|
import {
|
||||||
TGetUserOrgPermissionsDTO,
|
TGetUserOrgPermissionsDTO,
|
||||||
@@ -18,7 +19,6 @@ import {
|
|||||||
TPermission,
|
TPermission,
|
||||||
TProjectRole
|
TProjectRole
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { ActorType } from "../auditLogs/enums";
|
|
||||||
|
|
||||||
const $glob: FieldInstruction<string> = {
|
const $glob: FieldInstruction<string> = {
|
||||||
type: "field",
|
type: "field",
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import {
|
|||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||||
|
|
||||||
import { ProjectSelect } from "./components/ProjectSelect";
|
|
||||||
import { AssumePrivilegeModeBanner } from "./components/AssumePrivilegeModeBanner";
|
import { AssumePrivilegeModeBanner } from "./components/AssumePrivilegeModeBanner";
|
||||||
|
import { ProjectSelect } from "./components/ProjectSelect";
|
||||||
|
|
||||||
// This is a generic layout shared by all types of projects.
|
// This is a generic layout shared by all types of projects.
|
||||||
// If the product layout differs significantly, create a new layout as needed.
|
// If the product layout differs significantly, create a new layout as needed.
|
||||||
@@ -64,6 +64,7 @@ export const ProjectLayout = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="dark hidden h-screen w-full flex-col overflow-x-hidden md:flex">
|
<div className="dark hidden h-screen w-full flex-col overflow-x-hidden md:flex">
|
||||||
|
{impersonation && <AssumePrivilegeModeBanner />}
|
||||||
<div className="flex flex-grow flex-col overflow-y-hidden md:flex-row">
|
<div className="flex flex-grow flex-col overflow-y-hidden md:flex-row">
|
||||||
<motion.div
|
<motion.div
|
||||||
key="menu-project-items"
|
key="menu-project-items"
|
||||||
@@ -269,7 +270,6 @@ export const ProjectLayout = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{impersonation && <AssumePrivilegeModeBanner />}
|
|
||||||
<div className="z-[200] flex h-screen w-screen flex-col items-center justify-center bg-bunker-800 md:hidden">
|
<div className="z-[200] flex h-screen w-screen flex-col items-center justify-center bg-bunker-800 md:hidden">
|
||||||
<FontAwesomeIcon icon={faMobile} className="mb-8 text-7xl text-gray-300" />
|
<FontAwesomeIcon icon={faMobile} className="mb-8 text-7xl text-gray-300" />
|
||||||
<p className="max-w-sm px-6 text-center text-lg text-gray-200">
|
<p className="max-w-sm px-6 text-center text-lg text-gray-200">
|
||||||
|
|||||||
+30
-49
@@ -1,7 +1,7 @@
|
|||||||
import { faIdCard, faUser } from "@fortawesome/free-solid-svg-icons";
|
import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import { Button, HoverCard, HoverCardContent, HoverCardTrigger } from "@app/components/v2";
|
import { Button } from "@app/components/v2";
|
||||||
import { useProjectPermission, useWorkspace } from "@app/context";
|
import { useProjectPermission, useWorkspace } from "@app/context";
|
||||||
import { useRemoveAssumeProjectPrivilege } from "@app/hooks/api";
|
import { useRemoveAssumeProjectPrivilege } from "@app/hooks/api";
|
||||||
import { ActorType } from "@app/hooks/api/auditLogs/enums";
|
import { ActorType } from "@app/hooks/api/auditLogs/enums";
|
||||||
@@ -14,55 +14,36 @@ export const AssumePrivilegeModeBanner = () => {
|
|||||||
if (!impersonation) return null;
|
if (!impersonation) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed bottom-4 right-4 z-50 flex items-center gap-2 rounded border border-mineshaft-600 bg-mineshaft-800 p-2 shadow">
|
<div className="z-10 -mx-4 flex items-center justify-center gap-2 rounded border border-mineshaft-600 bg-primary-400 p-2 text-mineshaft-800 shadow">
|
||||||
<HoverCard openDelay={200}>
|
<div>
|
||||||
<HoverCardTrigger asChild>
|
<FontAwesomeIcon icon={faInfoCircle} className="mr-2" />
|
||||||
<Button
|
You are currently viewing the project with privileges of{" "}
|
||||||
leftIcon={
|
<b>
|
||||||
<FontAwesomeIcon
|
{impersonation?.actorType === ActorType.IDENTITY ? "identity" : "user"}{" "}
|
||||||
icon={impersonation?.actorType === ActorType.USER ? faUser : faIdCard}
|
{impersonation?.actorName}
|
||||||
/>
|
</b>
|
||||||
}
|
</div>
|
||||||
onClick={() => {
|
<div>
|
||||||
exitAssumePrivilegeMode.mutate(
|
<Button
|
||||||
{
|
size="xs"
|
||||||
projectId: currentWorkspace.id
|
variant="outline_bg"
|
||||||
},
|
className="hover:bg-mineshaft-500"
|
||||||
{
|
onClick={() => {
|
||||||
onSuccess: () => {
|
exitAssumePrivilegeMode.mutate(
|
||||||
window.location.href = `/${currentWorkspace.type}/${currentWorkspace.id}/overview`;
|
{
|
||||||
}
|
projectId: currentWorkspace.id
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
window.location.href = `/${currentWorkspace.type}/${currentWorkspace.id}/overview`;
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
}}
|
);
|
||||||
>
|
}}
|
||||||
Exit Assume Privilege Mode
|
|
||||||
</Button>
|
|
||||||
</HoverCardTrigger>
|
|
||||||
<HoverCardContent
|
|
||||||
className="bg-mineshaft-800 pt-4"
|
|
||||||
sideOffset={10}
|
|
||||||
style={{ width: "360px" }}
|
|
||||||
>
|
>
|
||||||
<div className="flex gap-2">
|
Click to exit
|
||||||
<div className="flex px-2 pt-2">
|
</Button>
|
||||||
<FontAwesomeIcon
|
</div>
|
||||||
className="text-3xl text-mineshaft-400"
|
|
||||||
icon={impersonation?.actorType === ActorType.USER ? faUser : faIdCard}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-4">
|
|
||||||
<div className="text-lg">{impersonation?.actorName}</div>
|
|
||||||
{impersonation?.actorEmail && (
|
|
||||||
<div className="text-xs">{impersonation?.actorEmail}</div>
|
|
||||||
)}
|
|
||||||
{impersonation?.actorType === ActorType.IDENTITY && (
|
|
||||||
<div className="text-xs">{impersonation?.actorId}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</HoverCardContent>
|
|
||||||
</HoverCard>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ const Page = () => {
|
|||||||
a={ProjectPermissionSub.Identity}
|
a={ProjectPermissionSub.Identity}
|
||||||
renderTooltip
|
renderTooltip
|
||||||
allowedLabel="Assume or impersonate privileges of the user"
|
allowedLabel="Assume or impersonate privileges of the user"
|
||||||
|
passThrough={false}
|
||||||
>
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Button
|
<Button
|
||||||
@@ -147,7 +148,7 @@ const Page = () => {
|
|||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
onClick={() => handlePopUpOpen("assumePrivileges")}
|
onClick={() => handlePopUpOpen("assumePrivileges")}
|
||||||
>
|
>
|
||||||
Impersonate Identity
|
Test Privileges
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</ProjectPermissionCan>
|
</ProjectPermissionCan>
|
||||||
@@ -191,7 +192,7 @@ const Page = () => {
|
|||||||
<ConfirmActionModal
|
<ConfirmActionModal
|
||||||
isOpen={popUp.assumePrivileges.isOpen}
|
isOpen={popUp.assumePrivileges.isOpen}
|
||||||
confirmKey="assume"
|
confirmKey="assume"
|
||||||
title="Do you want to impersonate privileges of this identity?"
|
title="Do you want to assume privileges of this identity?"
|
||||||
subTitle="This will set your privileges to those of the identity for the next hour."
|
subTitle="This will set your privileges to those of the identity for the next hour."
|
||||||
onChange={(isOpen) => handlePopUpToggle("assumePrivileges", isOpen)}
|
onChange={(isOpen) => handlePopUpToggle("assumePrivileges", isOpen)}
|
||||||
onConfirmed={handleAssumePrivileges}
|
onConfirmed={handleAssumePrivileges}
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ export const Page = () => {
|
|||||||
a={ProjectPermissionSub.Member}
|
a={ProjectPermissionSub.Member}
|
||||||
renderTooltip
|
renderTooltip
|
||||||
allowedLabel="Assume or impersonate privileges of the user"
|
allowedLabel="Assume or impersonate privileges of the user"
|
||||||
|
passThrough={false}
|
||||||
>
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Button
|
<Button
|
||||||
@@ -141,7 +142,7 @@ export const Page = () => {
|
|||||||
handlePopUpOpen("assumePrivileges", { userId: membershipDetails?.user?.id })
|
handlePopUpOpen("assumePrivileges", { userId: membershipDetails?.user?.id })
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Impersonate User
|
Test Privileges
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</ProjectPermissionCan>
|
</ProjectPermissionCan>
|
||||||
@@ -187,7 +188,7 @@ export const Page = () => {
|
|||||||
<ConfirmActionModal
|
<ConfirmActionModal
|
||||||
isOpen={popUp.assumePrivileges.isOpen}
|
isOpen={popUp.assumePrivileges.isOpen}
|
||||||
confirmKey="assume"
|
confirmKey="assume"
|
||||||
title="Do you want to impersonate privileges of this user?"
|
title="Do you want to assume privileges of this user?"
|
||||||
subTitle="This will set your privileges to those of the user for the next hour."
|
subTitle="This will set your privileges to those of the user for the next hour."
|
||||||
onChange={(isOpen) => handlePopUpToggle("assumePrivileges", isOpen)}
|
onChange={(isOpen) => handlePopUpToggle("assumePrivileges", isOpen)}
|
||||||
onConfirmed={handleAssumePrivileges}
|
onConfirmed={handleAssumePrivileges}
|
||||||
|
|||||||
+4
-2
@@ -92,7 +92,8 @@ const MemberPolicyActionSchema = z.object({
|
|||||||
[ProjectPermissionMemberActions.Create]: z.boolean().optional(),
|
[ProjectPermissionMemberActions.Create]: z.boolean().optional(),
|
||||||
[ProjectPermissionMemberActions.Edit]: z.boolean().optional(),
|
[ProjectPermissionMemberActions.Edit]: z.boolean().optional(),
|
||||||
[ProjectPermissionMemberActions.Delete]: z.boolean().optional(),
|
[ProjectPermissionMemberActions.Delete]: z.boolean().optional(),
|
||||||
[ProjectPermissionMemberActions.GrantPrivileges]: z.boolean().optional()
|
[ProjectPermissionMemberActions.GrantPrivileges]: z.boolean().optional(),
|
||||||
|
[ProjectPermissionMemberActions.AssumePrivileges]: z.boolean().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
const IdentityPolicyActionSchema = z.object({
|
const IdentityPolicyActionSchema = z.object({
|
||||||
@@ -100,7 +101,8 @@ const IdentityPolicyActionSchema = z.object({
|
|||||||
[ProjectPermissionIdentityActions.Create]: z.boolean().optional(),
|
[ProjectPermissionIdentityActions.Create]: z.boolean().optional(),
|
||||||
[ProjectPermissionIdentityActions.Edit]: z.boolean().optional(),
|
[ProjectPermissionIdentityActions.Edit]: z.boolean().optional(),
|
||||||
[ProjectPermissionIdentityActions.Delete]: z.boolean().optional(),
|
[ProjectPermissionIdentityActions.Delete]: z.boolean().optional(),
|
||||||
[ProjectPermissionIdentityActions.GrantPrivileges]: z.boolean().optional()
|
[ProjectPermissionIdentityActions.GrantPrivileges]: z.boolean().optional(),
|
||||||
|
[ProjectPermissionIdentityActions.AssumePrivileges]: z.boolean().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
const GroupPolicyActionSchema = z.object({
|
const GroupPolicyActionSchema = z.object({
|
||||||
|
|||||||
Reference in New Issue
Block a user