From ebb541dc6b5c008fd367d9da845930eee7251778 Mon Sep 17 00:00:00 2001 From: Luke Vella Date: Mon, 10 Mar 2025 17:08:42 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Harden=20name=20validat?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(auth)/register/components/schema.ts | 6 ++++- apps/web/src/trpc/routers/auth.ts | 3 ++- apps/web/src/utils/is-valid-name.ts | 27 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/utils/is-valid-name.ts diff --git a/apps/web/src/app/[locale]/(auth)/register/components/schema.ts b/apps/web/src/app/[locale]/(auth)/register/components/schema.ts index 30d1d2dd3..4a32a83a9 100644 --- a/apps/web/src/app/[locale]/(auth)/register/components/schema.ts +++ b/apps/web/src/app/[locale]/(auth)/register/components/schema.ts @@ -1,7 +1,11 @@ import { z } from "zod"; +import { isValidName } from "@/utils/is-valid-name"; + export const registerNameFormSchema = z.object({ - name: z.string().min(1).max(100), + name: z.string().trim().min(1).max(100).refine(isValidName, { + message: "Please enter a valid name, not a URL, email, or phone number", + }), email: z.string().email(), }); diff --git a/apps/web/src/trpc/routers/auth.ts b/apps/web/src/trpc/routers/auth.ts index 1c5f7d55a..d7d5b3149 100644 --- a/apps/web/src/trpc/routers/auth.ts +++ b/apps/web/src/trpc/routers/auth.ts @@ -8,6 +8,7 @@ import { isEmailBlocked } from "@/auth/helpers/is-email-blocked"; import { mergeGuestsIntoUser } from "@/auth/helpers/merge-user"; import { isTemporaryEmail } from "@/auth/helpers/temp-email-domains"; import { getEmailClient } from "@/utils/emails"; +import { isValidName } from "@/utils/is-valid-name"; import { createToken, decryptToken } from "@/utils/session"; import { createRateLimitMiddleware, publicProcedure, router } from "../trpc"; @@ -33,7 +34,7 @@ export const auth = router({ .use(createRateLimitMiddleware("request_registration", 5, "1 m")) .input( z.object({ - name: z.string().min(1).max(100), + name: z.string().trim().min(1).max(100).refine(isValidName), email: z.string().email(), }), ) diff --git a/apps/web/src/utils/is-valid-name.ts b/apps/web/src/utils/is-valid-name.ts new file mode 100644 index 000000000..c0873ddd9 --- /dev/null +++ b/apps/web/src/utils/is-valid-name.ts @@ -0,0 +1,27 @@ +/** + * Checks if a string contains contact information like URLs, email addresses, or phone numbers + * Returns true if the string is a valid personal/company name (no contact info) + * Returns false if the string contains contact information + */ +export function isValidName(value: string) { + // Check for URL patterns + const urlPattern = + /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/i; + if (urlPattern.test(value)) { + return false; + } + + // Check for email patterns + const emailPattern = /.+@.+\..+/i; + if (emailPattern.test(value)) { + return false; + } + + // Check for phone number patterns (various formats) + const phonePattern = /\+?[\d\s\(\)\-\.]{7,}/; + if (phonePattern.test(value)) { + return false; + } + + return true; +}