From 258cbcf238736e17a8a9efef597dc82a81b262a6 Mon Sep 17 00:00:00 2001 From: Paul Bailey Date: Sun, 16 Nov 2025 21:44:21 +0000 Subject: [PATCH] fix: prevent duplicate user_ prefix in usernames - Update user creation logic to strip 'user_' prefix from Clerk ID before generating username - Change default username pattern from 'user_' to 'user' - This prevents usernames like 'user_user_35Z...' and creates 'user35Z...' instead - Apply fix to both userService and reportController - Add migration script to fix existing duplicate usernames Example: user_user_35ZFZ... -> user35ZFZ... --- server/src/controllers/reportController.ts | 6 +- server/src/scripts/fixDuplicateUsernames.ts | 61 +++++++++++++++++++++ server/src/services/userService.ts | 6 +- 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 server/src/scripts/fixDuplicateUsernames.ts diff --git a/server/src/controllers/reportController.ts b/server/src/controllers/reportController.ts index 36b9530..2cf5eba 100644 --- a/server/src/controllers/reportController.ts +++ b/server/src/controllers/reportController.ts @@ -22,11 +22,15 @@ export class ReportController { try { const clerkUser = await clerkClient.users.getUser(clerkId); + // Generate a clean username from Clerk ID (remove 'user_' prefix if present) + const cleanClerkId = clerkId.startsWith('user_') ? clerkId.substring(5) : clerkId; + const defaultUsername = clerkUser.username || `user${cleanClerkId.substring(0, 8)}`; + user = await prisma.user.create({ data: { clerkId, email: clerkUser.emailAddresses[0]?.emailAddress || `${clerkId}@temp.com`, - username: clerkUser.username || `user_${clerkId.substring(0, 8)}`, + username: defaultUsername, firstName: clerkUser.firstName, lastName: clerkUser.lastName, avatarUrl: clerkUser.imageUrl, diff --git a/server/src/scripts/fixDuplicateUsernames.ts b/server/src/scripts/fixDuplicateUsernames.ts new file mode 100644 index 0000000..ebd6ca5 --- /dev/null +++ b/server/src/scripts/fixDuplicateUsernames.ts @@ -0,0 +1,61 @@ +/** + * Script to fix duplicate usernames that have the pattern user_user_xxxxx + * + * This script updates usernames that were created with the old logic + * where we used `user_${clerkId}` and the clerkId already started with 'user_' + * + * Usage: npx ts-node src/scripts/fixDuplicateUsernames.ts + */ + +import prisma from '../config/database'; + +async function fixDuplicateUsernames() { + console.log('šŸ” Finding users with duplicate username pattern...\n'); + + try { + // Find all users with usernames starting with 'user_user_' + const usersToFix = await prisma.user.findMany({ + where: { + username: { + startsWith: 'user_user_', + }, + }, + }); + + console.log(`Found ${usersToFix.length} users to fix\n`); + + if (usersToFix.length === 0) { + console.log('āœ… No users need fixing!'); + return; + } + + // Fix each user + for (const user of usersToFix) { + const oldUsername = user.username; + + // Remove the duplicate 'user_' prefix + const newUsername = oldUsername.replace(/^user_user_/, 'user'); + + console.log(`Updating user ${user.id}:`); + console.log(` Old: ${oldUsername}`); + console.log(` New: ${newUsername}`); + + await prisma.user.update({ + where: { id: user.id }, + data: { username: newUsername }, + }); + + console.log(' āœ… Updated\n'); + } + + console.log(`\nāœ… Successfully fixed ${usersToFix.length} usernames!`); + } catch (error) { + console.error('āŒ Error fixing usernames:', error); + throw error; + } finally { + await prisma.$disconnect(); + } +} + +// Run the script +fixDuplicateUsernames(); diff --git a/server/src/services/userService.ts b/server/src/services/userService.ts index 911996a..934a995 100644 --- a/server/src/services/userService.ts +++ b/server/src/services/userService.ts @@ -36,11 +36,15 @@ export class UserService { try { const clerkUser = await clerkClient.users.getUser(clerkId); + // Generate a clean username from Clerk ID (remove 'user_' prefix if present) + const cleanClerkId = clerkId.startsWith('user_') ? clerkId.substring(5) : clerkId; + const defaultUsername = clerkUser.username || `user${cleanClerkId.substring(0, 8)}`; + user = await prisma.user.create({ data: { clerkId, email: clerkUser.emailAddresses[0]?.emailAddress || `${clerkId}@temp.com`, - username: clerkUser.username || `user_${clerkId.substring(0, 8)}`, + username: defaultUsername, firstName: clerkUser.firstName, lastName: clerkUser.lastName, avatarUrl: clerkUser.imageUrl,