mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 10:26:16 +00:00
fix: view secret value (requested changes)
This commit is contained in:
@@ -5,6 +5,7 @@ import { ActionProjectType, SecretFoldersSchema, SecretImportsSchema } from "@ap
|
|||||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import {
|
import {
|
||||||
ProjectPermissionDynamicSecretActions,
|
ProjectPermissionDynamicSecretActions,
|
||||||
|
ProjectPermissionSecretActions,
|
||||||
ProjectPermissionSub
|
ProjectPermissionSub
|
||||||
} from "@app/ee/services/permission/project-permission";
|
} from "@app/ee/services/permission/project-permission";
|
||||||
import { DASHBOARD } from "@app/lib/api-docs";
|
import { DASHBOARD } from "@app/lib/api-docs";
|
||||||
@@ -688,6 +689,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
.optional(),
|
.optional(),
|
||||||
secrets: secretRawSchema
|
secrets: secretRawSchema
|
||||||
.extend({
|
.extend({
|
||||||
|
secretValueHidden: z.boolean(),
|
||||||
secretPath: z.string().optional(),
|
secretPath: z.string().optional(),
|
||||||
secretMetadata: ResourceMetadataSchema.optional(),
|
secretMetadata: ResourceMetadataSchema.optional(),
|
||||||
tags: SanitizedTagSchema.array().optional()
|
tags: SanitizedTagSchema.array().optional()
|
||||||
@@ -734,6 +736,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
|
|
||||||
const secrets = await server.services.secret.getSecretsRawByFolderMappings(
|
const secrets = await server.services.secret.getSecretsRawByFolderMappings(
|
||||||
{
|
{
|
||||||
|
filterByAction: ProjectPermissionSecretActions.DescribeSecret,
|
||||||
projectId,
|
projectId,
|
||||||
folderMappings,
|
folderMappings,
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ export const InfisicalSecretInput = forwardRef<HTMLTextAreaElement, Props>(
|
|||||||
|
|
||||||
const isPopupOpen = Boolean(suggestionSource.isOpen) && isFocused;
|
const isPopupOpen = Boolean(suggestionSource.isOpen) && isFocused;
|
||||||
const { data: secrets } = useGetProjectSecrets({
|
const { data: secrets } = useGetProjectSecrets({
|
||||||
|
viewSecretValue: false,
|
||||||
environment: suggestionSource.environment || "",
|
environment: suggestionSource.environment || "",
|
||||||
secretPath: suggestionSource.secretPath || "",
|
secretPath: suggestionSource.secretPath || "",
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
|||||||
@@ -26,8 +26,13 @@ import {
|
|||||||
|
|
||||||
export const secretKeys = {
|
export const secretKeys = {
|
||||||
// this is also used in secretSnapshot part
|
// this is also used in secretSnapshot part
|
||||||
getProjectSecret: ({ workspaceId, environment, secretPath }: TGetProjectSecretsKey) =>
|
getProjectSecret: ({
|
||||||
[{ workspaceId, environment, secretPath }, "secrets"] as const,
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
secretPath,
|
||||||
|
viewSecretValue
|
||||||
|
}: TGetProjectSecretsKey) =>
|
||||||
|
[{ workspaceId, environment, secretPath, viewSecretValue }, "secrets"] as const,
|
||||||
getSecretVersion: (secretId: string) => [{ secretId }, "secret-versions"] as const,
|
getSecretVersion: (secretId: string) => [{ secretId }, "secret-versions"] as const,
|
||||||
getSecretAccessList: ({
|
getSecretAccessList: ({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@@ -44,13 +49,15 @@ export const fetchProjectSecrets = async ({
|
|||||||
environment,
|
environment,
|
||||||
secretPath,
|
secretPath,
|
||||||
includeImports,
|
includeImports,
|
||||||
expandSecretReferences
|
expandSecretReferences,
|
||||||
|
viewSecretValue
|
||||||
}: TGetProjectSecretsKey) => {
|
}: TGetProjectSecretsKey) => {
|
||||||
const { data } = await apiRequest.get<SecretV3RawResponse>("/api/v3/secrets/raw", {
|
const { data } = await apiRequest.get<SecretV3RawResponse>("/api/v3/secrets/raw", {
|
||||||
params: {
|
params: {
|
||||||
environment,
|
environment,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
secretPath,
|
secretPath,
|
||||||
|
viewSecretValue,
|
||||||
expandSecretReferences,
|
expandSecretReferences,
|
||||||
include_imports: includeImports
|
include_imports: includeImports
|
||||||
}
|
}
|
||||||
@@ -108,6 +115,7 @@ export const useGetProjectSecrets = ({
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
environment,
|
environment,
|
||||||
secretPath,
|
secretPath,
|
||||||
|
viewSecretValue,
|
||||||
options
|
options
|
||||||
}: TGetProjectSecretsDTO & {
|
}: TGetProjectSecretsDTO & {
|
||||||
options?: Omit<
|
options?: Omit<
|
||||||
@@ -124,8 +132,13 @@ export const useGetProjectSecrets = ({
|
|||||||
...options,
|
...options,
|
||||||
// wait for all values to be available
|
// wait for all values to be available
|
||||||
enabled: Boolean(workspaceId && environment) && (options?.enabled ?? true),
|
enabled: Boolean(workspaceId && environment) && (options?.enabled ?? true),
|
||||||
queryKey: secretKeys.getProjectSecret({ workspaceId, environment, secretPath }),
|
queryKey: secretKeys.getProjectSecret({
|
||||||
queryFn: () => fetchProjectSecrets({ workspaceId, environment, secretPath }),
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
secretPath,
|
||||||
|
viewSecretValue
|
||||||
|
}),
|
||||||
|
queryFn: () => fetchProjectSecrets({ workspaceId, environment, secretPath, viewSecretValue }),
|
||||||
select: useCallback(
|
select: useCallback(
|
||||||
(data: Awaited<ReturnType<typeof fetchProjectSecrets>>) => mergePersonalSecrets(data.secrets),
|
(data: Awaited<ReturnType<typeof fetchProjectSecrets>>) => mergePersonalSecrets(data.secrets),
|
||||||
[]
|
[]
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ export type TGetProjectSecretsKey = {
|
|||||||
environment: string;
|
environment: string;
|
||||||
secretPath?: string;
|
secretPath?: string;
|
||||||
includeImports?: boolean;
|
includeImports?: boolean;
|
||||||
|
viewSecretValue?: boolean;
|
||||||
expandSecretReferences?: boolean;
|
expandSecretReferences?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+41
-21
@@ -110,21 +110,31 @@ export const QuickSearchSecretItem = ({
|
|||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
{isSingleEnv ? (
|
{isSingleEnv ? (
|
||||||
<IconButton
|
<Tooltip
|
||||||
size="md"
|
isDisabled={!groupSecret?.secretValueHidden}
|
||||||
variant="plain"
|
content={
|
||||||
colorSchema="secondary"
|
groupSecret?.secretValueHidden
|
||||||
ariaLabel="Copy secret value"
|
? "You do not have permission to view this secret value"
|
||||||
onClick={(e) => {
|
: ""
|
||||||
e.stopPropagation();
|
}
|
||||||
const el = envSlugMap.get(groupSecret.env)?.name;
|
|
||||||
if (el) {
|
|
||||||
handleCopy(groupSecret.value!, el);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={isUrlCopied ? faCheck : faCopy} />
|
<IconButton
|
||||||
</IconButton>
|
size="md"
|
||||||
|
isDisabled={groupSecret?.secretValueHidden}
|
||||||
|
variant="plain"
|
||||||
|
colorSchema="secondary"
|
||||||
|
ariaLabel="Copy secret value"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const el = envSlugMap.get(groupSecret.env)?.name;
|
||||||
|
if (el) {
|
||||||
|
handleCopy(groupSecret.value!, el);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={isUrlCopied ? faCheck : faCopy} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
) : (
|
) : (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
@@ -158,14 +168,24 @@ export const QuickSearchSecretItem = ({
|
|||||||
)}
|
)}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<IconButton
|
<Tooltip
|
||||||
size="md"
|
isDisabled={!groupSecret?.secretValueHidden}
|
||||||
variant="plain"
|
content={
|
||||||
colorSchema="secondary"
|
groupSecret?.secretValueHidden
|
||||||
ariaLabel="View secret value"
|
? "You do not have permission to view this secret value"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faEye} />
|
<IconButton
|
||||||
</IconButton>
|
size="md"
|
||||||
|
isDisabled={groupSecret?.secretValueHidden}
|
||||||
|
variant="plain"
|
||||||
|
colorSchema="secondary"
|
||||||
|
ariaLabel="View secret value"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faEye} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
<DropdownMenuLabel>Hover to Reveal...</DropdownMenuLabel>
|
<DropdownMenuLabel>Hover to Reveal...</DropdownMenuLabel>
|
||||||
|
|||||||
Reference in New Issue
Block a user