- PermissionManagement externalSelection 콜백 함수 오류 수정 - setSelectedItems → onToggleSelection, onToggleSelectAll, getItemId 변경 - claudedocs 문서 폴더별 정리 (26개 파일) - dashboard/, guides/, settings/, construction/, sales/ 등 Co-Authored-By: Claude <noreply@anthropic.com>
8.5 KiB
8.5 KiB
권한 관리 시스템 현황 분석
작성일: 2026-01-07 최종 수정일: 2026-01-12 목적: SAM 프로젝트 권한 시스템 현황 파악 및 향후 구현 계획 정리
1. 현재 상태 요약
| 구분 | 상태 | 설명 |
|---|---|---|
| 권한 설정 UI | ✅ 완성 | /settings/permissions/[id]에서 역할별 권한 설정 가능 |
| 백엔드 권한 API | ✅ 완성 | 권한 매트릭스 조회/설정 API 구현됨 |
| 백엔드 API 권한 체크 | ⚠️ 구조만 있음 | 미들웨어 존재하나 라우트에 미적용 |
| 프론트 권한 체크 | ❌ 미구현 | 권한 매트릭스 조회 및 UI 제어 로직 없음 |
2. 권한 타입 (5가지)
| 권한 | 영문 | 적용 대상 |
|---|---|---|
| 조회 | view |
페이지 접근 |
| 생성 | create |
등록/추가 버튼 |
| 수정 | update |
수정 버튼 |
| 삭제 | delete |
삭제 버튼 |
| 승인 | approve |
승인/반려 버튼 |
⚠️ 참고:
export,manage권한은 백엔드에 미구현 상태
3. 백엔드 API 구조
3.1 로그인 API
엔드포인트: POST /api/v1/login
응답 구조:
{
"access_token": "...",
"refresh_token": "...",
"user": { "id": 1, "name": "..." },
"menus": [...],
"roles": [...]
}
⚠️ 주의: 로그인 응답에 권한 매트릭스(permissions)는 포함되지 않음
3.2 권한 매트릭스 조회 API
사용자별 권한 조회 (프론트엔드에서 사용):
GET /api/v1/permissions/users/{userId}/menu-matrix
실제 응답 구조:
{
"success": true,
"message": "유저 메뉴 권한 매트릭스 조회 성공",
"data": {
"actions": ["view", "create", "update", "delete", "approve"],
"tree": [
{
"menu_id": 1,
"parent_id": null,
"name": "대시보드",
"url": "/dashboard",
"type": "system",
"children": [
{
"menu_id": 2,
"parent_id": 1,
"name": "CEO 대시보드",
"url": "/dashboard/ceo",
"children": [],
"actions": { ... }
}
],
"actions": {
"view": {
"permission_id": 123,
"permission_code": "menu:1.view",
"guard_name": "api",
"state": "allow",
"is_allowed": 1
},
"create": {
"permission_id": 124,
"permission_code": "menu:1.create",
"guard_name": "api",
"state": "deny",
"is_allowed": 0
},
"update": null,
"delete": null,
"approve": null
}
}
]
}
}
권한 상태 값:
| state | is_allowed | 의미 |
|---|---|---|
allow |
1 | 권한 허용됨 |
deny |
0 | 권한 명시적 거부 |
none |
0 | 권한 미설정 (기본 거부) |
actions가 null인 경우: 해당 메뉴에 해당 권한이 정의되지 않음
3.3 권한 매트릭스 API 목록
| 엔드포인트 | 메서드 | 설명 |
|---|---|---|
/api/v1/permissions/users/{user_id}/menu-matrix |
GET | 사용자별 권한 매트릭스 |
/api/v1/permissions/roles/{role_id}/menu-matrix |
GET | 역할별 권한 매트릭스 |
/api/v1/permissions/departments/{dept_id}/menu-matrix |
GET | 부서별 권한 매트릭스 |
3.4 역할 권한 관리 API
| 엔드포인트 | 메서드 | 설명 |
|---|---|---|
/api/v1/role-permissions/menus |
GET | 권한 설정용 메뉴 트리 |
/api/v1/roles/{id}/permissions |
GET | 역할 권한 목록 |
/api/v1/roles/{id}/permissions |
POST | 역할 권한 부여 |
/api/v1/roles/{id}/permissions |
DELETE | 역할 권한 회수 |
/api/v1/roles/{id}/permissions/sync |
PUT | 역할 권한 동기화 |
/api/v1/roles/{id}/permissions/matrix |
GET | 역할 권한 매트릭스 (설정 UI용) |
/api/v1/roles/{id}/permissions/toggle |
POST | 개별 권한 토글 |
/api/v1/roles/{id}/permissions/allow-all |
POST | 전체 허용 |
/api/v1/roles/{id}/permissions/deny-all |
POST | 전체 거부 |
/api/v1/roles/{id}/permissions/reset |
POST | 기본값 초기화 (view만 허용) |
4. 백엔드 권한 체크 미들웨어
4.1 CheckPermission.php
// 권한 체크 로직
if (! AccessService::allows($user, $perm, $tenantId, 'api')) {
return response()->json(['message' => '권한이 없습니다.'], 403);
}
// 단, perm 미지정 라우트는 통과 (현재 정책)
if (! $perm && ! $permsAny) {
return $next($request); // ← 현재 모든 API가 여기로 통과
}
4.2 PermMapper.php
HTTP 메서드에 따라 액션 자동 매핑:
| HTTP 메서드 | 권한 액션 |
|---|---|
| GET, HEAD | view |
| POST | create |
| PUT, PATCH | update |
| DELETE | delete |
권한 형식: menu:{menuId}.{action} (예: menu:1.view)
4.3 현재 상태
- 미들웨어 구조는 갖춰져 있음
- 라우트에
menu_id설정이 안 되어 있어 실제 권한 체크 미동작 - 모든 API가 권한 체크 없이 통과
5. 프론트엔드 현재 상태
5.1 구현된 것
- 로그인 시
menus,roles데이터 저장 (localStorage) - 사이드바 메뉴 표시 (백엔드에서 필터링된 메뉴)
- 메뉴 폴링 (30초 주기)
- 역할별 권한 설정 UI (
/settings/permissions/[id])
5.2 미구현 사항
- 권한 매트릭스 API 호출
- 권한 데이터 저장 (permissionStore)
usePermission훅- 페이지/버튼별 권한 체크
- 환경 변수 플래그
6. 향후 구현 계획
6.1 프론트엔드 (1단계 - UI 제어)
로그인 성공
↓
/api/v1/permissions/users/{userId}/menu-matrix 호출
↓
권한 매트릭스 저장 (Zustand permissionStore)
↓
usePermission 훅으로 권한 체크
↓
버튼/기능 숨김/비활성화
usePermission 훅 예시:
// 사용법 (메뉴명 또는 URL로 조회)
const { canView, canCreate, canUpdate, canDelete, canApprove } = usePermission('/sales/orders');
// 적용
{canCreate && <Button>등록</Button>}
{canDelete && <Button>삭제</Button>}
{canApprove && <Button>승인</Button>}
환경 변수 플래그:
NEXT_PUBLIC_ENABLE_AUTHORIZATION=false # 개발 중에는 비활성화
6.2 백엔드 (2단계 - API 보안)
라우트에 menu_id 설정하여 API 레벨 권한 체크 활성화:
// 예시: routes/api.php
Route::get('/orders', [OrderController::class, 'index'])
->defaults('menu_id', 5); // 판매관리 메뉴 ID
Route::post('/orders', [OrderController::class, 'store'])
->defaults('menu_id', 5); // POST → create 권한 자동 체크
7. 보안 고려사항
7.1 현재 취약점
- 프론트에서만 UI 숨기면 개발자 도구로 우회 가능
- 직접 API 호출 시 권한 없이도 작업 가능
7.2 권장 구조 (이중 보안)
프론트엔드: UI 컨트롤 (UX 향상)
↓
백엔드: API 권한 체크 (실제 보안)
↓
권한 없으면 403 반환
8. 관련 파일 경로
프론트엔드 (sam-react-prod)
| 파일 | 설명 |
|---|---|
src/app/[locale]/(protected)/settings/permissions/ |
권한 설정 페이지 |
src/components/settings/PermissionManagement/ |
권한 관리 컴포넌트 |
src/layouts/AuthenticatedLayout.tsx |
메뉴 표시 레이아웃 |
src/middleware.ts |
인증 체크 (권한 체크 없음) |
src/store/menuStore.ts |
메뉴 상태 관리 |
백엔드 (sam-api)
| 파일 | 설명 |
|---|---|
app/Http/Controllers/Api/V1/PermissionController.php |
권한 매트릭스 API |
app/Http/Controllers/Api/V1/RolePermissionController.php |
역할 권한 API |
app/Http/Middleware/CheckPermission.php |
권한 체크 미들웨어 |
app/Http/Middleware/PermMapper.php |
HTTP → 액션 매핑 |
app/Services/PermissionService.php |
권한 매트릭스 서비스 |
app/Services/Authz/AccessService.php |
권한 판정 서비스 |
app/Services/Authz/RolePermissionService.php |
역할 권한 서비스 |
9. 결론
현재: 권한 설정은 가능하지만, 프론트/백엔드 모두 권한 체크 미적용
1단계 (프론트):
- 로그인 후 권한 매트릭스 API 호출
- usePermission 훅으로 UI 제어
- 환경 변수로 개발 중 비활성화
2단계 (백엔드):
- 라우트에 menu_id 설정
- API 레벨 권한 체크 활성화
이 문서는 권한 시스템 구현 시 참고용으로 작성되었습니다.