This commit is contained in:
2026-01-04 20:58:47 +09:00
parent a87c11597a
commit 0660ed3973
37 changed files with 1723 additions and 885 deletions

View File

@@ -0,0 +1,37 @@
import { query } from '../../utils/db'
/**
* 본인 로그인 이력 조회
* GET /api/auth/login-history
*/
export default defineEventHandler(async (event) => {
const userId = getCookie(event, 'user_id')
if (!userId) {
throw createError({ statusCode: 401, message: '로그인이 필요합니다.' })
}
const history = await query<any>(`
SELECT
history_id,
login_at,
login_ip,
logout_at,
logout_ip,
last_active_at
FROM wr_login_history
WHERE employee_id = $1
ORDER BY login_at DESC
LIMIT 50
`, [userId])
return {
history: history.map(h => ({
historyId: h.history_id,
loginAt: h.login_at,
loginIp: h.login_ip,
logoutAt: h.logout_at,
logoutIp: h.logout_ip,
lastActiveAt: h.last_active_at
}))
}
})

View File

@@ -1,4 +1,5 @@
import { query, insertReturning, execute } from '../../utils/db'
import { getClientIp } from '../../utils/ip'
interface LoginBody {
email: string
@@ -11,6 +12,7 @@ interface LoginBody {
*/
export default defineEventHandler(async (event) => {
const body = await readBody<LoginBody>(event)
const clientIp = getClientIp(event)
if (!body.email || !body.name) {
throw createError({ statusCode: 400, message: '이메일과 이름을 입력해주세요.' })
@@ -22,31 +24,52 @@ export default defineEventHandler(async (event) => {
throw createError({ statusCode: 400, message: '올바른 이메일 형식이 아닙니다.' })
}
// 기존 사원 조회
const emailLower = body.email.toLowerCase()
const nameTrimmed = body.name.trim()
// 기존 직원 조회
let employee = await query<any>(`
SELECT * FROM wr_employee_info WHERE employee_email = $1
`, [body.email.toLowerCase()])
`, [emailLower])
let employeeData = employee[0]
// 없으면 자동 등록
if (!employeeData) {
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)
VALUES ($1, $2)
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 *
`, [body.name, body.email.toLowerCase()])
`, [nameTrimmed, emailLower, clientIp])
}
// 로그인 이력 추가
await execute(`
INSERT INTO wr_login_history (employee_id) VALUES ($1)
`, [employeeData.employee_id])
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])
// 쿠키에 사용자 정보 저장 (간단한 임시 세션)
// 쿠키에 사용자 정보 저장
setCookie(event, 'user_id', String(employeeData.employee_id), {
httpOnly: true,
maxAge: 60 * 60 * 24 * 7, // 7일
maxAge: 60 * 60 * 24 * 7,
path: '/'
})
setCookie(event, 'login_history_id', String(loginHistory.history_id), {
httpOnly: true,
maxAge: 60 * 60 * 24 * 7,
path: '/'
})

View File

@@ -1,8 +1,26 @@
import { execute } from '../../utils/db'
import { getClientIp } from '../../utils/ip'
/**
* 로그아웃
* POST /api/auth/logout
*/
export default defineEventHandler(async (event) => {
const historyId = getCookie(event, 'login_history_id')
const clientIp = getClientIp(event)
// 로그아웃 이력 기록
if (historyId) {
await execute(`
UPDATE wr_login_history
SET logout_at = NOW(), logout_ip = $1
WHERE history_id = $2
`, [clientIp, historyId])
}
// 쿠키 삭제
deleteCookie(event, 'user_id')
deleteCookie(event, 'login_history_id')
return { success: true }
})

View File

@@ -0,0 +1,43 @@
import { queryOne } from '../../utils/db'
/**
* 로그인된 사용자 정보 조회
* GET /api/auth/me
*/
export default defineEventHandler(async (event) => {
const userId = getCookie(event, 'user_id')
if (!userId) {
throw createError({ statusCode: 401, message: '로그인이 필요합니다.' })
}
const employee = await queryOne<any>(`
SELECT
employee_id,
employee_name,
employee_email,
employee_phone,
employee_position,
company,
join_date,
is_active
FROM wr_employee_info
WHERE employee_id = $1
`, [userId])
if (!employee) {
throw createError({ statusCode: 404, message: '사용자를 찾을 수 없습니다.' })
}
return {
user: {
employeeId: employee.employee_id,
employeeName: employee.employee_name,
employeeEmail: employee.employee_email,
employeePhone: employee.employee_phone,
employeePosition: employee.employee_position,
company: employee.company,
joinDate: employee.join_date,
isActive: employee.is_active
}
}
})