feat: add email and password change endpoints to profile routes

This commit is contained in:
2026-01-28 21:55:39 +00:00
parent 702156c406
commit 8abad1a242

View File

@@ -1,7 +1,7 @@
import { Elysia, t } from 'elysia';
import { db } from '../db';
import { users, userProfiles } from '../db/schema';
import { eq } from 'drizzle-orm';
import { users, userProfiles, accounts } from '../db/schema';
import { eq, and } from 'drizzle-orm';
import type { User } from '../lib/auth';
export const profileRoutes = new Elysia({ prefix: '/profile' })
@@ -96,4 +96,76 @@ export const profileRoutes = new Elysia({ prefix: '/profile' })
phone: t.Optional(t.String()),
emailSignature: t.Optional(t.String()),
}),
})
// Change email
.put('/email', async ({ body, user, set }: {
body: { newEmail: string };
user: User;
set: any;
}) => {
// Check if email is already taken
const [existing] = await db.select({ id: users.id })
.from(users)
.where(eq(users.email, body.newEmail))
.limit(1);
if (existing && existing.id !== user.id) {
set.status = 400;
throw new Error('Email is already in use');
}
await db.update(users)
.set({ email: body.newEmail, updatedAt: new Date() })
.where(eq(users.id, user.id));
return { success: true, email: body.newEmail };
}, {
body: t.Object({
newEmail: t.String({ format: 'email' }),
}),
})
// Change password
.put('/password', async ({ body, user, set }: {
body: { currentPassword: string; newPassword: string };
user: User;
set: any;
}) => {
// Get current password hash from accounts table
const [account] = await db.select({ password: accounts.password })
.from(accounts)
.where(and(
eq(accounts.userId, user.id),
eq(accounts.providerId, 'credential'),
))
.limit(1);
if (!account?.password) {
set.status = 400;
throw new Error('No password set for this account');
}
// Verify current password
const isValid = await Bun.password.verify(body.currentPassword, account.password);
if (!isValid) {
set.status = 400;
throw new Error('Current password is incorrect');
}
// Hash and update new password
const hashedPassword = await Bun.password.hash(body.newPassword, { algorithm: 'bcrypt', cost: 10 });
await db.update(accounts)
.set({ password: hashedPassword, updatedAt: new Date() })
.where(and(
eq(accounts.userId, user.id),
eq(accounts.providerId, 'credential'),
));
return { success: true };
}, {
body: t.Object({
currentPassword: t.String(),
newPassword: t.String({ minLength: 8 }),
}),
});