From 5c95051ddfa1fa64c224b4e1d9b7c86fb822c4e9 Mon Sep 17 00:00:00 2001 From: Face <69168154+face-hh@users.noreply.github.com> Date: Sun, 8 Jun 2025 21:36:50 +0300 Subject: [PATCH] fix display name minimum and maximum length --- website/src/routes/api/settings/+server.ts | 12 ++++++++ .../api/settings/check-username/+server.ts | 24 ++++++++++----- website/src/routes/settings/+page.svelte | 30 +++++++++++++++++-- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/website/src/routes/api/settings/+server.ts b/website/src/routes/api/settings/+server.ts index 3802ec5..fbdfa4a 100644 --- a/website/src/routes/api/settings/+server.ts +++ b/website/src/routes/api/settings/+server.ts @@ -8,6 +8,18 @@ import { MAX_FILE_SIZE } from '$lib/data/constants'; import { isNameAppropriate } from '$lib/server/moderation'; async function validateInputs(name: string, bio: string, username: string, avatarFile: File | null) { + if (!name || !name.trim()) { + throw error(400, 'Display name is required'); + } + + if (name.trim().length < 2) { + throw error(400, 'Display name must be at least 2 characters'); + } + + if (name.trim().length > 50) { + throw error(400, 'Display name must be 50 characters or less'); + } + if (name && !(await isNameAppropriate(name.trim()))) { throw error(400, 'Name contains inappropriate content'); } diff --git a/website/src/routes/api/settings/check-username/+server.ts b/website/src/routes/api/settings/check-username/+server.ts index 9d8ce5c..5498f7d 100644 --- a/website/src/routes/api/settings/check-username/+server.ts +++ b/website/src/routes/api/settings/check-username/+server.ts @@ -7,15 +7,13 @@ import { isNameAppropriate } from '$lib/server/moderation'; export async function GET({ url }) { let username = url.searchParams.get('username')?.toLowerCase().trim(); if (!username) { - return json({ available: false }); + return json({ available: false, reason: 'Username is required.' }); } - username = username.trim().replace(/\s+/g, ' '); - if (username.length < 3 || username.length > 30) { return json({ available: false, - reason: 'Username must be between 3 and 30 characters' + reason: 'Username must be 3-30 characters.' }); } @@ -23,17 +21,29 @@ export async function GET({ url }) { if (!alphanumericRegex.test(username)) { return json({ available: false, - reason: 'Username must contain only lowercase letters, numbers, and underscores' + reason: 'Username can only contain lowercase letters, numbers, and underscores.' + }); + } + + const purelyNumericRegex = /^\d+$/; + if (purelyNumericRegex.test(username)) { + return json({ + available: false, + reason: 'Username cannot be purely numeric.' }); } if (!(await isNameAppropriate(username))) { - return json({ available: false, reason: 'Inappropriate content' }); + return json({ available: false, reason: 'Username contains inappropriate content.' }); } const exists = await db.query.user.findFirst({ where: eq(user.username, username) }); - return json({ available: !exists }); + if (exists) { + return json({ available: false, reason: 'Username is already taken.' }); + } + + return json({ available: true }); } diff --git a/website/src/routes/settings/+page.svelte b/website/src/routes/settings/+page.svelte index 53cbe32..03f61df 100644 --- a/website/src/routes/settings/+page.svelte +++ b/website/src/routes/settings/+page.svelte @@ -27,6 +27,8 @@ let previewUrl: string | null = $state(null); let currentAvatarUrl = $derived(previewUrl || getPublicUrl($USER_DATA?.image ?? null)); + let nameError = $state(''); + let isDirty = $derived( name !== ($USER_DATA?.name || '') || bio !== ($USER_DATA?.bio ?? '') || @@ -101,6 +103,22 @@ if (username !== initialUsername) checkUsername(username); }); + $effect(() => { + validateName(); + }); + + function validateName() { + if (!name.trim()) { + nameError = 'Display name is required.'; + } else if (name.trim().length < 2) { + nameError = 'Display name must be at least 2 characters.'; + } else if (name.trim().length > 50) { + nameError = 'Display name must be 50 characters or less.'; + } else { + nameError = ''; + } + } + async function handleSubmit(e: Event) { e.preventDefault(); loading = true; @@ -317,7 +335,15 @@