From 66676ac9235b34e54aa58c7cb6c9497ba4ff45d2 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Mon, 30 Mar 2026 07:25:23 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20shared=20requirePage=20=EB=AF=B8?= =?UTF-8?q?=EB=93=A4=EC=9B=A8=EC=96=B4=20=EC=B6=94=EA=B0=80=20+=20tksuppor?= =?UTF-8?q?t=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- shared/middleware/pagePermission.js | 61 +++++++++++++++++++++++++++++ tksupport/api/middleware/auth.js | 35 ++--------------- 2 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 shared/middleware/pagePermission.js diff --git a/shared/middleware/pagePermission.js b/shared/middleware/pagePermission.js new file mode 100644 index 0000000..03a9232 --- /dev/null +++ b/shared/middleware/pagePermission.js @@ -0,0 +1,61 @@ +/** + * 페이지 권한 미들웨어 (shared) + * admin/system 역할은 자동 통과, 일반 사용자는 개인/부서 권한 체크 + * + * 사용법: + * const { createRequirePage } = require('../../shared/middleware/pagePermission'); + * const requirePage = createRequirePage(() => getPool()); + * router.get('/some', requirePage('page_name'), controller.handler); + */ + +function createRequirePage(getPool) { + return function requirePage(pageName) { + return async (req, res, next) => { + const userId = req.user.user_id || req.user.id; + const role = (req.user.role || '').toLowerCase(); + + // admin/system 자동 통과 + if (role === 'admin' || role === 'system') return next(); + + try { + const db = typeof getPool === 'function' ? getPool() : getPool; + + // 1. 개인 권한 체크 + const [rows] = await db.query( + 'SELECT can_access FROM user_page_permissions WHERE user_id = ? AND page_name = ?', + [userId, pageName] + ); + if (rows.length > 0) { + return rows[0].can_access + ? next() + : res.status(403).json({ success: false, error: '접근 권한이 없습니다' }); + } + + // 2. 부서 권한 체크 + const [userRows] = await db.query( + 'SELECT department_id FROM sso_users WHERE user_id = ?', + [userId] + ); + if (userRows.length > 0 && userRows[0].department_id) { + const [deptRows] = await db.query( + 'SELECT can_access FROM department_page_permissions WHERE department_id = ? AND page_name = ?', + [userRows[0].department_id, pageName] + ); + if (deptRows.length > 0) { + return deptRows[0].can_access + ? next() + : res.status(403).json({ success: false, error: '접근 권한이 없습니다' }); + } + } + + // 3. 권한 레코드 없음 → 거부 + return res.status(403).json({ success: false, error: '접근 권한이 없습니다' }); + } catch (err) { + console.error('Permission check error:', err); + return res.status(500).json({ success: false, error: '권한 확인 실패' }); + } + }; + }; +} + +module.exports = { createRequirePage }; diff --git a/tksupport/api/middleware/auth.js b/tksupport/api/middleware/auth.js index 0cf54fc..f86011e 100644 --- a/tksupport/api/middleware/auth.js +++ b/tksupport/api/middleware/auth.js @@ -42,38 +42,9 @@ function requireAdmin(req, res, next) { } } -function requirePage(pageName) { - return async (req, res, next) => { - const userId = req.user.user_id || req.user.id; - const role = (req.user.role || '').toLowerCase(); - if (role === 'admin' || role === 'system') return next(); - - try { - const db = getPool(); - const [rows] = await db.query( - 'SELECT can_access FROM user_page_permissions WHERE user_id = ? AND page_name = ?', - [userId, pageName] - ); - if (rows.length > 0) { - return rows[0].can_access ? next() : res.status(403).json({ success: false, error: '접근 권한이 없습니다' }); - } - const [userRows] = await db.query('SELECT department_id FROM sso_users WHERE user_id = ?', [userId]); - if (userRows.length > 0 && userRows[0].department_id) { - const [deptRows] = await db.query( - 'SELECT can_access FROM department_page_permissions WHERE department_id = ? AND page_name = ?', - [userRows[0].department_id, pageName] - ); - if (deptRows.length > 0) { - return deptRows[0].can_access ? next() : res.status(403).json({ success: false, error: '접근 권한이 없습니다' }); - } - } - return res.status(403).json({ success: false, error: '접근 권한이 없습니다' }); - } catch (err) { - console.error('Permission check error:', err); - return res.status(500).json({ success: false, error: '권한 확인 실패' }); - } - }; -} +// requirePage: shared 미들웨어 사용 +const { createRequirePage } = require('../../../shared/middleware/pagePermission'); +const requirePage = createRequirePage(() => getPool()); function requireSupportTeam(req, res, next) { const token = extractToken(req);