diff --git a/frontend/src/hooks/api/secrets/queries.tsx b/frontend/src/hooks/api/secrets/queries.tsx index 4b95579c2..b92e6e35b 100644 --- a/frontend/src/hooks/api/secrets/queries.tsx +++ b/frontend/src/hooks/api/secrets/queries.tsx @@ -10,6 +10,7 @@ import { useToggle } from "@app/hooks/useToggle"; import { ERROR_NOT_ALLOWED_READ_SECRETS } from "./constants"; import { GetSecretVersionsDTO, + SecretAccessListEntry, SecretType, SecretV3Raw, SecretV3RawResponse, @@ -18,6 +19,7 @@ import { TGetProjectSecretsAllEnvDTO, TGetProjectSecretsDTO, TGetProjectSecretsKey, + TGetSecretAccessListDTO, TGetSecretReferenceTreeDTO, TSecretReferenceTraceNode } from "./types"; @@ -27,6 +29,13 @@ export const secretKeys = { getProjectSecret: ({ workspaceId, environment, secretPath }: TGetProjectSecretsKey) => [{ workspaceId, environment, secretPath }, "secrets"] as const, getSecretVersion: (secretId: string) => [{ secretId }, "secret-versions"] as const, + getSecretAccessList: ({ + workspaceId, + environment, + secretPath, + secretKey + }: TGetSecretAccessListDTO) => + ["secret-access-list", { workspaceId, environment, secretPath, secretKey }] as const, getSecretReferenceTree: (dto: TGetSecretReferenceTreeDTO) => ["secret-reference-tree", dto] }; @@ -231,6 +240,27 @@ export const useGetSecretVersion = (dto: GetSecretVersionsDTO) => }, []) }); +export const useGetSecretAccessList = (dto: TGetSecretAccessListDTO) => + useQuery({ + enabled: Boolean(dto.secretKey), + queryKey: secretKeys.getSecretAccessList(dto), + queryFn: async () => { + const { data } = await apiRequest.get<{ + groups: SecretAccessListEntry[]; + identities: SecretAccessListEntry[]; + users: SecretAccessListEntry[]; + }>(`/api/v1/secrets/raw/${dto.secretKey}/access-list`, { + params: { + workspaceId: dto.workspaceId, + environment: dto.environment, + secretPath: dto.secretPath + } + }); + + return data; + } + }); + const fetchSecretReferenceTree = async ({ secretPath, projectId, diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index f4dfb07d1..4278f2ce5 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -1,3 +1,5 @@ +import { ProjectPermissionActions } from "@app/context"; + import type { WsTag } from "../tags/types"; export enum SecretType { @@ -123,6 +125,13 @@ export type GetSecretVersionsDTO = { offset: number; }; +export type TGetSecretAccessListDTO = { + workspaceId: string; + environment: string; + secretPath: string; + secretKey: string; +}; + export type TCreateSecretsV3DTO = { secretKey: string; secretValue: string; @@ -228,3 +237,10 @@ export type TSecretReferenceTraceNode = { secretPath: string; children: TSecretReferenceTraceNode[]; }; + +export type SecretAccessListEntry = { + allowedActions: ProjectPermissionActions[]; + id: string; + membershipId: string; + name: string; +}; diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx index 92f01f1d0..8d82d928b 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx @@ -12,6 +12,7 @@ import { } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; +import { Link } from "@tanstack/react-router"; import { format } from "date-fns"; import { createNotification } from "@app/components/notifications"; @@ -34,10 +35,17 @@ import { Tooltip } from "@app/components/v2"; import { InfisicalSecretInput } from "@app/components/v2/InfisicalSecretInput"; -import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission } from "@app/context"; +import { + ProjectPermissionActions, + ProjectPermissionSub, + useProjectPermission, + useWorkspace +} from "@app/context"; import { useToggle } from "@app/hooks"; import { useGetSecretVersion } from "@app/hooks/api"; +import { useGetSecretAccessList } from "@app/hooks/api/secrets/queries"; import { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types"; +import { ProjectType } from "@app/hooks/api/workspace/types"; import { CreateReminderForm } from "./CreateReminderForm"; import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils"; @@ -86,6 +94,7 @@ export const SecretDetailSidebar = ({ }); const { permission } = useProjectPermission(); + const { currentWorkspace } = useWorkspace(); const { fields, append, remove } = useFieldArray({ control, @@ -130,6 +139,13 @@ export const SecretDetailSidebar = ({ secretId: secret?.id }); + const { data: secretAccessList, isPending } = useGetSecretAccessList({ + workspaceId: currentWorkspace.id, + environment, + secretPath, + secretKey + }); + const handleOverrideClick = () => { if (isOverridden) { // override need not be flagged delete if it was never saved in server @@ -482,8 +498,116 @@ export const SecretDetailSidebar = ({ ))} +