From 5964976e47ac7ca2b4549a717675c0fd456912dc Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 24 Sep 2024 15:49:27 +0400 Subject: [PATCH 1/6] fix(folders-api): prefix paths --- backend/src/lib/fn/string.ts | 5 ++ .../server/routes/v1/secret-folder-router.ts | 74 ++++++++++++++++--- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/backend/src/lib/fn/string.ts b/backend/src/lib/fn/string.ts index c3651fd4e..26e8f27df 100644 --- a/backend/src/lib/fn/string.ts +++ b/backend/src/lib/fn/string.ts @@ -9,3 +9,8 @@ export const removeTrailingSlash = (str: string) => { return str.endsWith("/") ? str.slice(0, -1) : str; }; + +export const prefixWithSlash = (str: string) => { + if (str.startsWith("/")) return str; + return `/${str}`; +}; diff --git a/backend/src/server/routes/v1/secret-folder-router.ts b/backend/src/server/routes/v1/secret-folder-router.ts index 276bb36ef..f67f9ec67 100644 --- a/backend/src/server/routes/v1/secret-folder-router.ts +++ b/backend/src/server/routes/v1/secret-folder-router.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import { SecretFoldersSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { FOLDERS } from "@app/lib/api-docs"; -import { removeTrailingSlash } from "@app/lib/fn"; +import { prefixWithSlash, removeTrailingSlash } from "@app/lib/fn"; import { readLimit, secretsLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; @@ -26,9 +26,21 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => workspaceId: z.string().trim().describe(FOLDERS.CREATE.workspaceId), environment: z.string().trim().describe(FOLDERS.CREATE.environment), name: z.string().trim().describe(FOLDERS.CREATE.name), - path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.CREATE.path), + path: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.CREATE.path), // backward compatiability with cli - directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.CREATE.directory) + directory: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.CREATE.directory) }), response: { 200: z.object({ @@ -86,9 +98,21 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => workspaceId: z.string().trim().describe(FOLDERS.UPDATE.workspaceId), environment: z.string().trim().describe(FOLDERS.UPDATE.environment), name: z.string().trim().describe(FOLDERS.UPDATE.name), - path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.UPDATE.path), + path: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.UPDATE.path), // backward compatiability with cli - directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.UPDATE.directory) + directory: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.UPDATE.directory) }), response: { 200: z.object({ @@ -147,7 +171,13 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => id: z.string().describe(FOLDERS.UPDATE.folderId), environment: z.string().trim().describe(FOLDERS.UPDATE.environment), name: z.string().trim().describe(FOLDERS.UPDATE.name), - path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.UPDATE.path) + path: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.UPDATE.path) }) .array() .min(1) @@ -211,9 +241,21 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => body: z.object({ workspaceId: z.string().trim().describe(FOLDERS.DELETE.workspaceId), environment: z.string().trim().describe(FOLDERS.DELETE.environment), - path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.DELETE.path), + path: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.DELETE.path), // keep this here as cli need directory - directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.DELETE.directory) + directory: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.DELETE.directory) }), response: { 200: z.object({ @@ -267,9 +309,21 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) => querystring: z.object({ workspaceId: z.string().trim().describe(FOLDERS.LIST.workspaceId), environment: z.string().trim().describe(FOLDERS.LIST.environment), - path: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.LIST.path), + path: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.LIST.path), // backward compatiability with cli - directory: z.string().trim().default("/").transform(removeTrailingSlash).describe(FOLDERS.LIST.directory) + directory: z + .string() + .trim() + .default("/") + .transform(prefixWithSlash) + .transform(removeTrailingSlash) + .describe(FOLDERS.LIST.directory) }), response: { 200: z.object({ From fc39b3b0ddb977afbf66f99f61c00f19f3c8cadb Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Tue, 24 Sep 2024 17:24:38 +0400 Subject: [PATCH 2/6] fix(dashboard): fix imports missing secrets counter --- .../src/hooks/api/secretImports/queries.tsx | 23 ++++++++++++++++++- .../SecretOverviewPage/SecretOverviewPage.tsx | 15 +++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/frontend/src/hooks/api/secretImports/queries.tsx b/frontend/src/hooks/api/secretImports/queries.tsx index a3136e2a8..c2ddd2fbe 100644 --- a/frontend/src/hooks/api/secretImports/queries.tsx +++ b/frontend/src/hooks/api/secretImports/queries.tsx @@ -189,6 +189,22 @@ export const useGetImportedSecretsAllEnvs = ({ })) }); + const getEnvImportedSecretKeyCount = useCallback( + (env: string) => { + const selectedEnvIndex = environments.indexOf(env); + let totalSecrets = 0; + + if (selectedEnvIndex !== -1) { + secretImports?.[selectedEnvIndex]?.data?.forEach((secret) => { + totalSecrets += secret.secrets.length; + }); + } + + return totalSecrets; + }, + [(secretImports || []).map((response) => response.data)] + ); + const isImportedSecretPresentInEnv = useCallback( (envSlug: string, secretName: string) => { const selectedEnvIndex = environments.indexOf(envSlug); @@ -226,7 +242,12 @@ export const useGetImportedSecretsAllEnvs = ({ [(secretImports || []).map((response) => response.data)] ); - return { secretImports, isImportedSecretPresentInEnv, getImportedSecretByKey }; + return { + secretImports, + isImportedSecretPresentInEnv, + getImportedSecretByKey, + getEnvImportedSecretKeyCount + }; }; export const useGetImportedFoldersByEnv = ({ diff --git a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx index 46e5f4ba7..154937869 100644 --- a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx +++ b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx @@ -207,11 +207,12 @@ export const SecretOverviewPage = () => { setVisibleEnvs(readableEnvs); }, [userAvailableEnvs, secretPath]); - const { isImportedSecretPresentInEnv, getImportedSecretByKey } = useGetImportedSecretsAllEnvs({ - projectId: workspaceId, - path: secretPath, - environments: userAvailableEnvs.map(({ slug }) => slug) - }); + const { isImportedSecretPresentInEnv, getImportedSecretByKey, getEnvImportedSecretKeyCount } = + useGetImportedSecretsAllEnvs({ + projectId: workspaceId, + path: secretPath, + environments: userAvailableEnvs.map(({ slug }) => slug) + }); const paginationOffset = (page - 1) * perPage; @@ -784,7 +785,9 @@ export const SecretOverviewPage = () => { {visibleEnvs?.map(({ name, slug }, index) => { const envSecKeyCount = getEnvSecretKeyCount(slug); - const missingKeyCount = secKeys.length - envSecKeyCount; + const importedSecKeyCount = getEnvImportedSecretKeyCount(slug); + const missingKeyCount = secKeys.length - envSecKeyCount - importedSecKeyCount; + return ( Date: Wed, 25 Sep 2024 00:27:36 +0800 Subject: [PATCH 3/6] misc: added maintenance notice to audit log page and handled project auto-select --- .../views/Org/AuditLogsPage/AuditLogsPage.tsx | 6 +++++ .../AuditLogsPage/components/LogsFilter.tsx | 22 ++++++++++--------- .../AuditLogsPage/components/LogsSection.tsx | 3 ++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/frontend/src/views/Org/AuditLogsPage/AuditLogsPage.tsx b/frontend/src/views/Org/AuditLogsPage/AuditLogsPage.tsx index 2b6ec6744..1ce60ea5f 100644 --- a/frontend/src/views/Org/AuditLogsPage/AuditLogsPage.tsx +++ b/frontend/src/views/Org/AuditLogsPage/AuditLogsPage.tsx @@ -1,3 +1,4 @@ +import { NoticeBanner } from "@app/components/v2"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; import { withPermission } from "@app/hoc"; @@ -10,6 +11,11 @@ export const AuditLogsPage = withPermission(

Audit Logs

+ + We are currently working on improving the performance of querying audit logs. However, + please note that audit logs are still being published as usual, so there’s no + disruption to log generation. +
diff --git a/frontend/src/views/Org/AuditLogsPage/components/LogsFilter.tsx b/frontend/src/views/Org/AuditLogsPage/components/LogsFilter.tsx index 9ea92f9a9..bc99057ab 100644 --- a/frontend/src/views/Org/AuditLogsPage/components/LogsFilter.tsx +++ b/frontend/src/views/Org/AuditLogsPage/components/LogsFilter.tsx @@ -1,6 +1,6 @@ /* eslint-disable no-nested-ternary */ -import { useState } from "react"; -import { Control, Controller, UseFormReset, UseFormWatch } from "react-hook-form"; +import { useEffect, useState } from "react"; +import { Control, Controller, UseFormReset, UseFormSetValue, UseFormWatch } from "react-hook-form"; import { faCheckCircle, faChevronDown, @@ -41,6 +41,7 @@ type Props = { }; className?: string; isOrgAuditLogs?: boolean; + setValue: UseFormSetValue; control: Control; reset: UseFormReset; watch: UseFormWatch; @@ -51,6 +52,7 @@ export const LogsFilter = ({ isOrgAuditLogs, className, control, + setValue, reset, watch }: Props) => { @@ -60,6 +62,12 @@ export const LogsFilter = ({ const { currentWorkspace, workspaces } = useWorkspace(); const { data, isLoading } = useGetAuditLogActorFilterOpts(currentWorkspace?.id ?? ""); + useEffect(() => { + if (workspaces.length) { + setValue("projectId", workspaces[0].id); + } + }, [workspaces]); + const renderActorSelectItem = (actor: Actor) => { switch (actor.type) { case ActorType.USER: @@ -243,20 +251,14 @@ export const LogsFilter = ({ className="w-40" >