From 2bb7865c677ffaefb6f92d70579c884043a81836 Mon Sep 17 00:00:00 2001 From: aiirvizionz Date: Tue, 28 Jul 2026 23:28:04 -0600 Subject: [PATCH] fix(users): trim profile username params --- .../api/users/by-username/[username]/route.js | 5 ++-- .../by-username/[username]/route.test.js | 24 +++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/app/api/users/by-username/[username]/route.js b/src/app/api/users/by-username/[username]/route.js index 486e89a9..b94640b5 100644 --- a/src/app/api/users/by-username/[username]/route.js +++ b/src/app/api/users/by-username/[username]/route.js @@ -4,7 +4,8 @@ import { getServiceRoleClient } from '@/lib/supabase/service-role.js'; export async function GET(request, { params } = {}) { try { const { username } = (await params) || {}; - if (!username) { + const normalizedUsername = username?.trim().toLowerCase(); + if (!normalizedUsername) { return NextResponse.json({ error: 'Username required' }, { status: 400 }); } @@ -18,7 +19,7 @@ export async function GET(request, { params } = {}) { const { data, error } = await supabase .from('users') .select('id, username, display_name, avatar_url, bio, unique_identifier') - .eq('username', username.toLowerCase()) + .eq('username', normalizedUsername) .single(); if (error || !data) { diff --git a/src/app/api/users/by-username/[username]/route.test.js b/src/app/api/users/by-username/[username]/route.test.js index 969c793b..c68700cb 100644 --- a/src/app/api/users/by-username/[username]/route.test.js +++ b/src/app/api/users/by-username/[username]/route.test.js @@ -5,8 +5,8 @@ const mocks = vi.hoisted(() => ({ eq: vi.fn() })); -vi.mock('@/lib/supabase.js', () => ({ - createSupabaseServerClient: vi.fn(async () => ({ +vi.mock('@/lib/supabase/service-role.js', () => ({ + getServiceRoleClient: vi.fn(() => ({ from: mocks.from })) })); @@ -50,6 +50,16 @@ describe('GET /api/users/by-username/[username]', () => { expect(mocks.eq).toHaveBeenCalledWith('username', 'alice'); }); + it('trims usernames before database lookup', async () => { + const { GET } = await import('./route.js'); + const response = await GET(new Request('https://qrypt.chat/api/users/by-username/%20Alice%20'), { + params: Promise.resolve({ username: ' Alice ' }) + }); + + expect(response.status).toBe(200); + expect(mocks.eq).toHaveBeenCalledWith('username', 'alice'); + }); + it('rejects missing usernames before database work', async () => { const { GET } = await import('./route.js'); const response = await GET(new Request('https://qrypt.chat/api/users/by-username/'), { @@ -59,4 +69,14 @@ describe('GET /api/users/by-username/[username]', () => { expect(response.status).toBe(400); expect(mocks.from).not.toHaveBeenCalled(); }); + + it('rejects blank usernames before database work', async () => { + const { GET } = await import('./route.js'); + const response = await GET(new Request('https://qrypt.chat/api/users/by-username/%20%20'), { + params: Promise.resolve({ username: ' ' }) + }); + + expect(response.status).toBe(400); + expect(mocks.from).not.toHaveBeenCalled(); + }); });