From 049fa7ed61bf94f9385a08b93cc1e95d74ae5371 Mon Sep 17 00:00:00 2001 From: kent Date: Sun, 30 Nov 2025 23:05:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[users]=20=EC=8A=88=ED=8D=BC=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EC=9E=90=20=EB=B3=B4=ED=98=B8=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 일반관리자가 슈퍼관리자 수정/삭제 불가 - 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 --- .../Controllers/Api/Admin/UserController.php | 18 +++++++++++++ app/Http/Controllers/UserController.php | 5 ++++ app/Http/Requests/StoreUserRequest.php | 14 ++++++++++ app/Http/Requests/UpdateUserRequest.php | 21 +++++++++++++++ resources/views/users/create.blade.php | 2 ++ resources/views/users/edit.blade.php | 2 ++ .../views/users/partials/modal-info.blade.php | 26 ++++++++++++------- .../views/users/partials/table.blade.php | 11 ++++++-- 8 files changed, 88 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/Api/Admin/UserController.php b/app/Http/Controllers/Api/Admin/UserController.php index 424db1a5..bd8cc0f9 100644 --- a/app/Http/Controllers/Api/Admin/UserController.php +++ b/app/Http/Controllers/Api/Admin/UserController.php @@ -93,6 +93,15 @@ public function store(StoreUserRequest $request): JsonResponse public function update(UpdateUserRequest $request, int $id): JsonResponse { try { + // 슈퍼관리자 보호: 일반관리자가 슈퍼관리자를 수정하려는 경우 차단 + $targetUser = $this->userService->getUserById($id); + if ($targetUser?->is_super_admin && ! auth()->user()?->is_super_admin) { + return response()->json([ + 'success' => false, + 'message' => '슈퍼관리자는 수정할 수 없습니다.', + ], 403); + } + $result = $this->userService->updateUser($id, $request->validated()); if (! $result) { @@ -121,6 +130,15 @@ public function update(UpdateUserRequest $request, int $id): JsonResponse public function destroy(int $id): JsonResponse { try { + // 슈퍼관리자 보호: 일반관리자가 슈퍼관리자를 삭제하려는 경우 차단 + $targetUser = $this->userService->getUserById($id); + if ($targetUser?->is_super_admin && ! auth()->user()?->is_super_admin) { + return response()->json([ + 'success' => false, + 'message' => '슈퍼관리자는 삭제할 수 없습니다.', + ], 403); + } + $result = $this->userService->deleteUser($id); if (! $result) { diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 760fbd20..a681c635 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -47,6 +47,11 @@ public function edit(int $id): View abort(404, '사용자를 찾을 수 없습니다.'); } + // 슈퍼관리자 보호: 일반관리자가 슈퍼관리자를 수정하려는 경우 차단 + if ($user->is_super_admin && ! auth()->user()?->is_super_admin) { + abort(403, '슈퍼관리자는 수정할 수 없습니다.'); + } + $tenantId = session('selected_tenant_id'); // 역할/부서 목록 (테넌트별) diff --git a/app/Http/Requests/StoreUserRequest.php b/app/Http/Requests/StoreUserRequest.php index e3e8d050..3f55cfb0 100644 --- a/app/Http/Requests/StoreUserRequest.php +++ b/app/Http/Requests/StoreUserRequest.php @@ -14,6 +14,20 @@ public function authorize(): bool return true; } + /** + * Prepare the data for validation. + * 일반관리자가 슈퍼관리자를 생성하려는 경우 is_super_admin 필드 제거 + */ + protected function prepareForValidation(): void + { + // 슈퍼관리자가 아닌 경우 is_super_admin 필드를 false로 강제 설정 + if (! auth()->user()?->is_super_admin) { + $this->merge([ + 'is_super_admin' => false, + ]); + } + } + /** * Get the validation rules that apply to the request. * diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php index 52a6865f..584a39b4 100644 --- a/app/Http/Requests/UpdateUserRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -15,6 +15,27 @@ public function authorize(): bool return true; } + /** + * Prepare the data for validation. + * 일반관리자가 슈퍼관리자 관련 필드를 변경하려는 경우 처리 + */ + protected function prepareForValidation(): void + { + $userId = $this->route('id'); + $targetUser = \App\Models\User::find($userId); + $currentUser = auth()->user(); + + // 슈퍼관리자가 아닌 경우 + if (! $currentUser?->is_super_admin) { + // is_super_admin 필드가 있으면 제거 (기존 값 유지) + if ($this->has('is_super_admin')) { + $this->merge([ + 'is_super_admin' => $targetUser?->is_super_admin ?? false, + ]); + } + } + } + /** * Get the validation rules that apply to the request. * diff --git a/resources/views/users/create.blade.php b/resources/views/users/create.blade.php index 1b9967b6..8f50e02a 100644 --- a/resources/views/users/create.blade.php +++ b/resources/views/users/create.blade.php @@ -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"> 활성 상태 + @if(auth()->user()?->is_super_admin) + @endif diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index 26e7404f..45ee713d 100644 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -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"> 활성 상태 + @if(auth()->user()?->is_super_admin) + @endif diff --git a/resources/views/users/partials/modal-info.blade.php b/resources/views/users/partials/modal-info.blade.php index fd2722ba..1ff6af1d 100644 --- a/resources/views/users/partials/modal-info.blade.php +++ b/resources/views/users/partials/modal-info.blade.php @@ -179,23 +179,31 @@ class="text-xs text-blue-600 hover:text-blue-800 hover:underline"> {{-- 하단 버튼 --}} + @php + // 슈퍼관리자 보호: 일반관리자가 슈퍼관리자를 수정/삭제할 수 없음 + $canModify = ! $user->is_super_admin || auth()->user()?->is_super_admin; + @endphp
- @if(!$user->deleted_at) + @if($canModify) + @if(!$user->deleted_at) + + @endif + @else + 슈퍼관리자는 수정할 수 없습니다 @endif -
diff --git a/resources/views/users/partials/table.blade.php b/resources/views/users/partials/table.blade.php index a74e61af..bb6d3a41 100644 --- a/resources/views/users/partials/table.blade.php +++ b/resources/views/users/partials/table.blade.php @@ -78,6 +78,10 @@ @endif + @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 삭제됨 @endif - @else - + @elseif($canModify) + @@ -102,6 +106,9 @@ class="text-blue-600 hover:text-blue-900 mr-3"> + @else + + 수정 불가 @endif