feat: [users] 슈퍼관리자 보호 기능 구현

- 일반관리자가 슈퍼관리자 수정/삭제 불가
- API Controller: update/destroy에서 403 반환
- Web Controller: edit에서 403 abort
- FormRequest: is_super_admin 필드 강제/유지 처리
- View: 테이블, 모달, 생성/수정 폼에서 버튼/체크박스 숨김

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-30 23:05:07 +09:00
parent 6be0a219c3
commit 049fa7ed61
8 changed files with 88 additions and 11 deletions

View File

@@ -139,11 +139,13 @@ class="h-4 w-4 text-green-600 rounded focus:ring-2 focus:ring-green-500">
class="h-4 w-4 text-blue-600 rounded focus:ring-2 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">활성 상태</span>
</label>
@if(auth()->user()?->is_super_admin)
<label class="flex items-center">
<input type="checkbox" name="is_super_admin" value="1"
class="h-4 w-4 text-red-600 rounded focus:ring-2 focus:ring-red-500">
<span class="ml-2 text-sm text-gray-700">슈퍼 관리자</span>
</label>
@endif
</div>
</div>

View File

@@ -144,12 +144,14 @@ class="h-4 w-4 text-green-600 rounded focus:ring-2 focus:ring-green-500">
class="h-4 w-4 text-blue-600 rounded focus:ring-2 focus:ring-blue-500">
<span class="ml-2 text-sm text-gray-700">활성 상태</span>
</label>
@if(auth()->user()?->is_super_admin)
<label class="flex items-center">
<input type="checkbox" name="is_super_admin" value="1"
{{ old('is_super_admin', $user->is_super_admin) ? 'checked' : '' }}
class="h-4 w-4 text-red-600 rounded focus:ring-2 focus:ring-red-500">
<span class="ml-2 text-sm text-gray-700">슈퍼 관리자</span>
</label>
@endif
</div>
</div>

View File

@@ -179,23 +179,31 @@ class="text-xs text-blue-600 hover:text-blue-800 hover:underline">
</div>
{{-- 하단 버튼 --}}
@php
// 슈퍼관리자 보호: 일반관리자가 슈퍼관리자를 수정/삭제할 수 없음
$canModify = ! $user->is_super_admin || auth()->user()?->is_super_admin;
@endphp
<div class="flex justify-end gap-2 mt-6 pt-4 border-t border-gray-200">
<button type="button"
onclick="UserModal.close()"
class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50">
닫기
</button>
@if(!$user->deleted_at)
@if($canModify)
@if(!$user->deleted_at)
<button type="button"
onclick="UserModal.deleteUser()"
class="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-lg hover:bg-red-700">
삭제
</button>
@endif
<button type="button"
onclick="UserModal.deleteUser()"
class="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-lg hover:bg-red-700">
삭제
onclick="UserModal.goToEdit()"
class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700">
수정
</button>
@else
<span class="px-4 py-2 text-sm text-gray-400">슈퍼관리자는 수정할 없습니다</span>
@endif
<button type="button"
onclick="UserModal.goToEdit()"
class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700">
수정
</button>
</div>
</div>

View File

@@ -78,6 +78,10 @@
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium" onclick="event.stopPropagation()">
@php
// 슈퍼관리자 보호: 일반관리자가 슈퍼관리자를 수정/삭제할 수 없음
$canModify = ! $user->is_super_admin || auth()->user()?->is_super_admin;
@endphp
@if($user->deleted_at)
<!-- 삭제된 항목 - 슈퍼관리자만 복구/영구삭제 가능 -->
@if(auth()->user()?->is_super_admin)
@@ -92,8 +96,8 @@ class="text-red-600 hover:text-red-900">
@else
<span class="text-gray-400 text-xs">삭제됨</span>
@endif
@else
<!-- 활성 항목 -->
@elseif($canModify)
<!-- 활성 항목 (수정 가능한 경우만) -->
<a href="{{ route('users.edit', $user->id) }}"
onclick="event.stopPropagation()"
class="text-blue-600 hover:text-blue-900 mr-3">
@@ -102,6 +106,9 @@ class="text-blue-600 hover:text-blue-900 mr-3">
<button onclick="confirmDelete({{ $user->id }}, '{{ $user->name }}')" class="text-red-600 hover:text-red-900">
삭제
</button>
@else
<!-- 슈퍼관리자 - 일반관리자는 수정/삭제 불가 -->
<span class="text-gray-400 text-xs">수정 불가</span>
@endif
</td>
</tr>