import { query, queryOne, execute } from '../../utils/db' import { getClientIp } from '../../utils/ip' import { requireAuth } from '../../utils/session' import { hashPassword, generateTempPassword } from '../../utils/password' interface SetPasswordBody { password?: string employeeId?: number // 관리자가 다른 사용자 설정 시 generateTemp?: boolean // 임시 비밀번호 생성 } /** * 비밀번호 설정 * - 본인: password만 전송 * - 관리자: employeeId + (password 또는 generateTemp) * POST /api/auth/set-password */ export default defineEventHandler(async (event) => { const currentUserId = await requireAuth(event) const body = await readBody(event) const clientIp = getClientIp(event) // 대상 직원 ID 결정 (없으면 본인) let targetEmployeeId = body.employeeId || currentUserId // 다른 사람 비밀번호 설정 시 관리자 권한 확인 if (body.employeeId && body.employeeId !== currentUserId) { const roles = await query(` SELECT r.role_code FROM wr_employee_role er JOIN wr_role r ON er.role_id = r.role_id WHERE er.employee_id = $1 `, [currentUserId]) const isAdmin = roles.some((r: any) => r.role_code === 'ROLE_ADMIN') if (!isAdmin) { throw createError({ statusCode: 403, message: '관리자 권한이 필요합니다.' }) } } // 대상 직원 조회 const targetEmployee = await queryOne(` SELECT employee_id, employee_name, employee_email FROM wr_employee_info WHERE employee_id = $1 `, [targetEmployeeId]) if (!targetEmployee) { throw createError({ statusCode: 404, message: '직원을 찾을 수 없습니다.' }) } // 비밀번호 결정 let password = body.password if (body.generateTemp || !password) { password = generateTempPassword() } if (password.length < 8) { throw createError({ statusCode: 400, message: '비밀번호는 8자 이상이어야 합니다.' }) } // 비밀번호 해시 const hash = await hashPassword(password) // 업데이트 await execute(` UPDATE wr_employee_info SET password_hash = $1, updated_at = NOW(), updated_ip = $2 WHERE employee_id = $3 `, [hash, clientIp, targetEmployeeId]) return { success: true, employeeId: targetEmployee.employee_id, employeeName: targetEmployee.employee_name, tempPassword: body.generateTemp ? password : undefined, message: body.generateTemp ? '임시 비밀번호가 생성되었습니다.' : '비밀번호가 설정되었습니다.' } })