withCount('permissions'); // Guard 필터링 (선택된 경우에만) if (! empty($filters['guard_name'])) { $query->where('guard_name', $filters['guard_name']); } // 전체 보기일 때 tenant 정보 로드 if (! $tenantId || $tenantId === 'all') { $query->with('tenant'); } // Tenant 필터링 (선택된 경우에만) if ($tenantId && $tenantId !== 'all') { $query->where('tenant_id', $tenantId); } // 검색 필터 if (! empty($filters['search'])) { $search = $filters['search']; $query->where(function ($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('description', 'like', "%{$search}%"); }); } // 정렬 $sortBy = $filters['sort_by'] ?? 'id'; $sortDirection = $filters['sort_direction'] ?? 'desc'; $query->orderBy($sortBy, $sortDirection); return $query->paginate($perPage); } /** * 특정 역할 조회 */ public function getRoleById(int $id): ?Role { $tenantId = session('selected_tenant_id'); $query = Role::query()->with('permissions'); // Tenant 필터링 (선택된 경우에만) if ($tenantId && $tenantId !== 'all') { $query->where('tenant_id', $tenantId); } return $query->find($id); } /** * 역할 생성 */ public function createRole(array $data): Role { $tenantId = session('selected_tenant_id'); $effectiveTenantId = ($tenantId && $tenantId !== 'all') ? $tenantId : null; $guardName = $data['guard_name'] ?? 'api'; $role = Role::create([ 'tenant_id' => $effectiveTenantId, 'guard_name' => $guardName, 'name' => $data['name'], 'description' => $data['description'] ?? null, ]); // 메뉴 권한 동기화 (있는 경우) if (! empty($data['menu_permissions'])) { $this->syncMenuPermissions($role, $data['menu_permissions'], $effectiveTenantId, $guardName); } return $role->fresh(['permissions']); } /** * 역할 수정 */ public function updateRole(int $id, array $data): bool { $role = $this->getRoleById($id); if (! $role) { return false; } $tenantId = session('selected_tenant_id'); $effectiveTenantId = ($tenantId && $tenantId !== 'all') ? $tenantId : null; $guardName = $data['guard_name'] ?? $role->guard_name; $updated = $role->update([ 'name' => $data['name'] ?? $role->name, 'guard_name' => $guardName, 'description' => $data['description'] ?? $role->description, ]); // 메뉴 권한 동기화 (있는 경우) if (isset($data['menu_permissions'])) { $this->syncMenuPermissions($role, $data['menu_permissions'], $effectiveTenantId, $guardName); } return $updated; } /** * 메뉴 권한 동기화 */ protected function syncMenuPermissions(Role $role, array $menuPermissions, ?int $tenantId, string $guardName): void { // 기존 메뉴 권한 모두 제거 DB::table('role_has_permissions') ->where('role_id', $role->id) ->whereIn('permission_id', function ($query) use ($guardName) { $query->select('id') ->from('permissions') ->where('guard_name', $guardName) ->where('name', 'like', 'menu:%'); }) ->delete(); // 새로운 권한 부여 foreach ($menuPermissions as $menuId => $types) { if (! is_array($types)) { continue; } foreach ($types as $type) { $permissionName = "menu:{$menuId}.{$type}"; // 권한 생성 또는 조회 $permission = Permission::firstOrCreate( ['name' => $permissionName, 'guard_name' => $guardName, 'tenant_id' => $tenantId], ['created_by' => auth()->id()] ); // 권한 부여 $exists = DB::table('role_has_permissions') ->where('role_id', $role->id) ->where('permission_id', $permission->id) ->exists(); if (! $exists) { DB::table('role_has_permissions')->insert([ 'role_id' => $role->id, 'permission_id' => $permission->id, ]); } } } } /** * 역할 삭제 */ public function deleteRole(int $id): bool { $role = $this->getRoleById($id); if (! $role) { return false; } // 권한 연결 해제 $role->permissions()->detach(); // 사용자 연결은 FK CASCADE가 자동 처리 (model_has_roles.role_id → ON DELETE CASCADE) return $role->delete(); } /** * 역할 이름 중복 체크 */ public function isNameExists(string $name, ?int $excludeId = null): bool { $tenantId = session('selected_tenant_id'); $query = Role::where('guard_name', 'web') ->where('name', $name); if ($tenantId && $tenantId !== 'all') { $query->where('tenant_id', $tenantId); } if ($excludeId) { $query->where('id', '!=', $excludeId); } return $query->exists(); } /** * 활성 역할 목록 (드롭다운용) */ public function getActiveRoles(): Collection { $tenantId = session('selected_tenant_id'); $query = Role::query()->where('guard_name', 'web'); // Tenant 필터링 (선택된 경우에만) if ($tenantId && $tenantId !== 'all') { $query->where('tenant_id', $tenantId); } return $query->orderBy('name')->get(['id', 'name', 'description']); } /** * 역할 통계 */ public function getRoleStats(): array { $tenantId = session('selected_tenant_id'); $baseQuery = Role::query()->where('guard_name', 'web'); // Tenant 필터링 (선택된 경우에만) if ($tenantId && $tenantId !== 'all') { $baseQuery->where('tenant_id', $tenantId); } return [ 'total' => (clone $baseQuery)->count(), 'with_permissions' => (clone $baseQuery)->has('permissions')->count(), ]; } }