권한, 사용자, 메뉴 등에 대한 기능 업데이트
This commit is contained in:
44
backend/api/admin/menu/[id]/toggle-role.post.ts
Normal file
44
backend/api/admin/menu/[id]/toggle-role.post.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { queryOne, execute } from '../../../../utils/db'
|
||||
import { requireAdmin } from '../../../../utils/session'
|
||||
|
||||
/**
|
||||
* 메뉴 권한 토글
|
||||
* POST /api/admin/menu/[id]/toggle-role
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const menuId = getRouterParam(event, 'id')
|
||||
const body = await readBody(event)
|
||||
const { roleId, enabled } = body
|
||||
|
||||
if (!roleId) {
|
||||
throw createError({ statusCode: 400, message: '권한 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
// 메뉴 존재 확인
|
||||
const menu = await queryOne<any>(`
|
||||
SELECT menu_id FROM wr_menu WHERE menu_id = $1
|
||||
`, [menuId])
|
||||
|
||||
if (!menu) {
|
||||
throw createError({ statusCode: 404, message: '메뉴를 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
// 권한 추가
|
||||
await execute(`
|
||||
INSERT INTO wr_menu_role (menu_id, role_id)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT (menu_id, role_id) DO NOTHING
|
||||
`, [menuId, roleId])
|
||||
} else {
|
||||
// 권한 제거
|
||||
await execute(`
|
||||
DELETE FROM wr_menu_role
|
||||
WHERE menu_id = $1 AND role_id = $2
|
||||
`, [menuId, roleId])
|
||||
}
|
||||
|
||||
return { success: true }
|
||||
})
|
||||
73
backend/api/admin/menu/list.get.ts
Normal file
73
backend/api/admin/menu/list.get.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { query } from '../../../utils/db'
|
||||
import { requireAdmin } from '../../../utils/session'
|
||||
|
||||
/**
|
||||
* 메뉴 목록 조회 (권한 포함)
|
||||
* GET /api/admin/menu/list
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
// 메뉴 목록 조회
|
||||
const menus = await query<any>(`
|
||||
SELECT
|
||||
m.menu_id,
|
||||
m.menu_code,
|
||||
m.menu_name,
|
||||
m.menu_path,
|
||||
m.menu_icon,
|
||||
m.parent_menu_id,
|
||||
m.sort_order,
|
||||
m.is_active,
|
||||
m.created_at,
|
||||
m.updated_at,
|
||||
pm.menu_name AS parent_menu_name
|
||||
FROM wr_menu m
|
||||
LEFT JOIN wr_menu pm ON m.parent_menu_id = pm.menu_id
|
||||
ORDER BY m.parent_menu_id NULLS FIRST, m.sort_order
|
||||
`)
|
||||
|
||||
// 권한 목록 조회
|
||||
const roles = await query<any>(`
|
||||
SELECT role_id, role_code, role_name
|
||||
FROM wr_role
|
||||
ORDER BY role_id
|
||||
`)
|
||||
|
||||
// 메뉴-권한 매핑 조회
|
||||
const menuRoles = await query<any>(`
|
||||
SELECT menu_id, role_id
|
||||
FROM wr_menu_role
|
||||
`)
|
||||
|
||||
// 메뉴별 권한 매핑 정리
|
||||
const menuRoleMap: Record<number, number[]> = {}
|
||||
for (const mr of menuRoles) {
|
||||
if (!menuRoleMap[mr.menu_id]) {
|
||||
menuRoleMap[mr.menu_id] = []
|
||||
}
|
||||
menuRoleMap[mr.menu_id].push(mr.role_id)
|
||||
}
|
||||
|
||||
return {
|
||||
menus: menus.map(m => ({
|
||||
menuId: m.menu_id,
|
||||
menuCode: m.menu_code,
|
||||
menuName: m.menu_name,
|
||||
menuPath: m.menu_path,
|
||||
menuIcon: m.menu_icon,
|
||||
parentMenuId: m.parent_menu_id,
|
||||
parentMenuName: m.parent_menu_name,
|
||||
sortOrder: m.sort_order,
|
||||
isActive: m.is_active,
|
||||
createdAt: m.created_at,
|
||||
updatedAt: m.updated_at,
|
||||
roleIds: menuRoleMap[m.menu_id] || []
|
||||
})),
|
||||
roles: roles.map((r: any) => ({
|
||||
roleId: r.role_id,
|
||||
roleCode: r.role_code,
|
||||
roleName: r.role_name
|
||||
}))
|
||||
}
|
||||
})
|
||||
46
backend/api/admin/role/[id]/delete.delete.ts
Normal file
46
backend/api/admin/role/[id]/delete.delete.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { queryOne, execute } from '../../../../utils/db'
|
||||
import { requireAdmin } from '../../../../utils/session'
|
||||
|
||||
/**
|
||||
* 권한 삭제
|
||||
* DELETE /api/admin/role/[id]/delete
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const roleId = getRouterParam(event, 'id')
|
||||
if (!roleId) {
|
||||
throw createError({ statusCode: 400, message: '권한 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
// 존재 여부 확인
|
||||
const existing = await queryOne<any>(`
|
||||
SELECT role_id, role_code FROM wr_role WHERE role_id = $1
|
||||
`, [roleId])
|
||||
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, message: '권한을 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 기본 권한은 삭제 불가
|
||||
const protectedCodes = ['ROLE_ADMIN', 'ROLE_MANAGER', 'ROLE_USER']
|
||||
if (protectedCodes.includes(existing.role_code)) {
|
||||
throw createError({ statusCode: 400, message: '기본 권한은 삭제할 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 사용 중인 권한인지 확인
|
||||
const usageCount = await queryOne<any>(`
|
||||
SELECT COUNT(*) as cnt FROM wr_employee_role WHERE role_id = $1
|
||||
`, [roleId])
|
||||
|
||||
if (parseInt(usageCount.cnt) > 0) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
message: `${usageCount.cnt}명의 사용자가 이 권한을 사용 중입니다. 먼저 권한을 해제해주세요.`
|
||||
})
|
||||
}
|
||||
|
||||
await execute(`DELETE FROM wr_role WHERE role_id = $1`, [roleId])
|
||||
|
||||
return { success: true }
|
||||
})
|
||||
54
backend/api/admin/role/[id]/update.put.ts
Normal file
54
backend/api/admin/role/[id]/update.put.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { queryOne, execute } from '../../../../utils/db'
|
||||
import { requireAdmin } from '../../../../utils/session'
|
||||
|
||||
/**
|
||||
* 권한 수정
|
||||
* PUT /api/admin/role/[id]/update
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const roleId = getRouterParam(event, 'id')
|
||||
if (!roleId) {
|
||||
throw createError({ statusCode: 400, message: '권한 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
const body = await readBody<{
|
||||
roleName?: string
|
||||
roleDescription?: string
|
||||
isInternalIpOnly?: boolean
|
||||
sortOrder?: number
|
||||
isActive?: boolean
|
||||
}>(event)
|
||||
|
||||
// 존재 여부 확인
|
||||
const existing = await queryOne<any>(`
|
||||
SELECT role_id, role_code FROM wr_role WHERE role_id = $1
|
||||
`, [roleId])
|
||||
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, message: '권한을 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
await execute(`
|
||||
UPDATE wr_role SET
|
||||
role_name = COALESCE($2, role_name),
|
||||
role_description = COALESCE($3, role_description),
|
||||
is_internal_ip_only = COALESCE($4, is_internal_ip_only),
|
||||
sort_order = COALESCE($5, sort_order),
|
||||
is_active = COALESCE($6, is_active),
|
||||
updated_at = NOW()
|
||||
WHERE role_id = $1
|
||||
`, [
|
||||
roleId,
|
||||
body.roleName,
|
||||
body.roleDescription,
|
||||
body.isInternalIpOnly,
|
||||
body.sortOrder,
|
||||
body.isActive
|
||||
])
|
||||
|
||||
const updated = await queryOne<any>(`SELECT * FROM wr_role WHERE role_id = $1`, [roleId])
|
||||
|
||||
return { success: true, role: updated }
|
||||
})
|
||||
45
backend/api/admin/role/create.post.ts
Normal file
45
backend/api/admin/role/create.post.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { queryOne } from '../../../utils/db'
|
||||
import { requireAdmin } from '../../../utils/session'
|
||||
|
||||
/**
|
||||
* 권한 생성
|
||||
* POST /api/admin/role/create
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const body = await readBody<{
|
||||
roleCode: string
|
||||
roleName: string
|
||||
roleDescription?: string
|
||||
isInternalIpOnly?: boolean
|
||||
sortOrder?: number
|
||||
}>(event)
|
||||
|
||||
if (!body.roleCode || !body.roleName) {
|
||||
throw createError({ statusCode: 400, message: '권한코드와 권한명은 필수입니다.' })
|
||||
}
|
||||
|
||||
// 코드 중복 체크
|
||||
const existing = await queryOne<any>(`
|
||||
SELECT role_id FROM wr_role WHERE role_code = $1
|
||||
`, [body.roleCode])
|
||||
|
||||
if (existing) {
|
||||
throw createError({ statusCode: 400, message: '이미 존재하는 권한코드입니다.' })
|
||||
}
|
||||
|
||||
const role = await queryOne<any>(`
|
||||
INSERT INTO wr_role (role_code, role_name, role_description, is_internal_ip_only, sort_order)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *
|
||||
`, [
|
||||
body.roleCode,
|
||||
body.roleName,
|
||||
body.roleDescription || null,
|
||||
body.isInternalIpOnly || false,
|
||||
body.sortOrder || 0
|
||||
])
|
||||
|
||||
return { success: true, role }
|
||||
})
|
||||
34
backend/api/admin/role/list.get.ts
Normal file
34
backend/api/admin/role/list.get.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { query } from '../../../utils/db'
|
||||
import { requireAdmin } from '../../../utils/session'
|
||||
|
||||
/**
|
||||
* 권한 목록 조회
|
||||
* GET /api/admin/role/list
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
// 관리자 권한 체크
|
||||
await requireAdmin(event)
|
||||
|
||||
const roles = await query<any>(`
|
||||
SELECT
|
||||
r.role_id,
|
||||
r.role_code,
|
||||
r.role_name,
|
||||
r.role_description,
|
||||
r.is_internal_ip_only,
|
||||
r.sort_order,
|
||||
r.is_active,
|
||||
r.created_at,
|
||||
r.updated_at,
|
||||
COUNT(DISTINCT er.employee_id) as user_count
|
||||
FROM wr_role r
|
||||
LEFT JOIN wr_employee_role er ON r.role_id = er.role_id
|
||||
GROUP BY r.role_id
|
||||
ORDER BY r.sort_order, r.role_id
|
||||
`)
|
||||
|
||||
return {
|
||||
roles,
|
||||
total: roles.length
|
||||
}
|
||||
})
|
||||
55
backend/api/admin/user/[id]/roles.put.ts
Normal file
55
backend/api/admin/user/[id]/roles.put.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { query, queryOne, execute } from '../../../../utils/db'
|
||||
import { requireAdmin } from '../../../../utils/session'
|
||||
|
||||
/**
|
||||
* 사용자 권한 변경
|
||||
* PUT /api/admin/user/[id]/roles
|
||||
*
|
||||
* Body: { roleIds: number[] }
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const employeeId = getRouterParam(event, 'id')
|
||||
if (!employeeId) {
|
||||
throw createError({ statusCode: 400, message: '사용자 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
const body = await readBody<{ roleIds: number[] }>(event)
|
||||
const roleIds = body.roleIds || []
|
||||
|
||||
// 사용자 존재 확인
|
||||
const user = await queryOne<any>(`
|
||||
SELECT employee_id, employee_email FROM wr_employee_info WHERE employee_id = $1
|
||||
`, [employeeId])
|
||||
|
||||
if (!user) {
|
||||
throw createError({ statusCode: 404, message: '사용자를 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 기존 권한 모두 삭제
|
||||
await execute(`DELETE FROM wr_employee_role WHERE employee_id = $1`, [employeeId])
|
||||
|
||||
// 새 권한 추가
|
||||
for (const roleId of roleIds) {
|
||||
await execute(`
|
||||
INSERT INTO wr_employee_role (employee_id, role_id)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT (employee_id, role_id) DO NOTHING
|
||||
`, [employeeId, roleId])
|
||||
}
|
||||
|
||||
// 변경된 권한 조회
|
||||
const updatedRoles = await query<any>(`
|
||||
SELECT r.role_id, r.role_code, r.role_name
|
||||
FROM wr_employee_role er
|
||||
JOIN wr_role r ON er.role_id = r.role_id
|
||||
WHERE er.employee_id = $1
|
||||
`, [employeeId])
|
||||
|
||||
return {
|
||||
success: true,
|
||||
employeeId: parseInt(employeeId as string),
|
||||
roles: updatedRoles
|
||||
}
|
||||
})
|
||||
70
backend/api/admin/user/[id]/toggle-role.post.ts
Normal file
70
backend/api/admin/user/[id]/toggle-role.post.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { queryOne, execute } from '../../../../utils/db'
|
||||
import { requireAdmin } from '../../../../utils/session'
|
||||
|
||||
/**
|
||||
* 사용자 개별 권한 토글 (추가/제거)
|
||||
* POST /api/admin/user/[id]/toggle-role
|
||||
*
|
||||
* Body: { roleId: number }
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const employeeId = getRouterParam(event, 'id')
|
||||
if (!employeeId) {
|
||||
throw createError({ statusCode: 400, message: '사용자 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
const body = await readBody<{ roleId: number }>(event)
|
||||
if (!body.roleId) {
|
||||
throw createError({ statusCode: 400, message: '권한 ID가 필요합니다.' })
|
||||
}
|
||||
|
||||
// 사용자 존재 확인
|
||||
const user = await queryOne<any>(`
|
||||
SELECT employee_id FROM wr_employee_info WHERE employee_id = $1
|
||||
`, [employeeId])
|
||||
|
||||
if (!user) {
|
||||
throw createError({ statusCode: 404, message: '사용자를 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 권한 존재 확인
|
||||
const role = await queryOne<any>(`
|
||||
SELECT role_id, role_code FROM wr_role WHERE role_id = $1
|
||||
`, [body.roleId])
|
||||
|
||||
if (!role) {
|
||||
throw createError({ statusCode: 404, message: '권한을 찾을 수 없습니다.' })
|
||||
}
|
||||
|
||||
// 현재 권한 보유 여부 확인
|
||||
const existing = await queryOne<any>(`
|
||||
SELECT employee_role_id FROM wr_employee_role
|
||||
WHERE employee_id = $1 AND role_id = $2
|
||||
`, [employeeId, body.roleId])
|
||||
|
||||
let added: boolean
|
||||
|
||||
if (existing) {
|
||||
// 권한 제거
|
||||
await execute(`
|
||||
DELETE FROM wr_employee_role WHERE employee_id = $1 AND role_id = $2
|
||||
`, [employeeId, body.roleId])
|
||||
added = false
|
||||
} else {
|
||||
// 권한 추가
|
||||
await execute(`
|
||||
INSERT INTO wr_employee_role (employee_id, role_id) VALUES ($1, $2)
|
||||
`, [employeeId, body.roleId])
|
||||
added = true
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
employeeId: parseInt(employeeId as string),
|
||||
roleId: body.roleId,
|
||||
roleCode: role.role_code,
|
||||
added
|
||||
}
|
||||
})
|
||||
110
backend/api/admin/user/list.get.ts
Normal file
110
backend/api/admin/user/list.get.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { query } from '../../../utils/db'
|
||||
import { requireAdmin } from '../../../utils/session'
|
||||
|
||||
/**
|
||||
* 사용자 목록 조회 (권한 정보 + 최근 로그인 포함)
|
||||
* GET /api/admin/user/list
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
await requireAdmin(event)
|
||||
|
||||
const queryParams = getQuery(event)
|
||||
const company = queryParams.company as string || ''
|
||||
const name = queryParams.name as string || ''
|
||||
const email = queryParams.email as string || ''
|
||||
const phone = queryParams.phone as string || ''
|
||||
const status = queryParams.status as string || 'active' // 기본값: 활성
|
||||
|
||||
// 1. 사용자 목록 조회 (최근 로그인 포함)
|
||||
let userQuery = `
|
||||
SELECT
|
||||
e.employee_id,
|
||||
e.employee_name,
|
||||
e.employee_email,
|
||||
e.employee_phone,
|
||||
e.employee_position,
|
||||
e.company,
|
||||
e.join_date,
|
||||
e.is_active,
|
||||
e.created_at,
|
||||
(
|
||||
SELECT MAX(login_at)
|
||||
FROM wr_login_history
|
||||
WHERE employee_id = e.employee_id
|
||||
) as last_login_at
|
||||
FROM wr_employee_info e
|
||||
WHERE 1=1
|
||||
`
|
||||
const params: any[] = []
|
||||
|
||||
// 소속사 검색
|
||||
if (company) {
|
||||
params.push(`%${company}%`)
|
||||
userQuery += ` AND e.company ILIKE $${params.length}`
|
||||
}
|
||||
|
||||
// 이름 검색
|
||||
if (name) {
|
||||
params.push(`%${name}%`)
|
||||
userQuery += ` AND e.employee_name ILIKE $${params.length}`
|
||||
}
|
||||
|
||||
// 이메일 검색
|
||||
if (email) {
|
||||
params.push(`%${email}%`)
|
||||
userQuery += ` AND e.employee_email ILIKE $${params.length}`
|
||||
}
|
||||
|
||||
// 전화번호 검색
|
||||
if (phone) {
|
||||
params.push(`%${phone}%`)
|
||||
userQuery += ` AND e.employee_phone ILIKE $${params.length}`
|
||||
}
|
||||
|
||||
// 상태 검색
|
||||
if (status === 'active') {
|
||||
userQuery += ` AND e.is_active = true`
|
||||
} else if (status === 'inactive') {
|
||||
userQuery += ` AND e.is_active = false`
|
||||
}
|
||||
// status === 'all' 이면 조건 없음
|
||||
|
||||
userQuery += ` ORDER BY e.company, e.employee_position, e.employee_name`
|
||||
|
||||
const users = await query<any>(userQuery, params)
|
||||
|
||||
// 2. 모든 권한 목록 조회
|
||||
const roles = await query<any>(`
|
||||
SELECT role_id, role_code, role_name, sort_order
|
||||
FROM wr_role
|
||||
WHERE is_active = true
|
||||
ORDER BY sort_order
|
||||
`)
|
||||
|
||||
// 3. 사용자별 권한 매핑 조회
|
||||
const userRoles = await query<any>(`
|
||||
SELECT employee_id, role_id
|
||||
FROM wr_employee_role
|
||||
`)
|
||||
|
||||
// 4. 사용자별 권한 배열 생성
|
||||
const userRoleMap = new Map<number, number[]>()
|
||||
for (const ur of userRoles) {
|
||||
if (!userRoleMap.has(ur.employee_id)) {
|
||||
userRoleMap.set(ur.employee_id, [])
|
||||
}
|
||||
userRoleMap.get(ur.employee_id)!.push(ur.role_id)
|
||||
}
|
||||
|
||||
// 5. 사용자 데이터에 권한 정보 추가
|
||||
const usersWithRoles = users.map(u => ({
|
||||
...u,
|
||||
roleIds: userRoleMap.get(u.employee_id) || []
|
||||
}))
|
||||
|
||||
return {
|
||||
users: usersWithRoles,
|
||||
roles,
|
||||
total: users.length
|
||||
}
|
||||
})
|
||||
@@ -1,7 +1,8 @@
|
||||
import { getSession, refreshSession, getSessionIdFromCookie, deleteSessionCookie } from '../../utils/session'
|
||||
import { getDbSession, refreshSession, getSessionIdFromCookie, deleteSessionCookie, getUserRoles } from '../../utils/session'
|
||||
import { queryOne, execute, query } from '../../utils/db'
|
||||
|
||||
/**
|
||||
* 현재 로그인 사용자 정보
|
||||
* 현재 로그인 사용자 정보 (권한 포함)
|
||||
* GET /api/auth/current-user
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
@@ -43,12 +44,16 @@ export default defineEventHandler(async (event) => {
|
||||
`, [session.loginHistoryId])
|
||||
}
|
||||
|
||||
// 사용자 권한 조회
|
||||
const roles = await getUserRoles(employee.employee_id)
|
||||
|
||||
return {
|
||||
user: {
|
||||
employeeId: employee.employee_id,
|
||||
employeeName: employee.employee_name,
|
||||
employeeEmail: employee.employee_email,
|
||||
employeePosition: employee.employee_position
|
||||
employeePosition: employee.employee_position,
|
||||
roles // 권한 코드 배열 추가
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -28,7 +28,11 @@ export default defineEventHandler(async (event) => {
|
||||
employee_position,
|
||||
company,
|
||||
join_date,
|
||||
is_active
|
||||
is_active,
|
||||
created_at,
|
||||
created_ip,
|
||||
updated_at,
|
||||
updated_ip
|
||||
FROM wr_employee_info
|
||||
WHERE employee_id = $1
|
||||
`, [session.employeeId])
|
||||
@@ -46,7 +50,11 @@ export default defineEventHandler(async (event) => {
|
||||
employeePosition: employee.employee_position,
|
||||
company: employee.company,
|
||||
joinDate: employee.join_date,
|
||||
isActive: employee.is_active
|
||||
isActive: employee.is_active,
|
||||
createdAt: employee.created_at,
|
||||
createdIp: employee.created_ip,
|
||||
updatedAt: employee.updated_at,
|
||||
updatedIp: employee.updated_ip
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
80
backend/api/auth/menu.get.ts
Normal file
80
backend/api/auth/menu.get.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { query } from '../../utils/db'
|
||||
import { getDbSession, getSessionIdFromCookie } from '../../utils/session'
|
||||
|
||||
/**
|
||||
* 현재 사용자 접근 가능 메뉴 조회
|
||||
* GET /api/auth/menu
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const sessionId = getSessionIdFromCookie(event)
|
||||
|
||||
if (!sessionId) {
|
||||
throw createError({ statusCode: 401, message: '로그인이 필요합니다.' })
|
||||
}
|
||||
|
||||
const session = await getDbSession(sessionId)
|
||||
|
||||
if (!session) {
|
||||
throw createError({ statusCode: 401, message: '세션이 만료되었습니다.' })
|
||||
}
|
||||
|
||||
// 사용자의 권한 목록 조회
|
||||
const userRoles = await query<any>(`
|
||||
SELECT r.role_id, r.role_code
|
||||
FROM wr_employee_role er
|
||||
JOIN wr_role r ON er.role_id = r.role_id
|
||||
WHERE er.employee_id = $1
|
||||
`, [session.employeeId])
|
||||
|
||||
const roleIds = userRoles.map(r => r.role_id)
|
||||
|
||||
if (roleIds.length === 0) {
|
||||
return { menus: [] }
|
||||
}
|
||||
|
||||
// 접근 가능한 메뉴 조회
|
||||
const menus = await query<any>(`
|
||||
SELECT DISTINCT
|
||||
m.menu_id,
|
||||
m.menu_code,
|
||||
m.menu_name,
|
||||
m.menu_path,
|
||||
m.menu_icon,
|
||||
m.parent_menu_id,
|
||||
m.sort_order
|
||||
FROM wr_menu m
|
||||
JOIN wr_menu_role mr ON m.menu_id = mr.menu_id
|
||||
WHERE mr.role_id = ANY($1)
|
||||
AND m.is_active = true
|
||||
ORDER BY m.parent_menu_id NULLS FIRST, m.sort_order
|
||||
`, [roleIds])
|
||||
|
||||
// 계층 구조로 변환
|
||||
const menuMap = new Map<number, any>()
|
||||
const rootMenus: any[] = []
|
||||
|
||||
for (const m of menus) {
|
||||
const menuItem = {
|
||||
menuId: m.menu_id,
|
||||
menuCode: m.menu_code,
|
||||
menuName: m.menu_name,
|
||||
menuPath: m.menu_path,
|
||||
menuIcon: m.menu_icon,
|
||||
parentMenuId: m.parent_menu_id,
|
||||
sortOrder: m.sort_order,
|
||||
children: []
|
||||
}
|
||||
menuMap.set(m.menu_id, menuItem)
|
||||
}
|
||||
|
||||
for (const m of menus) {
|
||||
const menuItem = menuMap.get(m.menu_id)
|
||||
if (m.parent_menu_id && menuMap.has(m.parent_menu_id)) {
|
||||
menuMap.get(m.parent_menu_id).children.push(menuItem)
|
||||
} else if (!m.parent_menu_id) {
|
||||
rootMenus.push(menuItem)
|
||||
}
|
||||
}
|
||||
|
||||
return { menus: rootMenus }
|
||||
})
|
||||
@@ -1,25 +1,13 @@
|
||||
import { query, execute } from '../../../utils/db'
|
||||
|
||||
const ADMIN_EMAIL = 'coziny@gmail.com'
|
||||
import { requireAdmin } from '../../../utils/session'
|
||||
|
||||
/**
|
||||
* 직원 삭제
|
||||
* DELETE /api/employee/[id]
|
||||
* DELETE /api/employee/[id]/delete
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
const userId = getCookie(event, 'user_id')
|
||||
if (!userId) {
|
||||
throw createError({ statusCode: 401, message: '로그인이 필요합니다.' })
|
||||
}
|
||||
|
||||
// 관리자 권한 체크
|
||||
const currentUser = await query<any>(`
|
||||
SELECT employee_email FROM wr_employee_info WHERE employee_id = $1
|
||||
`, [userId])
|
||||
|
||||
if (!currentUser[0] || currentUser[0].employee_email !== ADMIN_EMAIL) {
|
||||
throw createError({ statusCode: 403, message: '관리자만 삭제할 수 있습니다.' })
|
||||
}
|
||||
// 관리자 권한 체크 (role 기반)
|
||||
const currentUserId = await requireAdmin(event)
|
||||
|
||||
const employeeId = getRouterParam(event, 'id')
|
||||
if (!employeeId) {
|
||||
@@ -27,7 +15,7 @@ export default defineEventHandler(async (event) => {
|
||||
}
|
||||
|
||||
// 본인 삭제 방지
|
||||
if (employeeId === userId) {
|
||||
if (parseInt(employeeId) === currentUserId) {
|
||||
throw createError({ statusCode: 400, message: '본인은 삭제할 수 없습니다.' })
|
||||
}
|
||||
|
||||
@@ -61,7 +49,9 @@ export default defineEventHandler(async (event) => {
|
||||
message: `${employee[0].employee_name}님이 비활성화되었습니다. (주간보고 ${reportCount}건 보존)`
|
||||
}
|
||||
} else {
|
||||
// 주간보고가 없으면 완전 삭제 (로그인 이력 포함)
|
||||
// 주간보고가 없으면 완전 삭제 (관련 데이터 포함)
|
||||
await execute(`DELETE FROM wr_employee_role WHERE employee_id = $1`, [employeeId])
|
||||
await execute(`DELETE FROM wr_session WHERE employee_id = $1`, [employeeId])
|
||||
await execute(`DELETE FROM wr_login_history WHERE employee_id = $1`, [employeeId])
|
||||
await execute(`DELETE FROM wr_employee_info WHERE employee_id = $1`, [employeeId])
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@ export default defineEventHandler(async (event) => {
|
||||
joinDate: employee.join_date,
|
||||
isActive: employee.is_active,
|
||||
createdAt: employee.created_at,
|
||||
updatedAt: employee.updated_at
|
||||
createdIp: employee.created_ip,
|
||||
updatedAt: employee.updated_at,
|
||||
updatedIp: employee.updated_ip
|
||||
},
|
||||
loginHistory: loginHistory.map(h => ({
|
||||
historyId: h.history_id,
|
||||
|
||||
Reference in New Issue
Block a user