From 065b37f0914847f4cd27b5f7b9f4f52514f9f699 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sun, 28 Apr 2024 14:05:07 -1000 Subject: [PATCH] fix(api): :bug: Automatically trim every relevant API request field to remove extra whitespace --- server/api/api/auth/login/index.ts | 2 +- server/api/api/auth/mastodon-login/index.ts | 2 +- server/api/api/v1/accounts/[id]/note.ts | 2 +- server/api/api/v1/accounts/index.ts | 2 +- .../v1/accounts/update_credentials/index.ts | 18 +++++++++++++++--- server/api/api/v1/apps/index.ts | 4 ++-- server/api/api/v1/statuses/[id]/index.ts | 2 +- server/api/api/v1/statuses/index.ts | 4 ++-- server/api/api/v2/filters/[id]/index.ts | 4 ++-- server/api/api/v2/filters/index.ts | 4 ++-- server/api/api/v2/search/index.ts | 2 +- server/api/oauth/token/index.ts | 4 ++-- server/api/well-known/webfinger/index.ts | 2 +- 13 files changed, 32 insertions(+), 20 deletions(-) diff --git a/server/api/api/auth/login/index.ts b/server/api/api/auth/login/index.ts index 1439a0cd..ace5a04b 100644 --- a/server/api/api/auth/login/index.ts +++ b/server/api/api/auth/login/index.ts @@ -21,7 +21,7 @@ export const meta = applyConfig({ }); export const schema = z.object({ - email: z.string().email(), + email: z.string().email().toLowerCase(), password: z.string().min(2).max(100), scope: z.string().optional(), redirect_uri: z.string().url().optional(), diff --git a/server/api/api/auth/mastodon-login/index.ts b/server/api/api/auth/mastodon-login/index.ts index 66205734..6e078ffd 100644 --- a/server/api/api/auth/mastodon-login/index.ts +++ b/server/api/api/auth/mastodon-login/index.ts @@ -22,7 +22,7 @@ export const meta = applyConfig({ export const schema = z.object({ user: z.object({ - email: z.string().email(), + email: z.string().email().toLowerCase(), password: z.string().max(100).min(3), }), }); diff --git a/server/api/api/v1/accounts/[id]/note.ts b/server/api/api/v1/accounts/[id]/note.ts index 2683eb5a..e5f942b2 100644 --- a/server/api/api/v1/accounts/[id]/note.ts +++ b/server/api/api/v1/accounts/[id]/note.ts @@ -22,7 +22,7 @@ export const meta = applyConfig({ }); export const schema = z.object({ - comment: z.string().min(0).max(5000).optional(), + comment: z.string().min(0).max(5000).trim().optional(), }); /** diff --git a/server/api/api/v1/accounts/index.ts b/server/api/api/v1/accounts/index.ts index e68bd8a6..d5ce2731 100644 --- a/server/api/api/v1/accounts/index.ts +++ b/server/api/api/v1/accounts/index.ts @@ -23,7 +23,7 @@ export const meta = applyConfig({ // No validation on the Zod side as we need to do custom validation export const schema = z.object({ username: z.string().toLowerCase(), - email: z.string(), + email: z.string().toLowerCase(), password: z.string(), agreement: z.boolean(), locale: z.string(), diff --git a/server/api/api/v1/accounts/update_credentials/index.ts b/server/api/api/v1/accounts/update_credentials/index.ts index 8dc09fdf..ee71140b 100644 --- a/server/api/api/v1/accounts/update_credentials/index.ts +++ b/server/api/api/v1/accounts/update_credentials/index.ts @@ -32,9 +32,15 @@ export const schema = z.object({ display_name: z .string() .min(3) + .trim() .max(config.validation.max_displayname_size) .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(), header: z.instanceof(File).optional(), locked: z.boolean().optional(), @@ -54,8 +60,14 @@ export const schema = z.object({ fields_attributes: z .array( z.object({ - name: z.string().max(config.validation.max_field_name_size), - value: z.string().max(config.validation.max_field_value_size), + name: z + .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) diff --git a/server/api/api/v1/apps/index.ts b/server/api/api/v1/apps/index.ts index dee56ced..f6e30364 100644 --- a/server/api/api/v1/apps/index.ts +++ b/server/api/api/v1/apps/index.ts @@ -1,6 +1,6 @@ import { randomBytes } from "node:crypto"; import { apiRoute, applyConfig } from "@api"; -import { errorResponse, jsonResponse } from "@response"; +import { jsonResponse } from "@response"; import { z } from "zod"; import { db } from "~drizzle/db"; import { Applications } from "~drizzle/schema"; @@ -18,7 +18,7 @@ export const meta = applyConfig({ }); 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(), scopes: z.string().min(1).max(200), website: z.string().min(0).max(2000).url().optional(), diff --git a/server/api/api/v1/statuses/[id]/index.ts b/server/api/api/v1/statuses/[id]/index.ts index 72cf3282..4e311689 100644 --- a/server/api/api/v1/statuses/[id]/index.ts +++ b/server/api/api/v1/statuses/[id]/index.ts @@ -20,7 +20,7 @@ export const meta = applyConfig({ }); 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 content_type: z.string().optional().default("text/plain"), media_ids: z diff --git a/server/api/api/v1/statuses/index.ts b/server/api/api/v1/statuses/index.ts index 5043f45b..43efc424 100644 --- a/server/api/api/v1/statuses/index.ts +++ b/server/api/api/v1/statuses/index.ts @@ -20,14 +20,14 @@ export const meta = applyConfig({ }); 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 content_type: z.string().optional().default("text/plain"), media_ids: z .array(z.string().regex(idValidator)) .max(config.validation.max_media_attachments) .optional(), - spoiler_text: z.string().max(255).optional(), + spoiler_text: z.string().max(255).trim().optional(), sensitive: z.boolean().optional(), language: z.enum(ISO6391.getAllCodes() as [string, ...string[]]).optional(), "poll[options]": z diff --git a/server/api/api/v2/filters/[id]/index.ts b/server/api/api/v2/filters/[id]/index.ts index 2fe473d9..16f3d71a 100644 --- a/server/api/api/v2/filters/[id]/index.ts +++ b/server/api/api/v2/filters/[id]/index.ts @@ -18,7 +18,7 @@ export const meta = applyConfig({ }); export const schema = z.object({ - title: z.string().min(1).max(100).optional(), + title: z.string().trim().min(1).max(100).optional(), context: z .array(z.enum(["home", "notifications", "public", "thread", "account"])) .optional(), @@ -32,7 +32,7 @@ export const schema = z.object({ keywords_attributes: z .array( 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(), whole_word: z.boolean().optional(), _destroy: z.boolean().optional(), diff --git a/server/api/api/v2/filters/index.ts b/server/api/api/v2/filters/index.ts index b5dd0698..8cbb5310 100644 --- a/server/api/api/v2/filters/index.ts +++ b/server/api/api/v2/filters/index.ts @@ -18,7 +18,7 @@ export const meta = applyConfig({ }); export const schema = z.object({ - title: z.string().min(1).max(100).optional(), + title: z.string().trim().min(1).max(100).optional(), context: z .array(z.enum(["home", "notifications", "public", "thread", "account"])) .optional(), @@ -32,7 +32,7 @@ export const schema = z.object({ keywords_attributes: z .array( z.object({ - keyword: z.string().min(1).max(100), + keyword: z.string().trim().min(1).max(100), whole_word: z.boolean().optional(), }), ) diff --git a/server/api/api/v2/search/index.ts b/server/api/api/v2/search/index.ts index 19f3b6fe..16a71f1a 100644 --- a/server/api/api/v2/search/index.ts +++ b/server/api/api/v2/search/index.ts @@ -25,7 +25,7 @@ export const meta = applyConfig({ }); export const schema = z.object({ - q: z.string().optional(), + q: z.string().trim().optional(), type: z.string().optional(), resolve: z.coerce.boolean().optional(), following: z.coerce.boolean().optional(), diff --git a/server/api/oauth/token/index.ts b/server/api/oauth/token/index.ts index ed6fbce1..a01a02d3 100644 --- a/server/api/oauth/token/index.ts +++ b/server/api/oauth/token/index.ts @@ -33,8 +33,8 @@ export const schema = z.object({ ]), client_id: z.string().optional(), client_secret: z.string().optional(), - username: z.string().optional(), - password: z.string().optional(), + username: z.string().trim().optional(), + password: z.string().trim().optional(), redirect_uri: z.string().url().optional(), refresh_token: z.string().optional(), scope: z.string().optional(), diff --git a/server/api/well-known/webfinger/index.ts b/server/api/well-known/webfinger/index.ts index a40a2579..991c5873 100644 --- a/server/api/well-known/webfinger/index.ts +++ b/server/api/well-known/webfinger/index.ts @@ -19,7 +19,7 @@ export const meta = applyConfig({ }); export const schema = z.object({ - resource: z.string().min(1).max(512), + resource: z.string().trim().min(1).max(512), }); export default apiRoute(