diff --git a/prisma/migrations/20251117173240_add_nickname_to_users/migration.sql b/prisma/migrations/20251117173240_add_nickname_to_users/migration.sql new file mode 100644 index 0000000..567e04d --- /dev/null +++ b/prisma/migrations/20251117173240_add_nickname_to_users/migration.sql @@ -0,0 +1,15 @@ +-- Add nickname column to users table +ALTER TABLE "users" ADD COLUMN "nickname" VARCHAR(255) NOT NULL DEFAULT ''; + +-- Generate random nicknames for existing users +UPDATE "users" SET "nickname" = ( + SELECT + adj || ' ' || noun + FROM ( + SELECT + unnest(ARRAY['Cool', 'Swift', 'Bright', 'Silent', 'Quick', 'Brave', 'Clever', 'Wise', 'Bold', 'Calm', 'Wild', 'Free', 'Sharp', 'Soft', 'Hard', 'Light', 'Dark', 'Fast', 'Slow', 'High', 'Low', 'Deep', 'Shallow', 'Wide', 'Narrow', 'Long', 'Short', 'Big', 'Small', 'Hot', 'Cold', 'Warm', 'Wet', 'Dry', 'Sweet', 'Sour', 'Bitter', 'Salty', 'Fresh', 'Stale', 'New', 'Old', 'Young', 'Mature', 'Happy', 'Sad', 'Angry', 'Calm', 'Excited', 'Bored']) AS adj, + unnest(ARRAY['Eagle', 'Wolf', 'Bear', 'Lion', 'Tiger', 'Shark', 'Falcon', 'Hawk', 'Owl', 'Raven', 'Fox', 'Cat', 'Dog', 'Horse', 'Deer', 'Rabbit', 'Mouse', 'Bird', 'Fish', 'Snake', 'Turtle', 'Frog', 'Butterfly', 'Bee', 'Ant', 'Spider', 'Dragon', 'Phoenix', 'Unicorn', 'Griffin', 'Wizard', 'Knight', 'Warrior', 'Hunter', 'Explorer', 'Adventurer', 'Pirate', 'Ninja', 'Samurai', 'Ranger', 'Scout', 'Pilot', 'Captain', 'Commander', 'Leader', 'Hero', 'Champion', 'Master', 'Legend']) AS noun + ORDER BY random() + LIMIT 1 + ) AS random_nick +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4e49248..b6c2ac7 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -97,6 +97,7 @@ model users { id String @id public_key String @unique(map: "users_public_key_unique") namespace String @db.VarChar(255) + nickname String @db.VarChar(255) created_at DateTime @db.Timestamptz(0) last_logged_in DateTime? @db.Timestamptz(0) permissions String[] diff --git a/server/routes/auth/register/complete.ts b/server/routes/auth/register/complete.ts index 58d2ef3..2df1f38 100644 --- a/server/routes/auth/register/complete.ts +++ b/server/routes/auth/register/complete.ts @@ -2,6 +2,7 @@ import { z } from 'zod'; import { useChallenge } from '~/utils/challenge'; import { useAuth } from '~/utils/auth'; import { randomUUID } from 'crypto'; +import { generateRandomNickname } from '~/utils/nickname'; const completeSchema = z.object({ publicKey: z.string(), @@ -51,17 +52,19 @@ export default defineEventHandler(async event => { const userId = randomUUID(); const now = new Date(); + const nickname = generateRandomNickname(); const user = await prisma.users.create({ data: { id: userId, namespace: body.namespace, public_key: body.publicKey, + nickname, created_at: now, last_logged_in: now, permissions: [], profile: body.profile, - }, + } as any, }); const auth = useAuth(); @@ -74,6 +77,7 @@ export default defineEventHandler(async event => { id: user.id, publicKey: user.public_key, namespace: user.namespace, + nickname: (user as any).nickname, profile: user.profile, permissions: user.permissions, }, diff --git a/server/routes/users/@me.ts b/server/routes/users/@me.ts index f9116e0..d4c1641 100644 --- a/server/routes/users/@me.ts +++ b/server/routes/users/@me.ts @@ -19,6 +19,7 @@ export default defineEventHandler(async event => { id: user.id, publicKey: user.public_key, namespace: user.namespace, + nickname: user.nickname, profile: user.profile, permissions: user.permissions, }, diff --git a/server/routes/users/[id]/index.ts b/server/routes/users/[id]/index.ts index 9dedab1..bfa1ccd 100644 --- a/server/routes/users/[id]/index.ts +++ b/server/routes/users/[id]/index.ts @@ -9,7 +9,8 @@ const userProfileSchema = z.object({ icon: z.string(), colorA: z.string(), colorB: z.string(), - }), + }).optional(), + nickname: z.string().min(1).max(255).optional(), }); export default defineEventHandler(async event => { @@ -31,11 +32,17 @@ export default defineEventHandler(async event => { const validatedBody = userProfileSchema.parse(body); + const updateData: any = {}; + if (validatedBody.profile) { + updateData.profile = validatedBody.profile; + } + if (validatedBody.nickname !== undefined) { + updateData.nickname = validatedBody.nickname; + } + const user = await prisma.users.update({ where: { id: userId }, - data: { - profile: validatedBody.profile, - }, + data: updateData, }); log.info('User profile updated successfully', { userId }); @@ -44,6 +51,7 @@ export default defineEventHandler(async event => { id: user.id, publicKey: user.public_key, namespace: user.namespace, + nickname: (user as any).nickname, profile: user.profile, permissions: user.permissions, createdAt: user.created_at, diff --git a/server/utils/nickname.ts b/server/utils/nickname.ts new file mode 100644 index 0000000..91ebd27 --- /dev/null +++ b/server/utils/nickname.ts @@ -0,0 +1,22 @@ +const adjectives = [ + 'Cool', 'Swift', 'Bright', 'Silent', 'Quick', 'Brave', 'Clever', 'Wise', 'Bold', 'Calm', + 'Wild', 'Free', 'Sharp', 'Soft', 'Hard', 'Light', 'Dark', 'Fast', 'Slow', 'High', + 'Low', 'Deep', 'Shallow', 'Wide', 'Narrow', 'Long', 'Short', 'Big', 'Small', 'Hot', + 'Cold', 'Warm', 'Wet', 'Dry', 'Sweet', 'Sour', 'Bitter', 'Salty', 'Fresh', 'Stale', + 'New', 'Old', 'Young', 'Mature', 'Happy', 'Sad', 'Angry', 'Calm', 'Excited', 'Bored' +]; + +const nouns = [ + 'Eagle', 'Wolf', 'Bear', 'Lion', 'Tiger', 'Shark', 'Falcon', 'Hawk', 'Owl', 'Raven', + 'Fox', 'Cat', 'Dog', 'Horse', 'Deer', 'Rabbit', 'Mouse', 'Bird', 'Fish', 'Snake', + 'Turtle', 'Frog', 'Butterfly', 'Bee', 'Ant', 'Spider', 'Dragon', 'Phoenix', 'Unicorn', + 'Griffin', 'Wizard', 'Knight', 'Warrior', 'Hunter', 'Explorer', 'Adventurer', 'Pirate', + 'Ninja', 'Samurai', 'Ranger', 'Scout', 'Pilot', 'Captain', 'Commander', 'Leader', + 'Hero', 'Champion', 'Master', 'Legend' +]; + +export function generateRandomNickname(): string { + const adjective = adjectives[Math.floor(Math.random() * adjectives.length)]; + const noun = nouns[Math.floor(Math.random() * nouns.length)]; + return `${adjective} ${noun}`; +}