fix : 부서관리 기능 수정
- Route, Controller, Service, Swagger, DB 수정 - 모델 위치 이동
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Commons\Department;
|
||||
use App\Models\Commons\DepartmentPermission;
|
||||
use App\Models\Commons\DepartmentUser;
|
||||
use App\Models\Tenants\Department;
|
||||
use App\Models\Tenants\Pivots\DepartmentUser;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -299,6 +298,7 @@ public function setPrimary(int $deptId, int $userId, array $params)
|
||||
/** 부서 권한 목록 */
|
||||
public function listPermissions(int $deptId, array $params)
|
||||
{
|
||||
// 1) 파라미터 검증
|
||||
$p = $this->v($params, [
|
||||
'menu_id' => 'nullable|integer|min:1',
|
||||
'is_allowed' => 'nullable|in:0,1',
|
||||
@@ -308,18 +308,78 @@ public function listPermissions(int $deptId, array $params)
|
||||
if ($p instanceof JsonResponse) return $p;
|
||||
if (isset($p['error'])) return $p;
|
||||
|
||||
// 2) 부서 확인
|
||||
$dept = Department::query()->find($deptId);
|
||||
if (!$dept) return ['error' => '부서를 찾을 수 없습니다.', 'code' => 404];
|
||||
|
||||
$q = DepartmentPermission::query()
|
||||
->whereNull('deleted_at')
|
||||
->where('department_id', $deptId);
|
||||
$tenantId = (int)$dept->tenant_id;
|
||||
$modelType = Department::class;
|
||||
|
||||
if (isset($p['menu_id'])) $q->where('menu_id', $p['menu_id']);
|
||||
if (isset($p['is_allowed'])) $q->where('is_allowed', (int)$p['is_allowed']);
|
||||
// 3) ALLOW/DENY 서브쿼리 준비 (컬럼 형태 통일)
|
||||
$allowSub = DB::table('model_has_permissions')
|
||||
->select([
|
||||
'permission_id',
|
||||
DB::raw('1 as is_allowed'),
|
||||
DB::raw('NULL as reason'),
|
||||
DB::raw('NULL as effective_from'),
|
||||
DB::raw('NULL as effective_to'),
|
||||
DB::raw('NULL as override_id'),
|
||||
DB::raw('NULL as override_updated_at'),
|
||||
])
|
||||
->where([
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'tenant_id' => $tenantId,
|
||||
]);
|
||||
|
||||
$q->orderByDesc('is_allowed')->orderBy('permission_id');
|
||||
$denySub = DB::table('permission_overrides')
|
||||
->select([
|
||||
'permission_id',
|
||||
DB::raw('0 as is_allowed'),
|
||||
'reason',
|
||||
'effective_from',
|
||||
'effective_to',
|
||||
'id as override_id',
|
||||
'updated_at as override_updated_at',
|
||||
])
|
||||
->where([
|
||||
'tenant_id' => $tenantId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
])
|
||||
->where('effect', -1);
|
||||
|
||||
// 4) 합치고 permissions 조인
|
||||
$q = DB::query()
|
||||
->fromSub(function ($sub) use ($allowSub, $denySub) {
|
||||
$sub->from($allowSub->unionAll($denySub), 'u');
|
||||
}, 'u')
|
||||
->join('permissions', 'permissions.id', '=', 'u.permission_id')
|
||||
->select([
|
||||
'u.permission_id',
|
||||
'u.is_allowed',
|
||||
'permissions.name as permission_code',
|
||||
'permissions.guard_name',
|
||||
'u.reason',
|
||||
'u.effective_from',
|
||||
'u.effective_to',
|
||||
'u.override_id',
|
||||
'u.override_updated_at',
|
||||
]);
|
||||
|
||||
// 5) 필터
|
||||
if (isset($p['is_allowed'])) {
|
||||
$q->where('u.is_allowed', (int)$p['is_allowed']);
|
||||
}
|
||||
if (isset($p['menu_id'])) {
|
||||
// 권한코드가 menu.{id}.xxx 형태라는 전제
|
||||
$q->where('permissions.name', 'like', 'menu.' . (int)$p['menu_id'] . '.%');
|
||||
}
|
||||
|
||||
// 6) 정렬(ALLOW 우선, 그 다음 permission_id 오름차순)
|
||||
$q->orderByDesc('u.is_allowed')->orderBy('u.permission_id');
|
||||
|
||||
// 7) 페이지네이션
|
||||
$perPage = $p['per_page'] ?? 20;
|
||||
$page = $p['page'] ?? null;
|
||||
|
||||
@@ -327,58 +387,170 @@ public function listPermissions(int $deptId, array $params)
|
||||
}
|
||||
|
||||
/** 권한 부여/차단 upsert */
|
||||
public function upsertPermission(int $deptId, array $params)
|
||||
public function upsertPermissions(int $deptId, array $payload): array
|
||||
{
|
||||
$p = $this->v($params, [
|
||||
'permission_id' => 'required|integer|min:1',
|
||||
'menu_id' => 'nullable|integer|min:1',
|
||||
'is_allowed' => 'nullable|in:0,1',
|
||||
// 단일이면 items로 감싸기
|
||||
$items = isset($payload['permission_id'])
|
||||
? [ $payload ]
|
||||
: ($payload['items'] ?? $payload);
|
||||
|
||||
$v = Validator::make(['items'=>$items], [
|
||||
'items' => 'required|array|max:1000',
|
||||
'items.*.permission_id' => 'required|integer|min:1',
|
||||
'items.*.is_allowed' => 'nullable|in:0,1', // 생략 시 1(허용)
|
||||
]);
|
||||
if ($p instanceof JsonResponse) return $p;
|
||||
if (isset($p['error'])) return $p;
|
||||
if ($v->fails()) return ['error'=>$v->errors()->first(),'code'=>422];
|
||||
|
||||
$dept = Department::query()->find($deptId);
|
||||
if (!$dept) return ['error' => '부서를 찾을 수 없습니다.', 'code' => 404];
|
||||
|
||||
$payload = [
|
||||
'department_id' => $deptId,
|
||||
'permission_id' => $p['permission_id'],
|
||||
'menu_id' => $p['menu_id'] ?? null,
|
||||
$tenantId = (int)$dept->tenant_id;
|
||||
$modelType = Department::class;
|
||||
|
||||
$ok = 0; $failed = [];
|
||||
|
||||
DB::transaction(function () use ($items, $tenantId, $deptId, $modelType, &$ok, &$failed) {
|
||||
foreach ($items as $i => $r) {
|
||||
try {
|
||||
$permissionId = (int)$r['permission_id'];
|
||||
$isAllowed = array_key_exists('is_allowed', $r) ? (int)$r['is_allowed'] : 1;
|
||||
|
||||
if ($isAllowed === 1) {
|
||||
// ALLOW: Spatie 표준에 넣고, 동일 권한의 DENY 제거
|
||||
$exists = DB::table('model_has_permissions')->where([
|
||||
'permission_id' => $permissionId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'tenant_id' => $tenantId,
|
||||
])->exists();
|
||||
|
||||
if (!$exists) {
|
||||
DB::table('model_has_permissions')->insert([
|
||||
'permission_id' => $permissionId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'tenant_id' => $tenantId,
|
||||
]);
|
||||
}
|
||||
|
||||
DB::table('permission_overrides')->where([
|
||||
'tenant_id' => $tenantId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'permission_id' => $permissionId,
|
||||
'effect' => -1,
|
||||
])->delete();
|
||||
} else {
|
||||
// DENY: overrides(effect=-1) upsert, 그리고 ALLOW 제거
|
||||
$exists = DB::table('permission_overrides')->where([
|
||||
'tenant_id' => $tenantId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'permission_id' => $permissionId,
|
||||
])->exists();
|
||||
|
||||
if ($exists) {
|
||||
DB::table('permission_overrides')->where([
|
||||
'tenant_id' => $tenantId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'permission_id' => $permissionId,
|
||||
])->update(['effect' => -1, 'updated_at' => now()]);
|
||||
} else {
|
||||
DB::table('permission_overrides')->insert([
|
||||
'tenant_id' => $tenantId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'permission_id' => $permissionId,
|
||||
'effect' => -1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
DB::table('model_has_permissions')->where([
|
||||
'permission_id' => $permissionId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'tenant_id' => $tenantId,
|
||||
])->delete();
|
||||
}
|
||||
|
||||
$ok++;
|
||||
} catch (\Throwable $e) {
|
||||
$failed[] = [
|
||||
'index' => $i,
|
||||
'permission_id' => $r['permission_id'] ?? null,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return [
|
||||
'processed' => count($items),
|
||||
'succeeded' => $ok,
|
||||
'failed' => $failed
|
||||
];
|
||||
|
||||
$model = DepartmentPermission::withTrashed()->firstOrNew($payload);
|
||||
$model->is_allowed = isset($p['is_allowed']) ? (int)$p['is_allowed'] : 1;
|
||||
$model->deleted_at = null;
|
||||
$model->save();
|
||||
|
||||
// 변경 후 목록 반환
|
||||
return $this->listPermissions($deptId, []);
|
||||
}
|
||||
|
||||
/** 권한 제거 (menu_id 없으면 전체 제거) */
|
||||
public function revokePermission(int $deptId, int $permissionId, array $params)
|
||||
public function revokePermissions(int $deptId, array $payload): array
|
||||
{
|
||||
$p = $this->v($params, [
|
||||
'menu_id' => 'nullable|integer|min:1',
|
||||
$items = isset($payload['permission_id'])
|
||||
? [ $payload ]
|
||||
: ($payload['items'] ?? $payload);
|
||||
|
||||
$v = Validator::make(['items'=>$items], [
|
||||
'items' => 'required|array|max:1000',
|
||||
'items.*.permission_id' => 'required|integer|min:1',
|
||||
]);
|
||||
if ($p instanceof JsonResponse) return $p;
|
||||
if (isset($p['error'])) return $p;
|
||||
if ($v->fails()) return ['error'=>$v->errors()->first(),'code'=>422];
|
||||
|
||||
$q = DepartmentPermission::whereNull('deleted_at')
|
||||
->where('department_id', $deptId)
|
||||
->where('permission_id', $permissionId);
|
||||
$dept = Department::query()->find($deptId);
|
||||
if (!$dept) return ['error' => '부서를 찾을 수 없습니다.', 'code' => 404];
|
||||
|
||||
if (isset($p['menu_id'])) $q->where('menu_id', $p['menu_id']);
|
||||
$tenantId = (int)$dept->tenant_id;
|
||||
$modelType = Department::class;
|
||||
|
||||
$rows = $q->get();
|
||||
if ($rows->isEmpty()) return ['error' => '대상 권한을 찾을 수 없습니다.', 'code' => 404];
|
||||
$ok = 0; $failed = [];
|
||||
|
||||
foreach ($rows as $row) $row->delete();
|
||||
DB::transaction(function () use ($items, $tenantId, $deptId, $modelType, &$ok, &$failed) {
|
||||
foreach ($items as $i => $r) {
|
||||
try {
|
||||
$permissionId = (int)$r['permission_id'];
|
||||
|
||||
// ALLOW 제거
|
||||
DB::table('model_has_permissions')->where([
|
||||
'permission_id' => $permissionId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'tenant_id' => $tenantId,
|
||||
])->delete();
|
||||
|
||||
// DENY/임시허용 오버라이드 제거
|
||||
DB::table('permission_overrides')->where([
|
||||
'tenant_id' => $tenantId,
|
||||
'model_type' => $modelType,
|
||||
'model_id' => $deptId,
|
||||
'permission_id' => $permissionId,
|
||||
])->delete();
|
||||
|
||||
$ok++;
|
||||
} catch (\Throwable $e) {
|
||||
$failed[] = [
|
||||
'index' => $i,
|
||||
'permission_id' => $r['permission_id'] ?? null,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return [
|
||||
'permission_id' => $permissionId,
|
||||
'menu_id' => $p['menu_id'] ?? null,
|
||||
'deleted_count' => $rows->count(),
|
||||
'processed' => count($items),
|
||||
'succeeded' => $ok,
|
||||
'failed' => $failed
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user