mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 21:15:18 +09:00
add path validation in PagesSchema
This commit is contained in:
1 parent
a27bbcaf04
commit
c2e8ff642d
4 files changed
+41
-12
No files matched your search
@@ -102,7 +102,7 @@ const Pages = ({
|
||||
actions={
|
||||
<>
|
||||
{onNewPage && (
|
||||
<IconButton size="2" onClick={onNewPage} aria-label="Close">
|
||||
<IconButton size="2" onClick={onNewPage} aria-label="New Page">
|
||||
<NewPageIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
@@ -23,7 +23,7 @@ const Group = styled(Flex, {
|
||||
defaultVariants: { direction: "column" },
|
||||
});
|
||||
|
||||
export type PutPageData =
|
||||
export type CreatePageData =
|
||||
| { ok: true; page: Page }
|
||||
| { errors: string | ZodError["formErrors"] };
|
||||
|
||||
@@ -67,7 +67,7 @@ export const NewPageSettings = ({
|
||||
const nameFieldId = useId();
|
||||
const pathFieldId = useId();
|
||||
|
||||
const fetcher = useFetcher<PutPageData>();
|
||||
const fetcher = useFetcher<CreatePageData>();
|
||||
|
||||
const [fieldErrors, setFieldErrors] = useState<
|
||||
ZodError["formErrors"]["fieldErrors"]
|
||||
@@ -107,7 +107,7 @@ export const NewPageSettings = ({
|
||||
actions={
|
||||
<>
|
||||
{onClose && (
|
||||
<IconButton size="2" onClick={onClose} aria-label="Close">
|
||||
<IconButton size="2" onClick={onClose} aria-label="Cancel">
|
||||
<ChevronDoubleLeftIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { db } from "@webstudio-is/project/index.server";
|
||||
import { type Pages, utils } from "@webstudio-is/project";
|
||||
import { zfd } from "zod-form-data";
|
||||
import { z } from "zod";
|
||||
import { PutPageData } from "~/designer/features/sidebar-left/panels/pages/settings";
|
||||
import { CreatePageData } from "~/designer/features/sidebar-left/panels/pages/settings";
|
||||
import { sentryException } from "~/shared/sentry";
|
||||
|
||||
const nonEmptyString = z
|
||||
@@ -33,7 +33,7 @@ const CreatePageInput = zfd.formData({
|
||||
const handlePUT = async (
|
||||
projectId: string,
|
||||
request: Request
|
||||
): Promise<PutPageData> => {
|
||||
): Promise<CreatePageData> => {
|
||||
const result = CreatePageInput.safeParse(await request.formData());
|
||||
if (result.success === false) {
|
||||
return { errors: result.error.formErrors };
|
||||
@@ -72,7 +72,7 @@ export const action: ActionFunction = async ({ request, params }) => {
|
||||
}
|
||||
|
||||
if (request.method.toLowerCase() === "put") {
|
||||
return handlePUT(params.projectId, request);
|
||||
await handlePUT(params.projectId, request);
|
||||
}
|
||||
|
||||
throw new Error(`Method ${request.method} is not supported`);
|
||||
|
||||
@@ -9,21 +9,50 @@ export type Project = Omit<BaseProject, "assets"> & {
|
||||
assets?: Array<Asset>;
|
||||
};
|
||||
|
||||
export const PageSchema = z.object({
|
||||
const commonPageFields = {
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
path: z.string(),
|
||||
name: z.string().refine((val) => val !== "", "Can't be empty"),
|
||||
title: z.string(),
|
||||
meta: z.record(z.string(), z.string()),
|
||||
treeId: z.string(),
|
||||
} as const;
|
||||
|
||||
const HomePageSchema = z.object({
|
||||
...commonPageFields,
|
||||
path: z
|
||||
.string()
|
||||
.refine((path) => path === "", "Home page path must be empty"),
|
||||
});
|
||||
|
||||
const PageSchema = z.object({
|
||||
...commonPageFields,
|
||||
path: z
|
||||
.string()
|
||||
.refine((path) => path !== "" && path !== "/", "Can't be empty")
|
||||
.refine((path) => path.startsWith("/"), "Must start with a /")
|
||||
.refine((path) => path.endsWith("/") === false, "Can't end with a /")
|
||||
.refine(
|
||||
(path) => path.includes("//") === false,
|
||||
"Can't contain repeating /"
|
||||
)
|
||||
.refine(
|
||||
(path) => /^[-_a-z0-9\\/]*$/.test(path),
|
||||
"Only a-z, 0-9, -, _ and / are allowed"
|
||||
),
|
||||
});
|
||||
|
||||
export type Page = z.infer<typeof PageSchema>;
|
||||
|
||||
export const PagesSchema: z.ZodType<{ homePage: Page; pages: Array<Page> }> =
|
||||
z.object({
|
||||
homePage: PageSchema,
|
||||
pages: z.array(PageSchema),
|
||||
homePage: HomePageSchema,
|
||||
pages: z
|
||||
.array(PageSchema)
|
||||
.refine(
|
||||
(array) =>
|
||||
new Set(array.map((page) => page.path)).size === array.length,
|
||||
"All paths must be unique"
|
||||
),
|
||||
});
|
||||
export type Pages = z.infer<typeof PagesSchema>;
|
||||
|
||||
|
||||
Reference in new issue
Block a user