import { resetUserPassword, getUserByUsername, deleteAllUserSessions, getDatabase } from '~/server/utils/database' import { getSessionUsername } from '~/server/utils/auth' export default defineEventHandler(async (event) => { const username = await getSessionUsername(event) if (!username) { throw createError({ statusCode: 401, message: 'Unauthorized' }) } const user = getUserByUsername(username) if (!user || user.is_admin !== 1) { throw createError({ statusCode: 403, message: 'Forbidden - Admin access required' }) } const id = parseInt(event.context.params?.id || '') const body = await readBody(event) const { newPassword } = body if (isNaN(id)) { throw createError({ statusCode: 400, message: 'Invalid user ID' }) } if (!newPassword || typeof newPassword !== 'string') { throw createError({ statusCode: 400, message: 'New password is required' }) } // Validate password strength if (newPassword.length < 8) { throw createError({ statusCode: 400, message: 'Password must be at least 8 characters long' }) } if (!/[A-Z]/.test(newPassword)) { throw createError({ statusCode: 400, message: 'Password must contain at least one uppercase letter' }) } if (!/[a-z]/.test(newPassword)) { throw createError({ statusCode: 400, message: 'Password must contain at least one lowercase letter' }) } if (!/[0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(newPassword)) { throw createError({ statusCode: 400, message: 'Password must contain at least one number or symbol' }) } try { // Get the target user's username before resetting password const db = getDatabase() const targetUser = db.prepare('SELECT username FROM users WHERE id = ?').get(id) as { username: string } | undefined if (!targetUser) { throw createError({ statusCode: 404, message: 'User not found' }) } // Reset the password resetUserPassword(id, newPassword) // SECURITY: Invalidate ALL sessions when admin resets a user's password // This prevents session fixation and forces user to log in with new password deleteAllUserSessions(targetUser.username) return { success: true, message: 'Password reset successfully. User will need to log in with the new password.' } } catch (error: any) { // Re-throw createError instances if (error.statusCode) { throw error } throw createError({ statusCode: 500, message: 'Failed to reset password' }) } })