refactor: TBM/작업보고 코드 통합 및 API 쿼리 버그 수정
- 공통 유틸리티 추출 (common/utils.js, common/base-state.js) - TBM 모바일 인라인 JS/CSS 외부 파일로 분리 (tbm-mobile.js, tbm-mobile.css) - 미사용 코드 삭제 (index.js, work-report-*.js 등 5개 파일) - TBM/작업보고 state.js, utils.js를 공통 모듈 기반으로 전환 - 작업보고서 SSO 인증 호환 수정 (token/user 함수) - tbmModel.js: incomplete-reports 쿼리에서 users→sso_users 조인 수정, leader_name 조인 추가 - docker-compose.yml: system1-web 볼륨 마운트 추가 - 모바일 인계(handover) 기능 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,71 +3,6 @@ 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
|
||||
@@ -94,22 +29,25 @@ router.get('/pages', requireAuth, async (req, res) => {
|
||||
*/
|
||||
router.get('/users/:userId/page-access', requireAuth, async (req, res) => {
|
||||
try {
|
||||
const ssoUserId = req.params.userId;
|
||||
const { userId } = req.params;
|
||||
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) {
|
||||
// 사용자의 역할 확인
|
||||
const [userRows] = await db.query(`
|
||||
SELECT u.user_id, u.username, 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 = ?
|
||||
`, [userId]);
|
||||
|
||||
if (userRows.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 user = userRows[0];
|
||||
|
||||
// Admin/System Admin인 경우 모든 페이지 접근 가능
|
||||
if (user.role_name === 'Admin' || user.role_name === 'System Admin') {
|
||||
const [allPages] = await db.query(`
|
||||
SELECT id, page_key, page_name, page_path, category, is_admin_only
|
||||
FROM pages
|
||||
@@ -124,66 +62,32 @@ router.get('/users/:userId/page-access', requireAuth, async (req, res) => {
|
||||
category: page.category,
|
||||
is_admin_only: page.is_admin_only,
|
||||
can_access: true,
|
||||
is_default: true
|
||||
is_default: true // Admin은 기본적으로 모든 권한 보유
|
||||
}));
|
||||
|
||||
return res.json({ success: true, data: { user: ssoUser, pageAccess } });
|
||||
return res.json({ success: true, data: { user, 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; });
|
||||
// 일반 사용자의 페이지 접근 권한 조회
|
||||
const [pageAccess] = await db.query(`
|
||||
SELECT
|
||||
p.id as page_id,
|
||||
p.page_key,
|
||||
p.page_name,
|
||||
p.page_path,
|
||||
p.category,
|
||||
p.is_admin_only,
|
||||
COALESCE(upa.can_access, p.is_default_accessible, 0) as can_access,
|
||||
upa.granted_at,
|
||||
u2.username as granted_by_username
|
||||
FROM pages p
|
||||
LEFT JOIN user_page_access upa ON p.id = upa.page_id AND upa.user_id = ?
|
||||
LEFT JOIN users u2 ON upa.granted_by = u2.user_id
|
||||
WHERE p.is_admin_only = 0
|
||||
ORDER BY p.display_order, p.page_name
|
||||
`, [userId]);
|
||||
|
||||
// 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 } });
|
||||
res.json({ success: true, data: { user, pageAccess } });
|
||||
} catch (error) {
|
||||
console.error('페이지 접근 권한 조회 오류:', error);
|
||||
res.status(500).json({ success: false, error: '페이지 접근 권한을 불러오는데 실패했습니다.' });
|
||||
|
||||
Reference in New Issue
Block a user