Files
sam-docs/dev/guides/super-admin-protection.md
권혁성 db63fcff85 refactor: [docs] 팀별 폴더 구조 재편 (공유/개발/프론트/기획)
- 개발팀 전용 폴더 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>
2026-03-05 16:46:03 +09:00

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.php
  • resources/views/users/partials/modal-info.blade.php
  • resources/views/departments/partials/table.blade.php
  • resources/views/menus/partials/table.blade.php
  • resources/views/boards/partials/table.blade.php
  • resources/views/tenants/partials/table.blade.php
  • resources/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 - 작업 히스토리