Add PostgreSQL and Redis integration for users and sessions Implement password and WebAuthn passkey login flows Add Docker stack, super-admin seeding, and protected routes
61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import { MIN_PASSWORD_LENGTH } from '~~/shared/auth'
|
|
|
|
import { requireAuth } from '../../utils/auth'
|
|
import { hashPassword, verifyPassword } from '../../utils/password'
|
|
import { getUserById, updateUserPassword } from '../../utils/user-repository'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const auth = await requireAuth(event)
|
|
const body = await readBody<{
|
|
currentPassword?: string
|
|
newPassword?: string
|
|
}>(event)
|
|
|
|
const currentPassword = body.currentPassword?.trim() || ''
|
|
const newPassword = body.newPassword?.trim() || ''
|
|
|
|
if (!currentPassword || !newPassword) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Current password and new password are required'
|
|
})
|
|
}
|
|
|
|
if (newPassword.length < MIN_PASSWORD_LENGTH) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: `New password must be at least ${MIN_PASSWORD_LENGTH} characters`
|
|
})
|
|
}
|
|
|
|
if (currentPassword === newPassword) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'New password must be different from the current password'
|
|
})
|
|
}
|
|
|
|
const currentPasswordMatches = await verifyPassword(currentPassword, auth.user.passwordHash)
|
|
|
|
if (!currentPasswordMatches) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Current password is incorrect'
|
|
})
|
|
}
|
|
|
|
const passwordHash = await hashPassword(newPassword)
|
|
|
|
await updateUserPassword({
|
|
userId: auth.user.id,
|
|
passwordHash,
|
|
mustChangePassword: false
|
|
})
|
|
|
|
const updatedUser = await getUserById(auth.user.id)
|
|
|
|
return {
|
|
user: updatedUser
|
|
}
|
|
})
|