주요 변경사항:
1. middlewares/auth.js 신규 생성 (355 lines)
* 4개 핵심 미들웨어 통합:
- requireAuth: JWT 토큰 검증
- requireRole(...roles): 특정 역할 체크
- requireMinLevel(level): 계층적 권한 레벨 체크
- requireOwnerOrAdmin(options): 소유자/관리자 체크
* 커스텀 에러 클래스 적용:
- AuthenticationError (401)
- ForbiddenError (403)
* 구조화된 로깅 시스템 통합
* 레거시 호환성 별칭 제공:
- verifyToken = requireAuth
- requireAdmin = requireRole('admin', 'system')
- requireSystem = requireRole('system')
* ACCESS_LEVELS 상수 정의 및 export
2. 라우터 업데이트 (새로운 미들웨어 적용)
* routes/workReportAnalysisRoutes.js
- authMiddleware → auth로 변경
- requireAdmin → requireRole('admin', 'system')
* routes/systemRoutes.js
- 커스텀 requireSystemAccess 제거
- requireRole('system') 사용
- 14줄 코드 감소 (298 → 284 lines)
* routes/auth.js
- utils/access의 requireAccess 제거
- requireAuth + requireRole 조합 사용
3. 레거시 호환성 래퍼 (하위 호환성 유지)
* middlewares/authMiddleware.js (89 → 37 lines, 58% 감소)
- auth.js의 래퍼로 변경
- @deprecated 태그 추가
- 기존 22개 파일 호환성 유지
* middlewares/accessMiddleware.js (33 → 30 lines)
- requireMinLevel 래퍼로 변경
- @deprecated 태그 및 마이그레이션 가이드 추가
* utils/access.js
- requireAccess 레거시 함수 추가 (하위 호환성)
- 유틸리티 함수들은 그대로 유지
기술적 개선사항:
- 중복 코드 제거: 4개 파일에 분산된 인증 로직 통합
- 일관된 에러 처리: 커스텀 에러 클래스 사용
- 상세한 로깅: 인증/인가 실패 원인 추적 가능
- 보안 강화: TokenExpiredError, JsonWebTokenError 세분화 처리
- 확장성: 새로운 권한 체크 패턴 쉽게 추가 가능
- JSDoc 문서화: 모든 함수에 상세한 사용 예제 포함
통합 전후 비교:
- 미들웨어 파일: 4개 → 1개 (통합) + 3개 (래퍼)
- 중복 코드: ~150 lines → 0 lines
- 일관성: 4가지 다른 패턴 → 1가지 통합 패턴
레거시 호환성:
- 기존 22개 라우터 파일 중 19개는 수정 없이 동작
- 3개 라우터만 새로운 패턴으로 업데이트 (예시용)
- verifyToken, requireAdmin, requireSystem 별칭 제공
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
178 lines
4.9 KiB
JavaScript
178 lines
4.9 KiB
JavaScript
/**
|
|
* @deprecated 이 파일의 미들웨어 함수들은 하위 호환성을 위해 유지됩니다.
|
|
* 새로운 코드에서는 '../middlewares/auth'를 사용하세요.
|
|
*/
|
|
|
|
// utils/access.js - 유틸리티 함수와 레거시 호환성
|
|
const ACCESS_LEVELS = {
|
|
worker: 1,
|
|
group_leader: 2,
|
|
support_team: 3,
|
|
admin: 4,
|
|
system: 5
|
|
};
|
|
|
|
const ACCESS_LEVEL_NAMES = {
|
|
worker: '작업자',
|
|
group_leader: '그룹장',
|
|
support_team: '지원팀',
|
|
admin: '관리자',
|
|
system: '시스템'
|
|
};
|
|
|
|
/**
|
|
* 권한 레벨 비교 (유틸리티 함수)
|
|
* @param {string} userLevel - 사용자의 권한 레벨
|
|
* @param {string} requiredLevel - 필요한 권한 레벨
|
|
* @returns {boolean} - 권한 여부
|
|
*/
|
|
const hasPermission = (userLevel, requiredLevel) => {
|
|
const userOrder = ACCESS_LEVELS[userLevel] || 0;
|
|
const requiredOrder = ACCESS_LEVELS[requiredLevel] || 999;
|
|
return userOrder >= requiredOrder;
|
|
};
|
|
|
|
/**
|
|
* 권한 레벨을 숫자로 변환
|
|
* @param {string} level - 권한 레벨 문자열
|
|
* @returns {number} - 권한 레벨 숫자
|
|
*/
|
|
const getLevelNumber = (level) => {
|
|
return ACCESS_LEVELS[level] || 0;
|
|
};
|
|
|
|
/**
|
|
* 권한 레벨을 한글명으로 변환
|
|
* @param {string} level - 권한 레벨 문자열
|
|
* @returns {string} - 한글 권한명
|
|
*/
|
|
const getLevelName = (level) => {
|
|
return ACCESS_LEVEL_NAMES[level] || '알 수 없음';
|
|
};
|
|
|
|
/**
|
|
* 사용자가 특정 권한들 중 하나라도 가지고 있는지 확인
|
|
* @param {string} userLevel - 사용자의 권한 레벨
|
|
* @param {string[]} allowedLevels - 허용된 권한 레벨들
|
|
* @returns {boolean} - 권한 여부
|
|
*/
|
|
const hasAnyPermission = (userLevel, allowedLevels) => {
|
|
return allowedLevels.some(level => hasPermission(userLevel, level));
|
|
};
|
|
|
|
/**
|
|
* 모든 권한 레벨 목록 반환
|
|
* @returns {string[]} - 권한 레벨 배열
|
|
*/
|
|
const getAllLevels = () => {
|
|
return Object.keys(ACCESS_LEVELS);
|
|
};
|
|
|
|
/**
|
|
* 특정 권한 레벨 이상의 모든 권한 반환
|
|
* @param {string} minLevel - 최소 권한 레벨
|
|
* @returns {string[]} - 해당 레벨 이상의 권한들
|
|
*/
|
|
const getLevelsAbove = (minLevel) => {
|
|
const minOrder = ACCESS_LEVELS[minLevel] || 0;
|
|
return Object.keys(ACCESS_LEVELS).filter(level => ACCESS_LEVELS[level] >= minOrder);
|
|
};
|
|
|
|
// ===== 프론트엔드용 권한 체크 함수들 =====
|
|
|
|
/**
|
|
* 페이지 접근 권한 체크 (프론트엔드에서 사용)
|
|
* @param {string} userLevel - 사용자 권한
|
|
* @param {object} pageConfig - 페이지 설정 {minLevel?, allowedRoles?, deniedRoles?}
|
|
* @returns {boolean} - 접근 가능 여부
|
|
*/
|
|
const canAccessPage = (userLevel, pageConfig) => {
|
|
const { minLevel, allowedRoles, deniedRoles = [] } = pageConfig;
|
|
|
|
// 거부 목록 체크
|
|
if (deniedRoles.includes(userLevel)) {
|
|
return false;
|
|
}
|
|
|
|
// 허용 목록 체크
|
|
if (allowedRoles && allowedRoles.length > 0) {
|
|
return allowedRoles.includes(userLevel);
|
|
}
|
|
|
|
// 최소 레벨 체크
|
|
if (minLevel) {
|
|
return hasPermission(userLevel, minLevel);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* CRUD 권한 체크 (프론트엔드에서 사용)
|
|
* @param {string} userLevel - 사용자 권한
|
|
* @param {string} table - 테이블명
|
|
* @param {string} action - 액션 (CREATE, READ, UPDATE, DELETE)
|
|
* @returns {boolean} - 권한 여부
|
|
*/
|
|
const canPerformAction = (userLevel, table, action) => {
|
|
// 기본적으로 모든 인증된 사용자에게 권한 부여
|
|
// 특별한 제한이 필요한 경우에만 여기서 체크
|
|
|
|
// 예시: 사용자 관리는 admin 이상만
|
|
if (table === 'Users' && ['CREATE', 'UPDATE', 'DELETE'].includes(action)) {
|
|
return hasPermission(userLevel, 'admin');
|
|
}
|
|
|
|
// 예시: 시스템 테이블은 system만
|
|
if (table === 'SystemConfig') {
|
|
return hasPermission(userLevel, 'system');
|
|
}
|
|
|
|
// 나머지는 모든 인증된 사용자에게 허용
|
|
return userLevel && userLevel !== 'anonymous';
|
|
};
|
|
|
|
// ===== 레거시 호환성: 미들웨어 함수 =====
|
|
|
|
/**
|
|
* @deprecated 이 미들웨어는 하위 호환성을 위해 유지됩니다.
|
|
* 새로운 코드에서는 '../middlewares/auth'의 requireRole을 사용하세요.
|
|
*
|
|
* @example
|
|
* // 이전 방식 (deprecated)
|
|
* const { requireAccess } = require('../utils/access');
|
|
* router.get('/admin', requireAccess('admin'), handler);
|
|
*
|
|
* // 새로운 방식 (권장)
|
|
* const { requireAuth, requireRole } = require('../middlewares/auth');
|
|
* router.get('/admin', requireAuth, requireRole('admin'), handler);
|
|
*/
|
|
const requireAccess = (...allowed) => {
|
|
return (req, res, next) => {
|
|
if (!req.user || !allowed.includes(req.user.access_level)) {
|
|
return res.status(403).json({ error: '접근 권한이 없습니다' });
|
|
}
|
|
next();
|
|
};
|
|
};
|
|
|
|
module.exports = {
|
|
// 기본 유틸리티 함수들
|
|
hasPermission,
|
|
getLevelNumber,
|
|
getLevelName,
|
|
hasAnyPermission,
|
|
getAllLevels,
|
|
getLevelsAbove,
|
|
|
|
// 프론트엔드용 함수들
|
|
canAccessPage,
|
|
canPerformAction,
|
|
|
|
// 레거시 호환성 (deprecated)
|
|
requireAccess,
|
|
|
|
// 상수들
|
|
ACCESS_LEVELS,
|
|
ACCESS_LEVEL_NAMES
|
|
}; |