improvement: Slug Validation Errors (#2788)

* improvement: Slug Validation Errors
This commit is contained in:
McPizza
2024-12-08 14:02:33 +01:00
committed by GitHub
parent 6614721d34
commit 3c588beebe
30 changed files with 160 additions and 385 deletions
@@ -3,7 +3,6 @@ import { Controller, useForm } from "react-hook-form";
import { faCheck } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
@@ -18,6 +17,7 @@ import {
} from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { useCreateWsTag } from "@app/hooks/api";
import { slugSchema } from "@app/lib/schemas";
export const secretTagsColors = [
{
@@ -88,13 +88,7 @@ type Props = {
};
const createTagSchema = z.object({
slug: z
.string()
.trim()
.toLowerCase()
.refine((v) => slugify(v) === v, {
message: "Invalid slug. Slug can only contain alphanumeric characters and hyphens."
}),
slug: slugSchema({ min: 1, field: "Tag Slug" }),
color: z.string().trim()
});
+3 -8
View File
@@ -1,6 +1,7 @@
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { slugSchema } from "@app/lib/schemas";
export type Kms = {
id: string;
description: string;
@@ -119,13 +120,7 @@ export const ExternalKmsInputSchema = z.discriminatedUnion("type", [
]);
export const AddExternalKmsSchema = z.object({
name: z
.string()
.trim()
.min(1)
.refine((v) => slugify(v) === v, {
message: "Alias must be a valid slug"
}),
name: slugSchema({ min: 1, field: "Alias" }),
description: z.string().trim().optional(),
provider: ExternalKmsInputSchema
});
+20 -9
View File
@@ -1,12 +1,23 @@
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
export const slugSchema = z
.string()
.trim()
.min(1)
.max(32)
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
.refine((v) => slugify(v) === v, {
message: "Invalid slug format"
});
interface SlugSchemaInputs {
min?: number;
max?: number;
field?: string;
}
export const slugSchema = ({ min = 1, max = 32, field = "Slug" }: SlugSchemaInputs = {}) => {
return z
.string()
.trim()
.min(min, {
message: `${field} field must be at least ${min} lowercase character${min === 1 ? "" : "s"}`
})
.max(max, {
message: `${field} field must be at most ${max} lowercase character${max === 1 ? "" : "s"}`
})
.refine((v) => slugify(v, { lowercase: true }) === v, {
message: `${field} field can only contain lowercase letters, numbers, and hyphens`
});
};
@@ -9,12 +9,13 @@ import { Button, FormControl, Input, Modal, ModalContent } from "@app/components
import { useOrganization } from "@app/context";
import { useCreateOrgRole, useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
import { slugSchema } from "@app/lib/schemas";
const schema = z
.object({
name: z.string(),
description: z.string(),
slug: z.string()
slug: slugSchema({ min: 1 })
})
.required();
@@ -1,6 +1,5 @@
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
@@ -17,16 +16,10 @@ import {
} from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { EncryptionAlgorithm, TCmek, useCreateCmek, useUpdateCmek } from "@app/hooks/api/cmeks";
import { slugSchema } from "@app/lib/schemas";
const formSchema = z.object({
name: z
.string()
.min(1)
.toLowerCase()
.max(32)
.refine((v) => slugify(v) === v, {
message: "Name must be in slug format"
}),
name: slugSchema({ min: 1, max: 32, field: "Name" }),
description: z.string().max(500).optional(),
encryptionAlgorithm: z.nativeEnum(EncryptionAlgorithm)
});
@@ -13,12 +13,13 @@ import {
useUpdateProjectRole
} from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
import { slugSchema } from "@app/lib/schemas";
const schema = z
.object({
name: z.string(),
description: z.string(),
slug: z.string()
slug: slugSchema({ min: 1 })
})
.required();
@@ -2,7 +2,6 @@ import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { useRouter } from "next/router";
import { zodResolver } from "@hookform/resolvers/zod";
import slugify from "@sindresorhus/slugify";
import axios from "axios";
import { z } from "zod";
@@ -15,6 +14,7 @@ import {
useGetSlackIntegrationById,
useUpdateSlackIntegration
} from "@app/hooks/api";
import { slugSchema } from "@app/lib/schemas";
type Props = {
id?: string;
@@ -22,13 +22,7 @@ type Props = {
};
const slackFormSchema = z.object({
slug: z
.string()
.trim()
.min(1)
.refine((v) => slugify(v) === v, {
message: "Alias must be a valid slug"
}),
slug: slugSchema({ min: 1, field: "Alias" }),
description: z.string().optional()
});
@@ -31,7 +31,7 @@ type Props = {
};
const formSchema = z.object({
slug: slugSchema,
slug: slugSchema(),
name: z.string().trim().min(1),
permissions: projectRoleFormSchema.shape.permissions
});
@@ -32,7 +32,7 @@ const formSchema = z.object({
environments: z
.object({
name: z.string().trim().min(1),
slug: slugSchema
slug: slugSchema({ min: 1, max: 32 })
})
.array()
});
@@ -1,6 +1,5 @@
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
@@ -18,17 +17,10 @@ import {
useCreateProjectTemplate,
useUpdateProjectTemplate
} from "@app/hooks/api/projectTemplates";
import { slugSchema } from "@app/lib/schemas";
const formSchema = z.object({
name: z
.string()
.trim()
.min(1)
.max(32)
.toLowerCase()
.refine((v) => slugify(v) === v, {
message: "Name must be in slug format"
}),
name: slugSchema({ min: 1, max: 32, field: "Name" }),
description: z.string().max(500).optional()
});
@@ -1,13 +1,13 @@
import { Controller, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import slugify from "@sindresorhus/slugify";
import * as yup from "yup";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { useCreateWsEnvironment } from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
import { slugSchema } from "@app/lib/schemas";
type Props = {
popUp: UsePopUpState<["createEnv"]>;
@@ -15,26 +15,20 @@ type Props = {
handlePopUpToggle: (popUpName: keyof UsePopUpState<["createEnv"]>, state?: boolean) => void;
};
const schema = yup.object({
environmentName: yup.string().label("Environment Name").required(),
environmentSlug: yup
const schema = z.object({
environmentName: z
.string()
.label("Environment Slug")
.test({
test: (slug) => slugify(slug as string) === slug,
message: "Slug must be a valid slug"
})
.required()
.min(1, { message: "Environment Name field must be at least 1 character" }),
environmentSlug: slugSchema()
});
export type FormData = yup.InferType<typeof schema>;
export type FormData = z.infer<typeof schema>;
export const AddEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
const { currentWorkspace } = useWorkspace();
const { mutateAsync, isLoading } = useCreateWsEnvironment();
const { control, handleSubmit, reset } = useForm<FormData>({
resolver: yupResolver(schema)
resolver: zodResolver(schema)
});
const onFormSubmit = async ({ environmentName, environmentSlug }: FormData) => {
@@ -112,7 +106,11 @@ export const AddEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle
Create
</Button>
<Button onClick={() => handlePopUpClose("createEnv")} colorSchema="secondary" variant="plain">
<Button
onClick={() => handlePopUpClose("createEnv")}
colorSchema="secondary"
variant="plain"
>
Cancel
</Button>
</div>
@@ -1,13 +1,13 @@
import { Controller, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import slugify from "@sindresorhus/slugify";
import * as yup from "yup";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { useUpdateWsEnvironment } from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
import { slugSchema } from "@app/lib/schemas";
type Props = {
popUp: UsePopUpState<["updateEnv"]>;
@@ -15,25 +15,18 @@ type Props = {
handlePopUpToggle: (popUpName: keyof UsePopUpState<["updateEnv"]>, state?: boolean) => void;
};
const schema = yup.object({
name: yup.string().label("Environment Name").required(),
slug: yup
.string()
.label("Environment Slug")
.test({
test: (slug) => slugify(slug as string) === slug,
message: "Slug must be a valid slug"
})
.required()
const schema = z.object({
name: z.string(),
slug: slugSchema({ min: 1 })
});
export type FormData = yup.InferType<typeof schema>;
export type FormData = z.infer<typeof schema>;
export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
const { currentWorkspace } = useWorkspace();
const { mutateAsync, isLoading } = useUpdateWsEnvironment();
const { control, handleSubmit, reset } = useForm<FormData>({
resolver: yupResolver(schema),
resolver: zodResolver(schema),
values: popUp.updateEnv.data as FormData
});
@@ -1,6 +1,5 @@
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
@@ -8,11 +7,10 @@ import { Button, FormControl, Input, Modal, ModalClose, ModalContent } from "@ap
import { useWorkspace } from "@app/context";
import { useCreateWsTag } from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
import { slugSchema } from "@app/lib/schemas";
const schema = z.object({
slug: z.string().refine((v) => slugify(v) === v, {
message: "Invalid slug. Slug can only contain alphanumeric characters and hyphens."
})
slug: slugSchema({ min: 1, field: "Tag Slug" })
});
export type FormData = z.infer<typeof schema>;