Merge pull request #1953 from akhilmhdh/main

Trailing slash in secret approval policy and overview bug
This commit is contained in:
Maidul Islam
2024-06-12 08:43:08 -04:00
committed by GitHub
5 changed files with 29 additions and 24 deletions
@@ -1,6 +1,7 @@
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import { z } from "zod"; import { z } from "zod";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { sapPubSchema } from "@app/server/routes/sanitizedSchemas"; import { sapPubSchema } from "@app/server/routes/sanitizedSchemas";
@@ -19,7 +20,11 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
workspaceId: z.string(), workspaceId: z.string(),
name: z.string().optional(), name: z.string().optional(),
environment: z.string(), environment: z.string(),
secretPath: z.string().optional().nullable(), secretPath: z
.string()
.optional()
.nullable()
.transform((val) => (val ? removeTrailingSlash(val) : val)),
approvers: z.string().array().min(1), approvers: z.string().array().min(1),
approvals: z.number().min(1).default(1) approvals: z.number().min(1).default(1)
}) })
@@ -63,7 +68,11 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
name: z.string().optional(), name: z.string().optional(),
approvers: z.string().array().min(1), approvers: z.string().array().min(1),
approvals: z.number().min(1).default(1), approvals: z.number().min(1).default(1),
secretPath: z.string().optional().nullable() secretPath: z
.string()
.optional()
.nullable()
.transform((val) => (val ? removeTrailingSlash(val) : val))
}) })
.refine((data) => data.approvals <= data.approvers.length, { .refine((data) => data.approvals <= data.approvers.length, {
path: ["approvals"], path: ["approvals"],
@@ -157,7 +166,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
querystring: z.object({ querystring: z.object({
workspaceId: z.string().trim(), workspaceId: z.string().trim(),
environment: z.string().trim(), environment: z.string().trim(),
secretPath: z.string().trim() secretPath: z.string().trim().transform(removeTrailingSlash)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -4,6 +4,7 @@ import picomatch from "picomatch";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn";
import { containsGlobPatterns } from "@app/lib/picomatch"; import { containsGlobPatterns } from "@app/lib/picomatch";
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal"; import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal"; import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
@@ -207,7 +208,8 @@ export const secretApprovalPolicyServiceFactory = ({
return sapPolicies; return sapPolicies;
}; };
const getSecretApprovalPolicy = async (projectId: string, environment: string, secretPath: string) => { const getSecretApprovalPolicy = async (projectId: string, environment: string, path: string) => {
const secretPath = removeTrailingSlash(path);
const env = await projectEnvDAL.findOne({ slug: environment, projectId }); const env = await projectEnvDAL.findOne({ slug: environment, projectId });
if (!env) throw new BadRequestError({ message: "Environment not found" }); if (!env) throw new BadRequestError({ message: "Environment not found" });
@@ -78,7 +78,8 @@ export const SecretPathInput = ({
const validPaths = inputValue.split("/"); const validPaths = inputValue.split("/");
validPaths.pop(); validPaths.pop();
const newValue = `${validPaths.join("/")}/${suggestions[selectedIndex]}/`; // removed trailing slash
const newValue = `${validPaths.join("/")}/${suggestions[selectedIndex]}`;
onChange?.(newValue); onChange?.(newValue);
setInputValue(newValue); setInputValue(newValue);
setSecretPath(newValue); setSecretPath(newValue);
@@ -264,13 +264,12 @@ export const useGetImportedSecretsAllEnvs = ({
}); });
const isImportedSecretPresentInEnv = useCallback( const isImportedSecretPresentInEnv = useCallback(
(secPath: string, envSlug: string, secretName: string) => { (envSlug: string, secretName: string) => {
const selectedEnvIndex = environments.indexOf(envSlug); const selectedEnvIndex = environments.indexOf(envSlug);
if (selectedEnvIndex !== -1) { if (selectedEnvIndex !== -1) {
const isPresent = secretImports?.[selectedEnvIndex]?.data?.find( const isPresent = secretImports?.[selectedEnvIndex]?.data?.find(({ secrets }) =>
({ secretPath, secrets }) => secrets.some((s) => s.key === secretName)
secretPath === secPath && secrets.some((s) => s.key === secretName)
); );
return Boolean(isPresent); return Boolean(isPresent);
@@ -29,7 +29,7 @@ type Props = {
onSecretCreate: (env: string, key: string, value: string) => Promise<void>; onSecretCreate: (env: string, key: string, value: string) => Promise<void>;
onSecretUpdate: (env: string, key: string, value: string, secretId?: string) => Promise<void>; onSecretUpdate: (env: string, key: string, value: string, secretId?: string) => Promise<void>;
onSecretDelete: (env: string, key: string, secretId?: string) => Promise<void>; onSecretDelete: (env: string, key: string, secretId?: string) => Promise<void>;
isImportedSecretPresentInEnv: (name: string, env: string, secretName: string) => boolean; isImportedSecretPresentInEnv: (env: string, secretName: string) => boolean;
}; };
export const SecretOverviewTableRow = ({ export const SecretOverviewTableRow = ({
@@ -53,9 +53,8 @@ export const SecretOverviewTableRow = ({
<> <>
<Tr isHoverable isSelectable onClick={() => setIsFormExpanded.toggle()} className="group"> <Tr isHoverable isSelectable onClick={() => setIsFormExpanded.toggle()} className="group">
<Td <Td
className={`sticky left-0 z-10 bg-mineshaft-800 bg-clip-padding py-0 px-0 group-hover:bg-mineshaft-700 ${ className={`sticky left-0 z-10 bg-mineshaft-800 bg-clip-padding py-0 px-0 group-hover:bg-mineshaft-700 ${isFormExpanded && "border-t-2 border-mineshaft-500"
isFormExpanded && "border-t-2 border-mineshaft-500" }`}
}`}
> >
<div className="h-full w-full border-r border-mineshaft-600 py-2.5 px-5"> <div className="h-full w-full border-r border-mineshaft-600 py-2.5 px-5">
<div className="flex items-center space-x-5"> <div className="flex items-center space-x-5">
@@ -83,7 +82,7 @@ export const SecretOverviewTableRow = ({
{environments.map(({ slug }, i) => { {environments.map(({ slug }, i) => {
const secret = getSecretByKey(slug, secretKey); const secret = getSecretByKey(slug, secretKey);
const isSecretImported = isImportedSecretPresentInEnv(secretPath, slug, secretKey); const isSecretImported = isImportedSecretPresentInEnv(slug, secretKey);
const isSecretPresent = Boolean(secret); const isSecretPresent = Boolean(secret);
const isSecretEmpty = secret?.value === ""; const isSecretEmpty = secret?.value === "";
@@ -108,8 +107,8 @@ export const SecretOverviewTableRow = ({
isSecretPresent isSecretPresent
? "Present secret" ? "Present secret"
: isSecretImported : isSecretImported
? "Imported secret" ? "Imported secret"
: "Missing secret" : "Missing secret"
} }
> >
<FontAwesomeIcon <FontAwesomeIcon
@@ -133,9 +132,8 @@ export const SecretOverviewTableRow = ({
<Tr> <Tr>
<Td <Td
colSpan={totalCols} colSpan={totalCols}
className={`bg-bunker-600 px-0 py-0 ${ className={`bg-bunker-600 px-0 py-0 ${isFormExpanded && "border-b-2 border-mineshaft-500"
isFormExpanded && "border-b-2 border-mineshaft-500" }`}
}`}
> >
<div <div
className="ml-2 p-2" className="ml-2 p-2"
@@ -180,11 +178,7 @@ export const SecretOverviewTableRow = ({
const secret = getSecretByKey(slug, secretKey); const secret = getSecretByKey(slug, secretKey);
const isCreatable = !secret; const isCreatable = !secret;
const isImportedSecret = isImportedSecretPresentInEnv( const isImportedSecret = isImportedSecretPresentInEnv(slug, secretKey);
secretPath,
slug,
secretKey
);
return ( return (
<tr <tr