import { getClientIp } from '../../utils/ip' import { createSession, setSessionCookie } from '../../utils/session' interface LoginBody { email: string name: string } /** * 이메일+이름 로그인 * POST /api/auth/login */ export default defineEventHandler(async (event) => { const body = await readBody(event) const clientIp = getClientIp(event) const userAgent = getHeader(event, 'user-agent') || null if (!body.email || !body.name) { throw createError({ statusCode: 400, message: '이메일과 이름을 입력해주세요.' }) } // 이메일 형식 검증 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ if (!emailRegex.test(body.email)) { throw createError({ statusCode: 400, message: '올바른 이메일 형식이 아닙니다.' }) } const emailLower = body.email.toLowerCase() const nameTrimmed = body.name.trim() // 기존 직원 조회 let employee = await query(` SELECT * FROM wr_employee_info WHERE employee_email = $1 `, [emailLower]) let employeeData = employee[0] if (employeeData) { // 기존 직원 - 이름이 다르면 업데이트 if (employeeData.employee_name !== nameTrimmed) { await execute(` UPDATE wr_employee_info SET employee_name = $1, updated_at = NOW(), updated_ip = $2, updated_email = $3 WHERE employee_id = $4 `, [nameTrimmed, clientIp, emailLower, employeeData.employee_id]) employeeData.employee_name = nameTrimmed } } else { // 신규 직원 자동 등록 employeeData = await insertReturning(` INSERT INTO wr_employee_info (employee_name, employee_email, created_ip, created_email, updated_ip, updated_email) VALUES ($1, $2, $3, $2, $3, $2) RETURNING * `, [nameTrimmed, emailLower, clientIp]) } // 로그인 이력 추가 const loginHistory = await insertReturning(` INSERT INTO wr_login_history (employee_id, login_ip, login_email) VALUES ($1, $2, $3) RETURNING history_id `, [employeeData.employee_id, clientIp, emailLower]) // DB 기반 세션 생성 const sessionId = await createSession( employeeData.employee_id, loginHistory.history_id, clientIp, userAgent ) // 세션 쿠키 설정 setSessionCookie(event, sessionId) return { success: true, user: { employeeId: employeeData.employee_id, employeeName: employeeData.employee_name, employeeEmail: employeeData.employee_email, employeePosition: employeeData.employee_position } } })