feat: refactor super admin to use is_super_admin flag and enhance site deletion logic
- Changed super admin detection from role-based to `is_super_admin` flag in AdminUser model
- Added `requireDefaultAdminSiteId()` method to throw validation error when no integration site exists
- Enhanced site deletion to migrate platform role bindings to fallback site and auto-delete site-specific admin accounts
- Made agent line code optional with auto-generation fallback using `{site_code}-agent-{counter}` format
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('admin_users', function (Blueprint $table): void {
|
||||
$table->boolean('is_super_admin')->default(false)->after('status');
|
||||
});
|
||||
|
||||
$superRoleId = DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
|
||||
if ($superRoleId !== null) {
|
||||
$superUserIds = DB::table('admin_user_site_roles')
|
||||
->where('role_id', $superRoleId)
|
||||
->distinct()
|
||||
->pluck('admin_user_id');
|
||||
|
||||
foreach ($superUserIds as $userId) {
|
||||
DB::table('admin_users')
|
||||
->where('id', $userId)
|
||||
->update(['is_super_admin' => true]);
|
||||
}
|
||||
|
||||
DB::table('admin_user_site_roles')
|
||||
->where('role_id', $superRoleId)
|
||||
->delete();
|
||||
}
|
||||
|
||||
// 仅允许一名超管:若历史数据误绑多名,保留最小 id。
|
||||
$superAdminIds = DB::table('admin_users')
|
||||
->where('is_super_admin', true)
|
||||
->orderBy('id')
|
||||
->pluck('id');
|
||||
|
||||
if ($superAdminIds->count() > 1) {
|
||||
$keepId = (int) $superAdminIds->first();
|
||||
DB::table('admin_users')
|
||||
->where('is_super_admin', true)
|
||||
->where('id', '!=', $keepId)
|
||||
->update(['is_super_admin' => false]);
|
||||
}
|
||||
|
||||
$driver = Schema::getConnection()->getDriverName();
|
||||
if ($driver === 'pgsql') {
|
||||
DB::statement('CREATE UNIQUE INDEX admin_users_single_super_admin ON admin_users (is_super_admin) WHERE is_super_admin = true');
|
||||
} elseif ($driver === 'sqlite') {
|
||||
DB::statement('CREATE UNIQUE INDEX admin_users_single_super_admin ON admin_users (is_super_admin) WHERE is_super_admin = 1');
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$driver = Schema::getConnection()->getDriverName();
|
||||
if (in_array($driver, ['pgsql', 'sqlite'], true)) {
|
||||
DB::statement('DROP INDEX IF EXISTS admin_users_single_super_admin');
|
||||
}
|
||||
|
||||
Schema::table('admin_users', function (Blueprint $table): void {
|
||||
$table->dropColumn('is_super_admin');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use App\Models\AdminRole;
|
||||
use App\Support\SiteAdminDefaultRolePermissions;
|
||||
use App\Support\SitePlatformRole;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
SiteAdminDefaultRolePermissions::ensurePlatformSiteAdminRole();
|
||||
$platformRoleId = SitePlatformRole::id();
|
||||
|
||||
$legacyRoles = AdminRole::query()
|
||||
->where('scope_type', AdminRole::SCOPE_SYSTEM)
|
||||
->where('slug', 'like', 'site_admin_%')
|
||||
->where('slug', '<>', SitePlatformRole::SLUG)
|
||||
->get(['id', 'slug']);
|
||||
|
||||
foreach ($legacyRoles as $legacy) {
|
||||
$bindings = DB::table('admin_user_site_roles')
|
||||
->where('role_id', $legacy->id)
|
||||
->get(['admin_user_id', 'site_id', 'granted_at']);
|
||||
|
||||
foreach ($bindings as $binding) {
|
||||
DB::table('admin_user_site_roles')->updateOrInsert(
|
||||
[
|
||||
'admin_user_id' => (int) $binding->admin_user_id,
|
||||
'site_id' => (int) $binding->site_id,
|
||||
'role_id' => $platformRoleId,
|
||||
],
|
||||
['granted_at' => $binding->granted_at ?? now()],
|
||||
);
|
||||
}
|
||||
|
||||
DB::table('admin_user_site_roles')->where('role_id', $legacy->id)->delete();
|
||||
AdminRole::query()->where('id', $legacy->id)->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// 不回滚 per-site 角色拆分;仅保留平台 site_admin 角色。
|
||||
}
|
||||
};
|
||||
@@ -7,6 +7,7 @@ use Illuminate\Database\Seeder;
|
||||
use App\Support\AdminAgentPermissionMenuActionSync;
|
||||
use App\Support\AdminDrawPermissionMenuActionSync;
|
||||
use App\Support\PlatformSystemRoles;
|
||||
use App\Support\SuperAdminAccount;
|
||||
|
||||
/**
|
||||
* 后台 RBAC:平台固定角色 super_admin / agent。
|
||||
@@ -22,8 +23,6 @@ final class AdminRbacAndUserSeeder extends Seeder
|
||||
|
||||
PlatformSystemRoles::ensureAll();
|
||||
|
||||
$super = PlatformSystemRoles::ensureSuperAdminRole();
|
||||
|
||||
$username = 'admin';
|
||||
AdminUser::query()->updateOrCreate(
|
||||
['username' => $username],
|
||||
@@ -37,13 +36,6 @@ final class AdminRbacAndUserSeeder extends Seeder
|
||||
|
||||
/** @var AdminUser $admin */
|
||||
$admin = AdminUser::query()->where('username', $username)->firstOrFail();
|
||||
$siteId = AdminUser::defaultAdminSiteId();
|
||||
$superId = (int) $super->getKey();
|
||||
$admin->roles()->sync([
|
||||
$superId => [
|
||||
'site_id' => $siteId,
|
||||
'granted_at' => now(),
|
||||
],
|
||||
]);
|
||||
SuperAdminAccount::assign($admin);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user