## 핵심 변경
- auth_perm_tree를 메뉴 SSOT로 확장 (V020~V024)
- url_path, label_key, component_key, nav_group, nav_sub_group, nav_sort 컬럼
- labels JSONB (다국어: {"ko":"...", "en":"..."})
- 보이지 않는 도메인 그룹 8개 삭제 (surveillance, detection, risk-assessment 등)
- 권한 트리 = 메뉴 트리 완전 동기화
- 그룹 레벨 권한 → 개별 자식 권한으로 확장 후 그룹 삭제
- 패널 노드 parent_cd를 실제 소속 페이지로 수정
(어구식별→어구탐지, 전역제외→후보제외, 역할관리→권한관리)
- vessel:vessel-detail 권한 노드 제거 (드릴다운 전용, 인증만 체크)
## 백엔드
- MenuConfigService: auth_perm_tree에서 menuConfig DTO 생성
- /api/auth/me 응답에 menuConfig 포함 (로그인 시 프리로드)
- @RequirePermission 12곳 수정 (삭제된 그룹명 → 구체적 자식 리소스)
- Caffeine 캐시 menuConfig 추가
## 프론트엔드
- NAV_ENTRIES 하드코딩 제거 → menuStore(Zustand) 동적 렌더링
- PATH_TO_RESOURCE 하드코딩 제거 → DB 기반 longest-match
- App.tsx 36개 정적 import/33개 Route → DynamicRoutes + componentRegistry
- PermissionsPanel: DB labels JSONB 기반 표시명 + 페이지/패널 아이콘 구분
- DB migration README.md 전면 재작성 (V001~V024, 49테이블, 149인덱스)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
55 lines
1.0 KiB
TypeScript
55 lines
1.0 KiB
TypeScript
import {
|
|
LayoutDashboard, Activity, Radar, Map, Layers, Shield,
|
|
EyeOff, Anchor, Ship, FileText, List, BarChart3,
|
|
Navigation, Users, Send, Smartphone, Monitor,
|
|
GitBranch, CheckSquare, Ban, Tag, Settings,
|
|
Brain, Cpu, MessageSquare, Database, Wifi, Globe,
|
|
Fingerprint, Megaphone, ScrollText, History, KeyRound,
|
|
type LucideIcon,
|
|
} from 'lucide-react';
|
|
|
|
/**
|
|
* DB icon 문자열 → Lucide React 컴포넌트 매핑.
|
|
* 사이드바에서 사용하는 아이콘만 포함.
|
|
*/
|
|
const ICON_MAP: Record<string, LucideIcon> = {
|
|
LayoutDashboard,
|
|
Activity,
|
|
Radar,
|
|
Map,
|
|
Layers,
|
|
Shield,
|
|
EyeOff,
|
|
Anchor,
|
|
Ship,
|
|
FileText,
|
|
List,
|
|
BarChart3,
|
|
Navigation,
|
|
Users,
|
|
Send,
|
|
Smartphone,
|
|
Monitor,
|
|
GitBranch,
|
|
CheckSquare,
|
|
Ban,
|
|
Tag,
|
|
Settings,
|
|
Brain,
|
|
Cpu,
|
|
MessageSquare,
|
|
Database,
|
|
Wifi,
|
|
Globe,
|
|
Fingerprint,
|
|
Megaphone,
|
|
ScrollText,
|
|
History,
|
|
KeyRound,
|
|
};
|
|
|
|
export function resolveIcon(name: string | null): LucideIcon | null {
|
|
if (!name) return null;
|
|
return ICON_MAP[name] ?? null;
|
|
}
|