2025-08-16 03:25:06 +09:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Observers;
|
|
|
|
|
|
|
|
|
|
use App\Models\Commons\Menu; // ← 실제 경로 확인
|
2025-11-10 10:30:35 +09:00
|
|
|
use Illuminate\Support\Facades\DB;
|
2025-08-16 03:25:06 +09:00
|
|
|
use Spatie\Permission\Models\Permission;
|
|
|
|
|
use Spatie\Permission\PermissionRegistrar;
|
|
|
|
|
|
|
|
|
|
class MenuObserver
|
|
|
|
|
{
|
|
|
|
|
protected function actions(): array
|
|
|
|
|
{
|
|
|
|
|
// config/authz.php 에서 오버라이드 가능 (없으면 기본값)
|
2025-11-06 17:45:49 +09:00
|
|
|
return config('authz.menu_actions', ['view', 'create', 'update', 'delete', 'approve']);
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected string $guard = 'api';
|
|
|
|
|
|
|
|
|
|
public function created(Menu $menu): void
|
|
|
|
|
{
|
2025-11-06 17:45:49 +09:00
|
|
|
if (! $this->shouldHandle($menu)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-16 03:25:06 +09:00
|
|
|
|
2025-11-06 17:45:49 +09:00
|
|
|
$this->setTeam((int) $menu->tenant_id);
|
2025-08-16 03:25:06 +09:00
|
|
|
$this->ensurePermissions($menu);
|
2025-11-10 10:30:35 +09:00
|
|
|
$this->forgetCacheAfterCommit();
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function updated(Menu $menu): void
|
|
|
|
|
{
|
|
|
|
|
// 메뉴 ID 기반: 권한 이름 변경 불필요
|
|
|
|
|
// 필요 시, 기본 롤 자동 부여/회수 같은 정책을 이곳에…
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function deleted(Menu $menu): void
|
|
|
|
|
{
|
2025-11-06 17:45:49 +09:00
|
|
|
if (! $this->shouldHandle($menu)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-16 03:25:06 +09:00
|
|
|
|
2025-11-06 17:45:49 +09:00
|
|
|
$this->setTeam((int) $menu->tenant_id);
|
2025-08-16 03:25:06 +09:00
|
|
|
$this->removePermissions($menu);
|
2025-11-10 10:30:35 +09:00
|
|
|
$this->forgetCacheAfterCommit();
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function restored(Menu $menu): void
|
|
|
|
|
{
|
2025-11-06 17:45:49 +09:00
|
|
|
if (! $this->shouldHandle($menu)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-16 03:25:06 +09:00
|
|
|
|
2025-11-06 17:45:49 +09:00
|
|
|
$this->setTeam((int) $menu->tenant_id);
|
2025-08-16 03:25:06 +09:00
|
|
|
$this->ensurePermissions($menu);
|
2025-11-10 10:30:35 +09:00
|
|
|
$this->forgetCacheAfterCommit();
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function forceDeleted(Menu $menu): void
|
|
|
|
|
{
|
2025-11-06 17:45:49 +09:00
|
|
|
if (! $this->shouldHandle($menu)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-16 03:25:06 +09:00
|
|
|
|
2025-11-06 17:45:49 +09:00
|
|
|
$this->setTeam((int) $menu->tenant_id);
|
2025-08-16 03:25:06 +09:00
|
|
|
$this->removePermissions($menu);
|
2025-11-10 10:30:35 +09:00
|
|
|
$this->forgetCacheAfterCommit();
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** teams 사용 시 tenant_id 없는 공용 메뉴는 스킵하는 게 안전 */
|
|
|
|
|
protected function shouldHandle(Menu $menu): bool
|
|
|
|
|
{
|
2025-11-06 17:45:49 +09:00
|
|
|
return ! is_null($menu->tenant_id);
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function setTeam(int $tenantId): void
|
|
|
|
|
{
|
|
|
|
|
app(PermissionRegistrar::class)->setPermissionsTeamId($tenantId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function ensurePermissions(Menu $menu): void
|
|
|
|
|
{
|
2025-11-10 10:30:35 +09:00
|
|
|
$actions = $this->actions();
|
|
|
|
|
$permissionsData = [];
|
|
|
|
|
$now = now();
|
|
|
|
|
|
|
|
|
|
foreach ($actions as $act) {
|
|
|
|
|
$permissionsData[] = [
|
2025-11-06 17:45:49 +09:00
|
|
|
'tenant_id' => (int) $menu->tenant_id,
|
2025-08-16 03:25:06 +09:00
|
|
|
'guard_name' => $this->guard,
|
2025-11-06 17:45:49 +09:00
|
|
|
'name' => "menu:{$menu->id}.{$act}",
|
2025-11-10 10:30:35 +09:00
|
|
|
'created_at' => $now,
|
|
|
|
|
'updated_at' => $now,
|
|
|
|
|
];
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
2025-11-10 10:30:35 +09:00
|
|
|
|
|
|
|
|
// Bulk insert using insertOrIgnore to avoid duplicate errors
|
|
|
|
|
DB::table('permissions')->insertOrIgnore($permissionsData);
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function removePermissions(Menu $menu): void
|
|
|
|
|
{
|
2025-11-06 17:45:49 +09:00
|
|
|
Permission::where('tenant_id', (int) $menu->tenant_id)
|
2025-08-16 03:25:06 +09:00
|
|
|
->where('guard_name', $this->guard)
|
|
|
|
|
->where(function ($q) use ($menu) {
|
|
|
|
|
foreach ($this->actions() as $act) {
|
|
|
|
|
$q->orWhere('name', "menu:{$menu->id}.{$act}");
|
|
|
|
|
}
|
|
|
|
|
})->delete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function forgetCache(): void
|
|
|
|
|
{
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
}
|
2025-11-10 10:30:35 +09:00
|
|
|
|
|
|
|
|
protected function forgetCacheAfterCommit(): void
|
|
|
|
|
{
|
|
|
|
|
// Defer cache clearing until after transaction commits
|
|
|
|
|
DB::afterCommit(function () {
|
|
|
|
|
app(PermissionRegistrar::class)->forgetCachedPermissions();
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-16 03:25:06 +09:00
|
|
|
}
|