import { query, execute } from '../../utils/db' import { hashPassword, generateTempPassword } from '../../utils/password' import { sendTempPasswordEmail } from '../../utils/email' import { getClientIp } from '../../utils/ip' interface ResetPasswordBody { email: string name: string phone: string } /** * 비밀번호 찾기 (임시 비밀번호 발급) * POST /api/auth/reset-password */ export default defineEventHandler(async (event) => { const body = await readBody(event) const clientIp = getClientIp(event) if (!body.email || !body.name || !body.phone) { throw createError({ statusCode: 400, message: '이메일, 이름, 휴대폰 번호를 입력해주세요.' }) } const emailLower = body.email.toLowerCase() const nameTrimmed = body.name.trim() // 사용자 조회 (이메일 + 이름 + 핸드폰) // 이메일: 양쪽 모두 소문자로 비교 // 핸드폰: 양쪽 모두 숫자만 추출해서 비교 const sql = ` SELECT * FROM wr_employee_info WHERE LOWER(employee_email) = $1 AND employee_name = $2 AND REGEXP_REPLACE(employee_phone, '[^0-9]', '', 'g') = $3 ` const phoneClean = body.phone.replace(/[^0-9]/g, '') const params: any[] = [emailLower, nameTrimmed, phoneClean] const employees = await query(sql, params) if (employees.length === 0) { // 보안상 동일한 메시지 반환 throw createError({ statusCode: 400, message: '입력하신 정보와 일치하는 계정을 찾을 수 없습니다.' }) } const employee = employees[0] // 임시 비밀번호 생성 const tempPassword = generateTempPassword() const hash = await hashPassword(tempPassword) // 비밀번호 업데이트 await execute(` UPDATE wr_employee_info SET password_hash = $1, updated_at = NOW(), updated_ip = $2 WHERE employee_id = $3 `, [hash, clientIp, employee.employee_id]) // 이메일 발송 const emailSent = await sendTempPasswordEmail( employee.employee_email, employee.employee_name, tempPassword ) if (!emailSent) { // 이메일 발송 실패해도 비밀번호는 이미 변경됨 console.warn('임시 비밀번호 이메일 발송 실패:', employee.employee_email) } // 보안상 이메일 일부만 표시 const maskedEmail = employee.employee_email.replace(/(.{2})(.*)(@.*)/, '$1***$3') return { success: true, message: `임시 비밀번호가 ${maskedEmail}로 발송되었습니다.`, emailSent } })