From a6724b2a205301549e32cbc6dbe2f225a8f1980d Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Wed, 25 Mar 2026 14:29:28 +0900 Subject: [PATCH] =?UTF-8?q?feat(tkuser):=20requireAdmin=20=E2=86=92=20requ?= =?UTF-8?q?ireAdminOrPermission=20=EC=A0=84=ED=99=98=20=E2=80=94=20?= =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EA=B8=B0=EB=B0=98=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EC=A0=9C=EC=96=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 9개 라우트 파일의 쓰기 작업을 requireAdminOrPermission으로 전환 - 권한 관리에서 tkuser.* 권한 부여 시 일반 사용자도 해당 탭 접근 가능 - GET(참조 데이터)은 requireAuth 유지, permissionRoutes는 admin 전용 유지 - 기존 partnerRoutes.js 패턴과 동일한 방식 적용 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../api/routes/departmentRoutes.js | 14 ++++++----- .../api/routes/notificationRecipientRoutes.js | 4 ++-- user-management/api/routes/projectRoutes.js | 10 ++++---- user-management/api/routes/taskRoutes.js | 16 +++++++------ user-management/api/routes/userRoutes.js | 16 +++++++------ user-management/api/routes/vacationRoutes.js | 24 ++++++++++--------- .../api/routes/vacationSettingsRoutes.js | 4 ++-- user-management/api/routes/workerRoutes.js | 10 ++++---- user-management/api/routes/workplaceRoutes.js | 20 +++++++++------- 9 files changed, 66 insertions(+), 52 deletions(-) diff --git a/user-management/api/routes/departmentRoutes.js b/user-management/api/routes/departmentRoutes.js index 87f87a9..0e9cfe5 100644 --- a/user-management/api/routes/departmentRoutes.js +++ b/user-management/api/routes/departmentRoutes.js @@ -5,17 +5,19 @@ const express = require('express'); const router = express.Router(); const departmentController = require('../controllers/departmentController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); + +const deptPerm = requireAdminOrPermission('tkuser.departments'); router.get('/', requireAuth, departmentController.getAll); router.get('/:id', requireAuth, departmentController.getById); -router.post('/', requireAdmin, departmentController.create); -router.put('/:id', requireAdmin, departmentController.update); -router.delete('/:id', requireAdmin, departmentController.remove); +router.post('/', deptPerm, departmentController.create); +router.put('/:id', deptPerm, departmentController.update); +router.delete('/:id', deptPerm, departmentController.remove); // 승인권한 (Approval Authority) router.get('/:id/approval-authorities', requireAuth, departmentController.getApprovalAuthorities); -router.post('/:id/approval-authorities', requireAdmin, departmentController.createApprovalAuthority); -router.delete('/:id/approval-authorities/:authId', requireAdmin, departmentController.deleteApprovalAuthority); +router.post('/:id/approval-authorities', deptPerm, departmentController.createApprovalAuthority); +router.delete('/:id/approval-authorities/:authId', deptPerm, departmentController.deleteApprovalAuthority); module.exports = router; diff --git a/user-management/api/routes/notificationRecipientRoutes.js b/user-management/api/routes/notificationRecipientRoutes.js index 6cac7c4..12be76d 100644 --- a/user-management/api/routes/notificationRecipientRoutes.js +++ b/user-management/api/routes/notificationRecipientRoutes.js @@ -2,7 +2,7 @@ const express = require('express'); const router = express.Router(); const controller = require('../controllers/notificationRecipientController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); // 모든 라우트에 인증 필요 router.use(requireAuth); @@ -25,7 +25,7 @@ router.get('/:type', controller.getByType); router.post('/', controller.add); // 유형별 수신자 일괄 설정 (관리자만) -router.put('/:type', requireAdmin, controller.setRecipients); +router.put('/:type', requireAdminOrPermission('tkuser.notification_recipients'), controller.setRecipients); // 수신자 제거 (본인: 모든 사용자, 타인: 관리자만 — 컨트롤러에서 검증) router.delete('/:type/:userId', controller.remove); diff --git a/user-management/api/routes/projectRoutes.js b/user-management/api/routes/projectRoutes.js index c55c890..d6380e6 100644 --- a/user-management/api/routes/projectRoutes.js +++ b/user-management/api/routes/projectRoutes.js @@ -5,13 +5,15 @@ const express = require('express'); const router = express.Router(); const projectController = require('../controllers/projectController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); + +const projectPerm = requireAdminOrPermission('tkuser.projects'); router.get('/', requireAuth, projectController.getAll); router.get('/active', requireAuth, projectController.getActive); router.get('/:id', requireAuth, projectController.getById); -router.post('/', requireAdmin, projectController.create); -router.put('/:id', requireAdmin, projectController.update); -router.delete('/:id', requireAdmin, projectController.remove); +router.post('/', projectPerm, projectController.create); +router.put('/:id', projectPerm, projectController.update); +router.delete('/:id', projectPerm, projectController.remove); module.exports = router; diff --git a/user-management/api/routes/taskRoutes.js b/user-management/api/routes/taskRoutes.js index bd0df25..b0302e8 100644 --- a/user-management/api/routes/taskRoutes.js +++ b/user-management/api/routes/taskRoutes.js @@ -7,20 +7,22 @@ const express = require('express'); const router = express.Router(); const taskController = require('../controllers/taskController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); + +const taskPerm = requireAdminOrPermission('tkuser.tasks'); // Work Types (공정) router.get('/work-types', requireAuth, taskController.getWorkTypes); -router.post('/work-types', requireAdmin, taskController.createWorkType); -router.put('/work-types/:id', requireAdmin, taskController.updateWorkType); -router.delete('/work-types/:id', requireAdmin, taskController.deleteWorkType); +router.post('/work-types', taskPerm, taskController.createWorkType); +router.put('/work-types/:id', taskPerm, taskController.updateWorkType); +router.delete('/work-types/:id', taskPerm, taskController.deleteWorkType); // Tasks (작업) router.get('/', requireAuth, taskController.getTasks); router.get('/active', requireAuth, taskController.getActiveTasks); router.get('/:id', requireAuth, taskController.getTaskById); -router.post('/', requireAdmin, taskController.createTask); -router.put('/:id', requireAdmin, taskController.updateTask); -router.delete('/:id', requireAdmin, taskController.deleteTask); +router.post('/', taskPerm, taskController.createTask); +router.put('/:id', taskPerm, taskController.updateTask); +router.delete('/:id', taskPerm, taskController.deleteTask); module.exports = router; diff --git a/user-management/api/routes/userRoutes.js b/user-management/api/routes/userRoutes.js index cb0ee95..c34b49d 100644 --- a/user-management/api/routes/userRoutes.js +++ b/user-management/api/routes/userRoutes.js @@ -6,16 +6,18 @@ const express = require('express'); const router = express.Router(); const userController = require('../controllers/userController'); const permissionController = require('../controllers/permissionController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); -// 사용자 CRUD (admin) -router.get('/', requireAdmin, userController.getUsers); -router.post('/', requireAdmin, userController.createUser); -router.put('/:id', requireAdmin, userController.updateUser); -router.delete('/:id', requireAdmin, userController.deleteUser); +const userPerm = requireAdminOrPermission('tkuser.users'); + +// 사용자 CRUD +router.get('/', userPerm, userController.getUsers); +router.post('/', userPerm, userController.createUser); +router.put('/:id', userPerm, userController.updateUser); +router.delete('/:id', userPerm, userController.deleteUser); // 비밀번호 관리 -router.post('/:id/reset-password', requireAdmin, userController.resetPassword); +router.post('/:id/reset-password', userPerm, userController.resetPassword); router.post('/change-password', requireAuth, userController.changePassword); // 사용자별 페이지 권한 조회 (auth - /api/users/:id/page-permissions) diff --git a/user-management/api/routes/vacationRoutes.js b/user-management/api/routes/vacationRoutes.js index d8c58bc..943fe8c 100644 --- a/user-management/api/routes/vacationRoutes.js +++ b/user-management/api/routes/vacationRoutes.js @@ -8,23 +8,25 @@ const express = require('express'); const router = express.Router(); const vc = require('../controllers/vacationController'); -const { requireAuth, requireAdmin, requireMinLevel } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission, requireMinLevel } = require('../middleware/auth'); + +const vacPerm = requireAdminOrPermission('tkuser.vacations'); // Vacation Types (휴가 유형) router.get('/types', requireAuth, vc.getVacationTypes); -router.post('/types', requireAdmin, vc.createVacationType); -router.put('/types/priorities', requireAdmin, vc.updatePriorities); -router.put('/types/:id', requireAdmin, vc.updateVacationType); -router.delete('/types/:id', requireAdmin, vc.deleteVacationType); +router.post('/types', vacPerm, vc.createVacationType); +router.put('/types/priorities', vacPerm, vc.updatePriorities); +router.put('/types/:id', vacPerm, vc.updateVacationType); +router.delete('/types/:id', vacPerm, vc.deleteVacationType); // Vacation Balances (연차 배정) -router.get('/balances/year/:year', requireAdmin, vc.getBalancesByYear); +router.get('/balances/year/:year', vacPerm, vc.getBalancesByYear); router.get('/balances/user/:userId/year/:year', requireAuth, vc.getBalancesByUserYear); -router.post('/balances', requireAdmin, vc.createBalance); -router.post('/balances/bulk-upsert', requireAdmin, vc.bulkUpsertBalances); -router.post('/balances/auto-calculate', requireAdmin, vc.autoCalculate); -router.put('/balances/:id', requireAdmin, vc.updateBalance); -router.delete('/balances/:id', requireAdmin, vc.deleteBalance); +router.post('/balances', vacPerm, vc.createBalance); +router.post('/balances/bulk-upsert', vacPerm, vc.bulkUpsertBalances); +router.post('/balances/auto-calculate', vacPerm, vc.autoCalculate); +router.put('/balances/:id', vacPerm, vc.updateBalance); +router.delete('/balances/:id', vacPerm, vc.deleteBalance); // 장기근속 제외 설정 router.put('/long-service-exclusion', requireMinLevel('support_team'), vc.setLongServiceExclusion); diff --git a/user-management/api/routes/vacationSettingsRoutes.js b/user-management/api/routes/vacationSettingsRoutes.js index d8fcd6f..6251c12 100644 --- a/user-management/api/routes/vacationSettingsRoutes.js +++ b/user-management/api/routes/vacationSettingsRoutes.js @@ -7,9 +7,9 @@ const express = require('express'); const router = express.Router(); const vsc = require('../controllers/vacationSettingsController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); router.get('/', requireAuth, vsc.getSettings); -router.put('/', requireAdmin, vsc.updateSettings); +router.put('/', requireAdminOrPermission('tkuser.vacation_settings'), vsc.updateSettings); module.exports = router; diff --git a/user-management/api/routes/workerRoutes.js b/user-management/api/routes/workerRoutes.js index aad996e..338f9d0 100644 --- a/user-management/api/routes/workerRoutes.js +++ b/user-management/api/routes/workerRoutes.js @@ -5,12 +5,14 @@ const express = require('express'); const router = express.Router(); const workerController = require('../controllers/workerController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); + +const workerPerm = requireAdminOrPermission('tkuser.workers'); router.get('/', requireAuth, workerController.getAll); router.get('/:id', requireAuth, workerController.getById); -router.post('/', requireAdmin, workerController.create); -router.put('/:id', requireAdmin, workerController.update); -router.delete('/:id', requireAdmin, workerController.remove); +router.post('/', workerPerm, workerController.create); +router.put('/:id', workerPerm, workerController.update); +router.delete('/:id', workerPerm, workerController.remove); module.exports = router; diff --git a/user-management/api/routes/workplaceRoutes.js b/user-management/api/routes/workplaceRoutes.js index 45ffb49..de24fc6 100644 --- a/user-management/api/routes/workplaceRoutes.js +++ b/user-management/api/routes/workplaceRoutes.js @@ -5,24 +5,26 @@ const express = require('express'); const router = express.Router(); const workplaceController = require('../controllers/workplaceController'); -const { requireAuth, requireAdmin } = require('../middleware/auth'); +const { requireAuth, requireAdminOrPermission } = require('../middleware/auth'); const upload = require('../middleware/upload'); +const wpPerm = requireAdminOrPermission('tkuser.workplaces'); + router.get('/categories', requireAuth, workplaceController.getCategories); // 구역지도 (/:id 보다 먼저 등록) -router.post('/categories/:id/layout-image', requireAdmin, upload.single('image'), workplaceController.uploadCategoryLayoutImage); +router.post('/categories/:id/layout-image', wpPerm, upload.single('image'), workplaceController.uploadCategoryLayoutImage); router.get('/categories/:categoryId/map-regions', requireAuth, workplaceController.getMapRegionsByCategory); -router.post('/map-regions', requireAdmin, workplaceController.createMapRegion); -router.put('/map-regions/:id', requireAdmin, workplaceController.updateMapRegion); -router.delete('/map-regions/:id', requireAdmin, workplaceController.deleteMapRegion); +router.post('/map-regions', wpPerm, workplaceController.createMapRegion); +router.put('/map-regions/:id', wpPerm, workplaceController.updateMapRegion); +router.delete('/map-regions/:id', wpPerm, workplaceController.deleteMapRegion); -router.post('/:id/layout-image', requireAdmin, upload.single('image'), workplaceController.uploadWorkplaceLayoutImage); +router.post('/:id/layout-image', wpPerm, upload.single('image'), workplaceController.uploadWorkplaceLayoutImage); router.get('/', requireAuth, workplaceController.getAll); router.get('/:id', requireAuth, workplaceController.getById); -router.post('/', requireAdmin, workplaceController.create); -router.put('/:id', requireAdmin, workplaceController.update); -router.delete('/:id', requireAdmin, workplaceController.remove); +router.post('/', wpPerm, workplaceController.create); +router.put('/:id', wpPerm, workplaceController.update); +router.delete('/:id', wpPerm, workplaceController.remove); module.exports = router;