Files
sam-api/app/Services/Authz/RoleService.php
kent f896f267e7 fix(API): 역할 권한 서비스 버그 수정
- RolePermissionService: Menu 모델 네임스페이스 수정
  - \App\Models\Menus\Menu → \App\Models\Commons\Menu
- RolePermissionService: 존재하지 않는 컬럼 수정
  - code, path → url
- RoleService: 커스텀 Role 모델 사용
  - Spatie\Permission\Models\Role → App\Models\Permissions\Role
- Role 모델: users() 관계 추가

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-30 20:41:33 +09:00

192 lines
5.6 KiB
PHP

<?php
namespace App\Services\Authz;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use App\Models\Permissions\Role;
use Spatie\Permission\PermissionRegistrar;
class RoleService
{
protected static string $guard = 'api';
/** 목록 */
public static function index(array $params = [])
{
$tenantId = (int) app('tenant_id');
$page = (int) ($params['page'] ?? 1);
$size = (int) ($params['size'] ?? 10);
$q = trim((string) ($params['q'] ?? ''));
$query = Role::query()
->where('tenant_id', $tenantId)
->where('guard_name', self::$guard)
->withCount(['permissions', 'users']);
// 검색 필터
if ($q !== '') {
$query->where(function ($w) use ($q) {
$w->where('name', 'like', "%{$q}%")
->orWhere('description', 'like', "%{$q}%");
});
}
// 숨김 상태 필터
if (isset($params['is_hidden'])) {
$isHidden = filter_var($params['is_hidden'], FILTER_VALIDATE_BOOLEAN);
$query->where('is_hidden', $isHidden);
}
$list = $query->orderByDesc('id')
->paginate($size, ['*'], 'page', $page);
return $list;
}
/** 생성 */
public static function store(array $params = [])
{
$tenantId = (int) app('tenant_id');
$userId = app('api_user');
$v = Validator::make($params, [
'name' => [
'required', 'string', 'max:100',
Rule::unique('roles', 'name')->where(fn ($q) => $q
->where('tenant_id', $tenantId)
->where('guard_name', self::$guard)),
],
'description' => 'nullable|string|max:255',
'is_hidden' => 'sometimes|boolean',
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
// Spatie 팀(테넌트) 컨텍스트
app(PermissionRegistrar::class)->setPermissionsTeamId($tenantId);
$role = Role::create([
'tenant_id' => $tenantId,
'guard_name' => self::$guard,
'name' => $v->validated()['name'],
'description' => $params['description'] ?? null,
'is_hidden' => $params['is_hidden'] ?? false,
'created_by' => $userId,
]);
return $role->loadCount(['permissions', 'users']);
}
/** 단건 */
public static function show(int $id)
{
$tenantId = (int) app('tenant_id');
$role = Role::where('tenant_id', $tenantId)
->where('guard_name', self::$guard)
->withCount(['permissions', 'users'])
->find($id);
if (! $role) {
return ['error' => '역할을 찾을 수 없습니다.', 'code' => 404];
}
return $role;
}
/** 수정 */
public static function update(int $id, array $params = [])
{
$tenantId = (int) app('tenant_id');
$userId = app('api_user');
$role = Role::where('tenant_id', $tenantId)
->where('guard_name', self::$guard)
->find($id);
if (! $role) {
return ['error' => '역할을 찾을 수 없습니다.', 'code' => 404];
}
$v = Validator::make($params, [
'name' => [
'sometimes', 'string', 'max:100',
Rule::unique('roles', 'name')
->where(fn ($q) => $q->where('tenant_id', $tenantId)->where('guard_name', self::$guard))
->ignore($role->id),
],
'description' => 'sometimes|nullable|string|max:255',
'is_hidden' => 'sometimes|boolean',
]);
if ($v->fails()) {
return ['error' => $v->errors()->first(), 'code' => 422];
}
$updateData = $v->validated();
$updateData['updated_by'] = $userId;
$role->fill($updateData)->save();
return $role->fresh()->loadCount(['permissions', 'users']);
}
/** 삭제 (Soft Delete) */
public static function destroy(int $id)
{
$tenantId = (int) app('tenant_id');
$userId = app('api_user');
$role = Role::where('tenant_id', $tenantId)
->where('guard_name', self::$guard)
->find($id);
if (! $role) {
return ['error' => '역할을 찾을 수 없습니다.', 'code' => 404];
}
DB::transaction(function () use ($role, $userId) {
// 권한 연결 해제
$role->permissions()->detach();
// Soft Delete
$role->update(['deleted_by' => $userId]);
$role->delete();
});
return 'success';
}
/** 통계 조회 */
public static function stats()
{
$tenantId = (int) app('tenant_id');
$baseQuery = Role::where('tenant_id', $tenantId)
->where('guard_name', self::$guard);
return [
'total' => (clone $baseQuery)->count(),
'visible' => (clone $baseQuery)->where('is_hidden', false)->count(),
'hidden' => (clone $baseQuery)->where('is_hidden', true)->count(),
'with_users' => (clone $baseQuery)->has('users')->count(),
];
}
/** 활성 역할 목록 (드롭다운용) */
public static function active()
{
$tenantId = (int) app('tenant_id');
return Role::where('tenant_id', $tenantId)
->where('guard_name', self::$guard)
->where('is_hidden', false)
->orderBy('name')
->get(['id', 'name', 'description']);
}
}