- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동) - 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/) - 기획팀 폴더 requests/ 생성 - plans/ → dev/dev_plans/ 이름 변경 - README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용) - resources.md 신규 (노션 링크용, assets/brochure 이관 예정) - CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동 - 전체 참조 경로 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.0 KiB
6.0 KiB
Super Admin Protection Feature
날짜: 2025-12-01 작업자: Claude Code 요청: 슈퍼관리자 보호 및 복원/영구삭제 권한 분리
1. 요구사항
1.1 슈퍼관리자 보호
- 일반관리자는 슈퍼관리자를 볼 수 없음 (목록에서 숨김)
- 일반관리자는 슈퍼관리자를 수정/삭제할 수 없음
- 슈퍼관리자만 다른 슈퍼관리자를 관리 가능
1.2 복원/영구삭제 권한 분리
- 복원 (Restore): 일반관리자도 가능
- 영구삭제 (Force Delete): 슈퍼관리자 전용
2. 구현 내용
2.1 라우트 수정 (routes/api.php)
8개 엔티티의 restore 라우트를 super.admin 미들웨어 밖으로 이동:
| 엔티티 | 라인 | 복원 라우트 | 영구삭제 라우트 |
|---|---|---|---|
| Tenants | 42-48 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| Departments | 76-82 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| Users | 93-99 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| Menus | 117-123 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| Boards | 151-157 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| PM Projects | 234-240 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| PM Tasks | 260-266 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
| PM Issues | 292-298 | POST /{id}/restore |
DELETE /{id}/force (super.admin) |
패턴:
// 복원 (일반관리자 가능)
Route::post('/{id}/restore', [Controller::class, 'restore'])->name('restore');
// 슈퍼관리자 전용 액션 (영구삭제)
Route::middleware('super.admin')->group(function () {
Route::delete('/{id}/force', [Controller::class, 'forceDestroy'])->name('forceDestroy');
});
2.2 서비스 레이어 수정
app/Services/UserService.php
public function canAccessUser(int $targetUserId): bool
{
// withTrashed()를 사용하여 soft-deleted 사용자도 확인 (복원 시 필요)
$targetUser = User::withTrashed()->find($targetUserId);
$currentUser = auth()->user();
// 대상 사용자가 슈퍼관리자이고 현재 사용자가 슈퍼관리자가 아니면 접근 불가
if ($targetUser?->is_super_admin && ! $currentUser?->is_super_admin) {
return false;
}
return true;
}
app/Services/UserPermissionService.php
public function canModifyUser(int $targetUserId): bool
{
// withTrashed()를 사용하여 일관성 유지
$targetUser = User::withTrashed()->find($targetUserId);
$currentUser = auth()->user();
if ($targetUser?->is_super_admin && ! $currentUser?->is_super_admin) {
return false;
}
return true;
}
핵심 수정: User::find() → User::withTrashed()->find()
- Soft-deleted 사용자도 조회 가능하게 변경
- 복원 작업 시 권한 체크가 정상 작동
2.3 뷰 레이어 수정
6개 테이블 뷰에 권한별 버튼 표시 로직 적용:
| 파일 | 복원 버튼 | 영구삭제 버튼 |
|---|---|---|
users/partials/table.blade.php |
$canModify 체크 |
is_super_admin 체크 |
users/partials/modal-info.blade.php |
슈퍼관리자이거나 대상이 일반사용자 | - |
departments/partials/table.blade.php |
항상 표시 | is_super_admin 체크 |
menus/partials/table.blade.php |
항상 표시 | is_super_admin 체크 |
boards/partials/table.blade.php |
항상 표시 | is_super_admin 체크 |
tenants/partials/table.blade.php |
항상 표시 | is_super_admin 체크 |
project-management/projects/partials/table.blade.php |
항상 표시 | is_super_admin 체크 |
Blade 패턴:
@if($item->deleted_at)
<!-- 삭제된 항목 - 복원은 일반관리자도 가능, 영구삭제는 슈퍼관리자만 -->
<button onclick="confirmRestore({{ $item->id }}, '{{ $item->name }}')">
복원
</button>
@if(auth()->user()?->is_super_admin)
<button onclick="confirmForceDelete({{ $item->id }}, '{{ $item->name }}')">
영구삭제
</button>
@endif
@endif
3. 수정된 파일 목록
라우트
routes/api.php- 8개 엔티티 restore 라우트 분리
서비스
app/Services/UserService.php-canAccessUser()withTrashed 적용app/Services/UserPermissionService.php-canModifyUser()withTrashed 적용
뷰 (Blade)
resources/views/users/partials/table.blade.phpresources/views/users/partials/modal-info.blade.phpresources/views/departments/partials/table.blade.phpresources/views/menus/partials/table.blade.phpresources/views/boards/partials/table.blade.phpresources/views/tenants/partials/table.blade.phpresources/views/project-management/projects/partials/table.blade.php
4. 테스트 시나리오
4.1 일반관리자 테스트
- 사용자 목록에서 슈퍼관리자가 보이지 않음
- 삭제된 사용자 복원 가능
- 삭제된 부서/메뉴/게시판/테넌트/프로젝트 복원 가능
- 영구삭제 버튼이 보이지 않음
- 슈퍼관리자 수정/삭제 불가 (API 레벨)
4.2 슈퍼관리자 테스트
- 모든 사용자 조회 가능 (슈퍼관리자 포함)
- 삭제된 항목 복원 가능
- 영구삭제 가능
- 다른 슈퍼관리자 관리 가능
5. 이슈 해결
5.1 302 Found 에러
문제: 일반관리자가 복원 API 호출 시 302 리다이렉트 발생
원인: restore 라우트가 super.admin 미들웨어 내부에 있었음
해결: restore 라우트를 미들웨어 밖으로 이동
5.2 Soft-deleted 사용자 권한 체크 실패
문제: User::find()가 soft-deleted 사용자를 조회하지 못함
원인: Eloquent 기본 동작으로 soft-deleted 레코드 제외
해결: User::withTrashed()->find() 사용
6. 관련 문서
claudedocs/archive-restore-feature-analysis.md- 아카이브/복원 기능 분석CURRENT_WORKS.md- 작업 히스토리