fix(api): 🐛 Automatically trim every relevant API request field to remove extra whitespace

This commit is contained in:
Jesse Wierzbinski 2024-04-28 14:05:07 -10:00
parent aee47e6df4
commit 065b37f091
No known key found for this signature in database
13 changed files with 32 additions and 20 deletions

View file

@ -21,7 +21,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
email: z.string().email(), email: z.string().email().toLowerCase(),
password: z.string().min(2).max(100), password: z.string().min(2).max(100),
scope: z.string().optional(), scope: z.string().optional(),
redirect_uri: z.string().url().optional(), redirect_uri: z.string().url().optional(),

View file

@ -22,7 +22,7 @@ export const meta = applyConfig({
export const schema = z.object({ export const schema = z.object({
user: z.object({ user: z.object({
email: z.string().email(), email: z.string().email().toLowerCase(),
password: z.string().max(100).min(3), password: z.string().max(100).min(3),
}), }),
}); });

View file

@ -22,7 +22,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
comment: z.string().min(0).max(5000).optional(), comment: z.string().min(0).max(5000).trim().optional(),
}); });
/** /**

View file

@ -23,7 +23,7 @@ export const meta = applyConfig({
// No validation on the Zod side as we need to do custom validation // No validation on the Zod side as we need to do custom validation
export const schema = z.object({ export const schema = z.object({
username: z.string().toLowerCase(), username: z.string().toLowerCase(),
email: z.string(), email: z.string().toLowerCase(),
password: z.string(), password: z.string(),
agreement: z.boolean(), agreement: z.boolean(),
locale: z.string(), locale: z.string(),

View file

@ -32,9 +32,15 @@ export const schema = z.object({
display_name: z display_name: z
.string() .string()
.min(3) .min(3)
.trim()
.max(config.validation.max_displayname_size) .max(config.validation.max_displayname_size)
.optional(), .optional(),
note: z.string().min(0).max(config.validation.max_bio_size).optional(), note: z
.string()
.min(0)
.max(config.validation.max_bio_size)
.trim()
.optional(),
avatar: z.instanceof(File).optional(), avatar: z.instanceof(File).optional(),
header: z.instanceof(File).optional(), header: z.instanceof(File).optional(),
locked: z.boolean().optional(), locked: z.boolean().optional(),
@ -54,8 +60,14 @@ export const schema = z.object({
fields_attributes: z fields_attributes: z
.array( .array(
z.object({ z.object({
name: z.string().max(config.validation.max_field_name_size), name: z
value: z.string().max(config.validation.max_field_value_size), .string()
.trim()
.max(config.validation.max_field_name_size),
value: z
.string()
.trim()
.max(config.validation.max_field_value_size),
}), }),
) )
.max(config.validation.max_field_count) .max(config.validation.max_field_count)

View file

@ -1,6 +1,6 @@
import { randomBytes } from "node:crypto"; import { randomBytes } from "node:crypto";
import { apiRoute, applyConfig } from "@api"; import { apiRoute, applyConfig } from "@api";
import { errorResponse, jsonResponse } from "@response"; import { jsonResponse } from "@response";
import { z } from "zod"; import { z } from "zod";
import { db } from "~drizzle/db"; import { db } from "~drizzle/db";
import { Applications } from "~drizzle/schema"; import { Applications } from "~drizzle/schema";
@ -18,7 +18,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
client_name: z.string().min(1).max(100), client_name: z.string().trim().min(1).max(100),
redirect_uris: z.string().min(0).max(2000).url(), redirect_uris: z.string().min(0).max(2000).url(),
scopes: z.string().min(1).max(200), scopes: z.string().min(1).max(200),
website: z.string().min(0).max(2000).url().optional(), website: z.string().min(0).max(2000).url().optional(),

View file

@ -20,7 +20,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
status: z.string().max(config.validation.max_note_size).optional(), status: z.string().trim().max(config.validation.max_note_size).optional(),
// TODO: Add regex to validate // TODO: Add regex to validate
content_type: z.string().optional().default("text/plain"), content_type: z.string().optional().default("text/plain"),
media_ids: z media_ids: z

View file

@ -20,14 +20,14 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
status: z.string().max(config.validation.max_note_size).optional(), status: z.string().max(config.validation.max_note_size).trim().optional(),
// TODO: Add regex to validate // TODO: Add regex to validate
content_type: z.string().optional().default("text/plain"), content_type: z.string().optional().default("text/plain"),
media_ids: z media_ids: z
.array(z.string().regex(idValidator)) .array(z.string().regex(idValidator))
.max(config.validation.max_media_attachments) .max(config.validation.max_media_attachments)
.optional(), .optional(),
spoiler_text: z.string().max(255).optional(), spoiler_text: z.string().max(255).trim().optional(),
sensitive: z.boolean().optional(), sensitive: z.boolean().optional(),
language: z.enum(ISO6391.getAllCodes() as [string, ...string[]]).optional(), language: z.enum(ISO6391.getAllCodes() as [string, ...string[]]).optional(),
"poll[options]": z "poll[options]": z

View file

@ -18,7 +18,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
title: z.string().min(1).max(100).optional(), title: z.string().trim().min(1).max(100).optional(),
context: z context: z
.array(z.enum(["home", "notifications", "public", "thread", "account"])) .array(z.enum(["home", "notifications", "public", "thread", "account"]))
.optional(), .optional(),
@ -32,7 +32,7 @@ export const schema = z.object({
keywords_attributes: z keywords_attributes: z
.array( .array(
z.object({ z.object({
keyword: z.string().min(1).max(100).optional(), keyword: z.string().trim().min(1).max(100).optional(),
id: z.string().regex(idValidator).optional(), id: z.string().regex(idValidator).optional(),
whole_word: z.boolean().optional(), whole_word: z.boolean().optional(),
_destroy: z.boolean().optional(), _destroy: z.boolean().optional(),

View file

@ -18,7 +18,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
title: z.string().min(1).max(100).optional(), title: z.string().trim().min(1).max(100).optional(),
context: z context: z
.array(z.enum(["home", "notifications", "public", "thread", "account"])) .array(z.enum(["home", "notifications", "public", "thread", "account"]))
.optional(), .optional(),
@ -32,7 +32,7 @@ export const schema = z.object({
keywords_attributes: z keywords_attributes: z
.array( .array(
z.object({ z.object({
keyword: z.string().min(1).max(100), keyword: z.string().trim().min(1).max(100),
whole_word: z.boolean().optional(), whole_word: z.boolean().optional(),
}), }),
) )

View file

@ -25,7 +25,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
q: z.string().optional(), q: z.string().trim().optional(),
type: z.string().optional(), type: z.string().optional(),
resolve: z.coerce.boolean().optional(), resolve: z.coerce.boolean().optional(),
following: z.coerce.boolean().optional(), following: z.coerce.boolean().optional(),

View file

@ -33,8 +33,8 @@ export const schema = z.object({
]), ]),
client_id: z.string().optional(), client_id: z.string().optional(),
client_secret: z.string().optional(), client_secret: z.string().optional(),
username: z.string().optional(), username: z.string().trim().optional(),
password: z.string().optional(), password: z.string().trim().optional(),
redirect_uri: z.string().url().optional(), redirect_uri: z.string().url().optional(),
refresh_token: z.string().optional(), refresh_token: z.string().optional(),
scope: z.string().optional(), scope: z.string().optional(),

View file

@ -19,7 +19,7 @@ export const meta = applyConfig({
}); });
export const schema = z.object({ export const schema = z.object({
resource: z.string().min(1).max(512), resource: z.string().trim().min(1).max(512),
}); });
export default apiRoute<typeof meta, typeof schema>( export default apiRoute<typeof meta, typeof schema>(