const express = require('express'); const router = express.Router(); const { getDb } = require('../dbPool'); const { requireAuth, requireAdmin } = require('../middlewares/auth'); // tkuser page_name → default_access 매핑 (permissionModel.js의 DEFAULT_PAGES와 동기화) const TKUSER_DEFAULT_ACCESS = { 's1.dashboard': true, 's1.work.tbm': true, 's1.work.report_create': true, 's1.work.analysis': false, 's1.work.nonconformity': true, 's1.factory.repair_management': false, 's1.inspection.daily_patrol': false, 's1.inspection.checkin': true, 's1.inspection.work_status': false, 's1.safety.visit_request': true, 's1.safety.management': false, 's1.safety.checklist_manage': false, 's1.attendance.my_vacation_info': true, 's1.attendance.monthly': true, 's1.attendance.vacation_request': true, 's1.attendance.vacation_management': false, 's1.attendance.vacation_allocation': false, 's1.attendance.annual_overview': false, 's1.admin.workers': false, 's1.admin.projects': false, 's1.admin.tasks': false, 's1.admin.workplaces': false, 's1.admin.equipments': false, 's1.admin.issue_categories': false, 's1.admin.attendance_report': false, }; // system1 page_key → tkuser page_name 매핑 const PAGEKEY_TO_TKUSER = { 'dashboard': 's1.dashboard', 'work.tbm': 's1.work.tbm', 'work.report-create': 's1.work.report_create', 'work.report-view': 's1.work.report_create', 'work.analysis': 's1.work.analysis', 'work.visit-request': 's1.safety.visit_request', 'work.issue-report': 's1.work.nonconformity', 'work.issue-list': 's1.work.nonconformity', 'work.issue-detail': 's1.work.nonconformity', 'safety.issue_report': 's1.work.nonconformity', 'safety.issue_list': 's1.work.nonconformity', 'safety.issue_detail': 's1.work.nonconformity', 'safety.checklist_manage': 's1.safety.checklist_manage', 'admin.workers': 's1.admin.workers', 'admin.projects': 's1.admin.projects', 'admin.tasks': 's1.admin.tasks', 'admin.workplaces': 's1.admin.workplaces', 'admin.equipments': 's1.admin.equipments', 'admin.codes': 's1.admin.tasks', 'admin.safety-management': 's1.safety.management', 'admin.safety-training-conduct': 's1.safety.management', 'admin.attendance-report-comparison': 's1.admin.attendance_report', 'admin.departments': 's1.admin.workers', 'common.daily-attendance': 's1.inspection.checkin', 'common.monthly-attendance': 's1.attendance.monthly', 'common.vacation-request': 's1.attendance.vacation_request', 'common.vacation-management': 's1.attendance.vacation_management', 'common.annual-vacation-overview': 's1.attendance.annual_overview', 'common.vacation-allocation': 's1.attendance.vacation_allocation', 'inspection.daily_patrol': 's1.inspection.daily_patrol', 'attendance.vacation_approval': 's1.attendance.vacation_management', 'attendance.vacation_input': 's1.attendance.vacation_allocation', }; /** * 모든 페이지 목록 조회 * GET /api/pages */ router.get('/pages', requireAuth, async (req, res) => { try { const db = await getDb(); const [pages] = await db.query(` SELECT id, page_key, page_name, page_path, category, description, is_admin_only, display_order FROM pages ORDER BY display_order, page_name `); res.json({ success: true, data: pages }); } catch (error) { console.error('페이지 목록 조회 오류:', error); res.status(500).json({ success: false, error: '페이지 목록을 불러오는데 실패했습니다.' }); } }); /** * 특정 사용자의 페이지 접근 권한 조회 * GET /api/users/:userId/page-access */ router.get('/users/:userId/page-access', requireAuth, async (req, res) => { try { const ssoUserId = req.params.userId; const db = await getDb(); // SSO 사용자 조회 (department_id 포함) const [ssoRows] = await db.query( 'SELECT user_id, username, name, role, department_id FROM sso_users WHERE user_id = ?', [ssoUserId] ); if (ssoRows.length === 0) { return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다.' }); } const ssoUser = ssoRows[0]; // SSO role로 Admin 체크 const ssoRole = (ssoUser.role || '').toLowerCase(); if (ssoRole === 'admin' || ssoRole === 'system') { const [allPages] = await db.query(` SELECT id, page_key, page_name, page_path, category, is_admin_only FROM pages ORDER BY display_order, page_name `); const pageAccess = allPages.map(page => ({ page_id: page.id, page_key: page.page_key, page_name: page.page_name, page_path: page.page_path, category: page.category, is_admin_only: page.is_admin_only, can_access: true, is_default: true })); return res.json({ success: true, data: { user: ssoUser, pageAccess } }); } // 일반 사용자: tkuser 권한 테이블에서 조회 // 1) 개인 권한 (user_page_permissions) const [userPerms] = await db.query( 'SELECT page_name, can_access FROM user_page_permissions WHERE user_id = ?', [ssoUserId] ); const userPermMap = {}; userPerms.forEach(p => { userPermMap[p.page_name] = !!p.can_access; }); // 2) 부서 권한 (department_page_permissions) const deptPermMap = {}; if (ssoUser.department_id) { const [deptPerms] = await db.query( 'SELECT page_name, can_access FROM department_page_permissions WHERE department_id = ?', [ssoUser.department_id] ); deptPerms.forEach(p => { deptPermMap[p.page_name] = !!p.can_access; }); } // 3) 페이지 목록 조회 + 권한 매핑 const [pages] = await db.query(` SELECT id, page_key, page_name, page_path, category, is_admin_only FROM pages WHERE is_admin_only = 0 ORDER BY display_order, page_name `); const pageAccess = pages.map(page => { const tkuserKey = PAGEKEY_TO_TKUSER[page.page_key]; let canAccess = false; if (tkuserKey) { // 우선순위: 개인 권한 > 부서 권한 > default_access if (tkuserKey in userPermMap) { canAccess = userPermMap[tkuserKey]; } else if (tkuserKey in deptPermMap) { canAccess = deptPermMap[tkuserKey]; } else if (tkuserKey in TKUSER_DEFAULT_ACCESS) { canAccess = TKUSER_DEFAULT_ACCESS[tkuserKey]; } } return { page_id: page.id, page_key: page.page_key, page_name: page.page_name, page_path: page.page_path, category: page.category, is_admin_only: page.is_admin_only, can_access: canAccess ? 1 : 0 }; }); res.json({ success: true, data: { user: ssoUser, pageAccess } }); } catch (error) { console.error('페이지 접근 권한 조회 오류:', error); res.status(500).json({ success: false, error: '페이지 접근 권한을 불러오는데 실패했습니다.' }); } }); /** * 사용자에게 페이지 접근 권한 부여/회수 * POST /api/users/:userId/page-access * Body: { pageIds: [1, 2, 3], canAccess: true } */ router.post('/users/:userId/page-access', requireAuth, async (req, res) => { try { const { userId } = req.params; const { pageIds, canAccess } = req.body; const adminUserId = req.user.user_id; // 권한을 부여하는 Admin의 user_id // Admin 권한 확인 const db = await getDb(); const [adminRows] = await db.query(` SELECT u.role_id, r.name as role_name FROM users u LEFT JOIN roles r ON u.role_id = r.id WHERE u.user_id = ? `, [adminUserId]); if (adminRows.length === 0 || (adminRows[0].role_name !== 'Admin' && adminRows[0].role_name !== 'System Admin')) { return res.status(403).json({ success: false, error: '권한이 없습니다. Admin 계정만 사용자 권한을 관리할 수 있습니다.' }); } // 사용자 존재 확인 const [userRows] = await db.query('SELECT user_id FROM users WHERE user_id = ?', [userId]); if (userRows.length === 0) { return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다.' }); } // 페이지 접근 권한 업데이트 for (const pageId of pageIds) { // 기존 권한 확인 const [existing] = await db.query( 'SELECT * FROM user_page_access WHERE user_id = ? AND page_id = ?', [userId, pageId] ); if (existing.length > 0) { // 업데이트 await db.query( 'UPDATE user_page_access SET can_access = ?, granted_at = NOW(), granted_by = ? WHERE user_id = ? AND page_id = ?', [canAccess ? 1 : 0, adminUserId, userId, pageId] ); } else { // 삽입 await db.query( 'INSERT INTO user_page_access (user_id, page_id, can_access, granted_by) VALUES (?, ?, ?, ?)', [userId, pageId, canAccess ? 1 : 0, adminUserId] ); } } res.json({ success: true, message: '페이지 접근 권한이 업데이트되었습니다.' }); } catch (error) { console.error('페이지 접근 권한 부여 오류:', error); res.status(500).json({ success: false, error: '페이지 접근 권한을 업데이트하는데 실패했습니다.' }); } }); /** * 특정 페이지의 접근 권한 회수 * DELETE /api/users/:userId/page-access/:pageId */ router.delete('/users/:userId/page-access/:pageId', requireAuth, async (req, res) => { try { const { userId, pageId } = req.params; const adminUserId = req.user.user_id; // Admin 권한 확인 const db = await getDb(); const [adminRows] = await db.query(` SELECT u.role_id, r.name as role_name FROM users u LEFT JOIN roles r ON u.role_id = r.id WHERE u.user_id = ? `, [adminUserId]); if (adminRows.length === 0 || (adminRows[0].role_name !== 'Admin' && adminRows[0].role_name !== 'System Admin')) { return res.status(403).json({ success: false, error: '권한이 없습니다.' }); } // 접근 권한 삭제 await db.query( 'DELETE FROM user_page_access WHERE user_id = ? AND page_id = ?', [userId, pageId] ); res.json({ success: true, message: '페이지 접근 권한이 회수되었습니다.' }); } catch (error) { console.error('페이지 접근 권한 회수 오류:', error); res.status(500).json({ success: false, error: '페이지 접근 권한을 회수하는데 실패했습니다.' }); } }); /** * 모든 사용자의 페이지 접근 권한 요약 조회 (Admin용) * GET /api/page-access/summary */ router.get('/page-access/summary', requireAuth, async (req, res) => { try { const adminUserId = req.user.user_id; // Admin 권한 확인 const db = await getDb(); const [adminRows] = await db.query(` SELECT u.role_id, r.name as role_name FROM users u LEFT JOIN roles r ON u.role_id = r.id WHERE u.user_id = ? `, [adminUserId]); if (adminRows.length === 0 || (adminRows[0].role_name !== 'Admin' && adminRows[0].role_name !== 'System Admin')) { return res.status(403).json({ success: false, error: '권한이 없습니다.' }); } // 모든 사용자와 페이지 권한 조회 const [summary] = await db.query(` SELECT u.user_id, u.username, u.name, r.name as role_name, COUNT(DISTINCT upa.page_id) as accessible_pages_count, (SELECT COUNT(*) FROM pages WHERE is_admin_only = 0) as total_pages_count FROM users u LEFT JOIN roles r ON u.role_id = r.id LEFT JOIN user_page_access upa ON u.user_id = upa.user_id AND upa.can_access = 1 WHERE r.name NOT IN ('Admin', 'System Admin') GROUP BY u.user_id, u.username, u.name, r.name ORDER BY u.username `); res.json({ success: true, data: summary }); } catch (error) { console.error('페이지 접근 권한 요약 조회 오류:', error); res.status(500).json({ success: false, error: '페이지 접근 권한 요약을 불러오는데 실패했습니다.' }); } }); module.exports = router;