feat(tkuser): 알림 시스템 이관 system1-factory → tkuser

- Phase 1: tkuser에 알림 CRUD, Push/ntfy 발송, 내부 알림 API 추가
- Phase 2: notifyHelper URL을 tkuser-api:3000으로 전환 (system2, tkpurchase, tksafety, system1)
- Phase 3: notification-bell.js API 도메인 tkuser로 변경 + 캐시 버스팅 v=4
- Phase 4: system1에서 알림 코드 제거 (routes, controllers, models, utils)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-17 15:56:41 +09:00
parent afa10c044f
commit 84cf222b81
30 changed files with 244 additions and 172 deletions

View File

@@ -76,4 +76,31 @@ function requireAdminOrPermission(pageName) {
};
}
module.exports = { extractToken, requireAuth, requireAdmin, requireAdminOrPermission };
/**
* 최소 권한 레벨 체크 미들웨어
* worker(1) < group_leader(2) < support_team(3) < admin(4) < system(5)
*/
const ACCESS_LEVELS = { worker: 1, group_leader: 2, support_team: 3, admin: 4, system: 5 };
function requireMinLevel(minLevel) {
return (req, res, next) => {
const token = extractToken(req);
if (!token) {
return res.status(401).json({ success: false, error: '인증이 필요합니다' });
}
try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded;
const userLevel = ACCESS_LEVELS[decoded.access_level] || ACCESS_LEVELS[decoded.role] || 0;
const requiredLevel = ACCESS_LEVELS[minLevel] || 999;
if (userLevel < requiredLevel) {
return res.status(403).json({ success: false, error: `${minLevel} 이상의 권한이 필요합니다` });
}
next();
} catch {
return res.status(401).json({ success: false, error: '유효하지 않은 토큰입니다' });
}
};
}
module.exports = { extractToken, requireAuth, requireAdmin, requireAdminOrPermission, requireMinLevel };