feat: 增强玩家管理功能,集成接入站点权限控制
在多个玩家相关控制器中引入 AdminSiteScope,确保管理员在执行操作前具备相应的接入站点权限。更新 Player 相关请求以支持 site_code 参数,增强权限验证逻辑,确保系统安全性与灵活性。同时,新增 AdminUser 模型方法以获取可访问的站点 ID 列表,优化权限管理。
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use App\Support\AdminAuthorizationRegistry;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('admin_sites', function (Blueprint $table): void {
|
||||
$table->string('wallet_api_url', 512)->nullable()->after('extra_json');
|
||||
$table->string('wallet_debit_path', 128)->default('/wallet/debit-for-lottery')->after('wallet_api_url');
|
||||
$table->string('wallet_credit_path', 128)->default('/wallet/credit-from-lottery')->after('wallet_debit_path');
|
||||
$table->string('wallet_balance_path', 128)->default('/wallet/balance')->after('wallet_credit_path');
|
||||
$table->text('wallet_api_key_encrypted')->nullable()->after('wallet_balance_path');
|
||||
$table->text('sso_jwt_secret_encrypted')->nullable()->after('wallet_api_key_encrypted');
|
||||
$table->unsignedSmallInteger('wallet_timeout_seconds')->default(10)->after('sso_jwt_secret_encrypted');
|
||||
$table->json('iframe_allowed_origins')->nullable()->after('wallet_timeout_seconds');
|
||||
$table->string('lottery_h5_base_url', 512)->nullable()->after('iframe_allowed_origins');
|
||||
$table->text('notes')->nullable()->after('lottery_h5_base_url');
|
||||
});
|
||||
|
||||
$this->seedIntegrationMenuActions();
|
||||
$this->backfillDefaultSiteFromEnv();
|
||||
$this->syncIntegrationApiResources();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$resourceIds = DB::table('admin_api_resources')
|
||||
->where('code', 'like', 'admin.integration-sites.%')
|
||||
->pluck('id')
|
||||
->all();
|
||||
|
||||
if ($resourceIds !== []) {
|
||||
DB::table('admin_role_api_resources')->whereIn('api_resource_id', $resourceIds)->delete();
|
||||
DB::table('admin_api_resource_bindings')->whereIn('api_resource_id', $resourceIds)->delete();
|
||||
DB::table('admin_api_resources')->whereIn('id', $resourceIds)->delete();
|
||||
}
|
||||
|
||||
Schema::table('admin_sites', function (Blueprint $table): void {
|
||||
$table->dropColumn([
|
||||
'wallet_api_url',
|
||||
'wallet_debit_path',
|
||||
'wallet_credit_path',
|
||||
'wallet_balance_path',
|
||||
'wallet_api_key_encrypted',
|
||||
'sso_jwt_secret_encrypted',
|
||||
'wallet_timeout_seconds',
|
||||
'iframe_allowed_origins',
|
||||
'lottery_h5_base_url',
|
||||
'notes',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
private function seedIntegrationMenuActions(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$viewActionId = DB::table('admin_action_catalog')->where('code', 'view')->value('id');
|
||||
$manageActionId = DB::table('admin_action_catalog')->where('code', 'manage')->value('id');
|
||||
if ($viewActionId === null || $manageActionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$configMenuId = DB::table('admin_menus')->where('code', 'config')->value('id');
|
||||
if ($configMenuId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$integrationMenuId = DB::table('admin_menus')->where('code', 'config.integration')->value('id');
|
||||
if ($integrationMenuId === null) {
|
||||
$integrationMenuId = DB::table('admin_menus')->insertGetId([
|
||||
'parent_id' => (int) $configMenuId,
|
||||
'menu_type' => 'page',
|
||||
'code' => 'config.integration',
|
||||
'name' => '主站接入站点',
|
||||
'path' => '/admin/config/integration-sites',
|
||||
'route_name' => 'admin.config.integration',
|
||||
'component' => 'config/integration',
|
||||
'icon' => null,
|
||||
'active_menu_code' => null,
|
||||
'sort_order' => 45,
|
||||
'is_visible' => true,
|
||||
'is_cache' => false,
|
||||
'is_external' => false,
|
||||
'status' => 1,
|
||||
'meta_json' => null,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ([
|
||||
['permission_code' => 'integration.site.view', 'action_id' => (int) $viewActionId, 'name' => '接入站点查看'],
|
||||
['permission_code' => 'integration.site.manage', 'action_id' => (int) $manageActionId, 'name' => '接入站点管理'],
|
||||
] as $row) {
|
||||
$exists = DB::table('admin_menu_actions')
|
||||
->where('permission_code', $row['permission_code'])
|
||||
->exists();
|
||||
if ($exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_menu_actions')->insert([
|
||||
'menu_id' => (int) $integrationMenuId,
|
||||
'action_id' => $row['action_id'],
|
||||
'permission_code' => $row['permission_code'],
|
||||
'name' => $row['name'],
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function backfillDefaultSiteFromEnv(): void
|
||||
{
|
||||
$siteId = DB::table('admin_sites')->where('is_default', true)->value('id')
|
||||
?? DB::table('admin_sites')->orderBy('id')->value('id');
|
||||
|
||||
if ($siteId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$walletUrl = env('MAIN_SITE_WALLET_API_URL');
|
||||
$ssoSecret = env('MAIN_SITE_SSO_JWT_SECRET');
|
||||
$walletKey = env('MAIN_SITE_WALLET_API_KEY');
|
||||
|
||||
$payload = [
|
||||
'updated_at' => Carbon::now(),
|
||||
];
|
||||
|
||||
if (is_string($walletUrl) && trim($walletUrl) !== '') {
|
||||
$payload['wallet_api_url'] = rtrim(trim($walletUrl), '/');
|
||||
}
|
||||
|
||||
$debitPath = env('MAIN_SITE_WALLET_DEBIT_PATH');
|
||||
if (is_string($debitPath) && $debitPath !== '') {
|
||||
$payload['wallet_debit_path'] = $debitPath;
|
||||
}
|
||||
|
||||
$creditPath = env('MAIN_SITE_WALLET_CREDIT_PATH');
|
||||
if (is_string($creditPath) && $creditPath !== '') {
|
||||
$payload['wallet_credit_path'] = $creditPath;
|
||||
}
|
||||
|
||||
$balancePath = env('MAIN_SITE_WALLET_BALANCE_PATH');
|
||||
if (is_string($balancePath) && $balancePath !== '') {
|
||||
$payload['wallet_balance_path'] = $balancePath;
|
||||
}
|
||||
|
||||
$timeout = env('MAIN_SITE_WALLET_TIMEOUT');
|
||||
if (is_numeric($timeout)) {
|
||||
$payload['wallet_timeout_seconds'] = max(1, (int) $timeout);
|
||||
}
|
||||
|
||||
if (is_string($ssoSecret) && $ssoSecret !== '') {
|
||||
$payload['sso_jwt_secret_encrypted'] = encrypt($ssoSecret);
|
||||
}
|
||||
|
||||
if (is_string($walletKey) && $walletKey !== '') {
|
||||
$payload['wallet_api_key_encrypted'] = encrypt($walletKey);
|
||||
}
|
||||
|
||||
if (count($payload) > 1) {
|
||||
DB::table('admin_sites')->where('id', (int) $siteId)->update($payload);
|
||||
}
|
||||
}
|
||||
|
||||
private function syncIntegrationApiResources(): void
|
||||
{
|
||||
if (! Schema::hasTable('admin_api_resources')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$now = Carbon::now();
|
||||
$menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
|
||||
|
||||
$resources = array_values(array_filter(
|
||||
AdminAuthorizationRegistry::resources(),
|
||||
static fn (array $resource): bool => str_starts_with((string) $resource['code'], 'admin.integration-sites.'),
|
||||
));
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
$resourceId = DB::table('admin_api_resources')
|
||||
->where('code', $resource['code'])
|
||||
->value('id');
|
||||
|
||||
$payload = [
|
||||
'module_code' => $resource['module_code'],
|
||||
'name' => $resource['name'],
|
||||
'http_method' => $resource['http_method'],
|
||||
'uri_pattern' => $resource['uri_pattern'],
|
||||
'route_name' => $resource['route_name'],
|
||||
'auth_mode' => $resource['auth_mode'],
|
||||
'is_audit_required' => $resource['is_audit_required'],
|
||||
'status' => 1,
|
||||
'meta_json' => null,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
if ($resourceId === null) {
|
||||
$resourceId = DB::table('admin_api_resources')->insertGetId($payload + [
|
||||
'code' => $resource['code'],
|
||||
'created_at' => $now,
|
||||
]);
|
||||
} else {
|
||||
DB::table('admin_api_resources')
|
||||
->where('id', (int) $resourceId)
|
||||
->update($payload);
|
||||
}
|
||||
|
||||
DB::table('admin_api_resource_bindings')
|
||||
->where('api_resource_id', (int) $resourceId)
|
||||
->delete();
|
||||
|
||||
foreach ($resource['permission_codes'] as $permissionCode) {
|
||||
$menuActionId = $menuActionIds[$permissionCode] ?? null;
|
||||
if ($menuActionId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_api_resource_bindings')->insert([
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
'menu_action_id' => (int) $menuActionId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Support\AdminAuthorizationRegistry;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
/**
|
||||
* 为已执行 140000 的环境补种 integration 权限动作并同步 API 绑定。
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$viewActionId = DB::table('admin_action_catalog')->where('code', 'view')->value('id');
|
||||
$manageActionId = DB::table('admin_action_catalog')->where('code', 'manage')->value('id');
|
||||
if ($viewActionId === null || $manageActionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$configMenuId = DB::table('admin_menus')->where('code', 'config')->value('id');
|
||||
if ($configMenuId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$integrationMenuId = DB::table('admin_menus')->where('code', 'config.integration')->value('id');
|
||||
if ($integrationMenuId === null) {
|
||||
$integrationMenuId = DB::table('admin_menus')->insertGetId([
|
||||
'parent_id' => (int) $configMenuId,
|
||||
'menu_type' => 'page',
|
||||
'code' => 'config.integration',
|
||||
'name' => '主站接入站点',
|
||||
'path' => '/admin/config/integration-sites',
|
||||
'route_name' => 'admin.config.integration',
|
||||
'component' => 'config/integration',
|
||||
'icon' => null,
|
||||
'active_menu_code' => null,
|
||||
'sort_order' => 45,
|
||||
'is_visible' => true,
|
||||
'is_cache' => false,
|
||||
'is_external' => false,
|
||||
'status' => 1,
|
||||
'meta_json' => null,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ([
|
||||
['permission_code' => 'integration.site.view', 'action_id' => (int) $viewActionId, 'name' => '接入站点查看'],
|
||||
['permission_code' => 'integration.site.manage', 'action_id' => (int) $manageActionId, 'name' => '接入站点管理'],
|
||||
] as $row) {
|
||||
if (DB::table('admin_menu_actions')->where('permission_code', $row['permission_code'])->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_menu_actions')->insert([
|
||||
'menu_id' => (int) $integrationMenuId,
|
||||
'action_id' => $row['action_id'],
|
||||
'permission_code' => $row['permission_code'],
|
||||
'name' => $row['name'],
|
||||
'status' => 1,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
$menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
|
||||
$resources = array_values(array_filter(
|
||||
AdminAuthorizationRegistry::resources(),
|
||||
static fn (array $resource): bool => str_starts_with((string) $resource['code'], 'admin.integration-sites.'),
|
||||
));
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
$resourceId = DB::table('admin_api_resources')->where('code', $resource['code'])->value('id');
|
||||
if ($resourceId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_api_resource_bindings')
|
||||
->where('api_resource_id', (int) $resourceId)
|
||||
->delete();
|
||||
|
||||
foreach ($resource['permission_codes'] as $permissionCode) {
|
||||
$menuActionId = $menuActionIds[$permissionCode] ?? null;
|
||||
if ($menuActionId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('admin_api_resource_bindings')->insert([
|
||||
'api_resource_id' => (int) $resourceId,
|
||||
'menu_action_id' => (int) $menuActionId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// 保留 menu_actions / bindings,避免回滚后超管无法管理已创建的接入站点。
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user