feat: add email and password change endpoints to profile routes
This commit is contained in:
@@ -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 }),
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user