- 在 DrawHallSnapshotBuilder 中简化数据获取逻辑,仅保留必要字段,更新状态表示方式。 - 在 AdminAuthorizationRegistry 中整合接入站点权限定义,提升权限管理的灵活性与可维护性。 - 更新调度任务配置,确保任务在单一服务器上运行,避免重叠执行,提高系统稳定性。 - 增强测试用例,确保新逻辑的正确性与稳定性。
164 lines
6.8 KiB
PHP
164 lines
6.8 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Support\AdminAuthorizationRegistry;
|
||
use App\Support\AdminPermissionLanguage;
|
||
use Illuminate\Console\Command;
|
||
|
||
final class CheckAdminPermissionLanguageCommand extends Command
|
||
{
|
||
protected $signature = 'lottery:admin-permission-language-check
|
||
{--page=integration-sites : 页面 key(当前只验证 integration-sites 示例映射)}';
|
||
|
||
protected $description = '检查“权限语言映射”与后端 Registry / API 资源绑定的一致性';
|
||
|
||
public function handle(): int
|
||
{
|
||
$pageKey = (string) $this->option('page');
|
||
if ($pageKey === '') {
|
||
$this->error('Missing --page');
|
||
return self::FAILURE;
|
||
}
|
||
|
||
$issues = [];
|
||
|
||
$requiredPrdSlugs = AdminPermissionLanguage::requiredAnyPrdSlugs($pageKey);
|
||
if ($requiredPrdSlugs === []) {
|
||
$issues[] = [
|
||
'type' => 'config',
|
||
'message' => sprintf('No required prd slugs found for page `%s`.', $pageKey),
|
||
];
|
||
}
|
||
|
||
$permissionDefinitions = AdminAuthorizationRegistry::permissionDefinitions();
|
||
|
||
/** @var array<string, array{slug: string, permission_codes: list<string>}> $bySlug */
|
||
$bySlug = [];
|
||
foreach ($permissionDefinitions as $def) {
|
||
$slug = $def['slug'] ?? '';
|
||
if (! is_string($slug) || $slug === '') {
|
||
continue;
|
||
}
|
||
$bySlug[$slug] = $def;
|
||
}
|
||
|
||
foreach (AdminPermissionLanguage::requiredBundleKeys($pageKey) as $bundleKey) {
|
||
$expectedSlug = AdminPermissionLanguage::prdSlug($pageKey, $bundleKey);
|
||
$expectedCodes = AdminPermissionLanguage::permissionCodes($pageKey, $bundleKey);
|
||
|
||
if (! isset($bySlug[$expectedSlug])) {
|
||
$issues[] = [
|
||
'type' => 'prd_slug',
|
||
'message' => sprintf('PRD slug `%s` for bundle `%s` not found in AdminAuthorizationRegistry::permissionDefinitions().', $expectedSlug, $bundleKey),
|
||
];
|
||
continue;
|
||
}
|
||
|
||
$actualCodes = $bySlug[$expectedSlug]['permission_codes'] ?? [];
|
||
$actualSet = array_fill_keys(is_array($actualCodes) ? $actualCodes : [], true);
|
||
$expectedSet = array_fill_keys($expectedCodes, true);
|
||
|
||
$missing = array_values(array_diff(array_keys($expectedSet), array_keys($actualSet)));
|
||
if ($missing !== []) {
|
||
$issues[] = [
|
||
'type' => 'prd_action_codes',
|
||
'message' => sprintf(
|
||
'PRD slug `%s` (bundle `%s`) missing action codes: %s',
|
||
$expectedSlug,
|
||
$bundleKey,
|
||
implode(', ', $missing),
|
||
),
|
||
];
|
||
}
|
||
}
|
||
|
||
// Sidebar / “页面可进”入口:integration-sites 对应 nav_segment=integration
|
||
foreach (AdminAuthorizationRegistry::navigationDefinitions() as $nav) {
|
||
if (($nav['segment'] ?? '') !== 'integration') {
|
||
continue;
|
||
}
|
||
|
||
$requiredAny = $nav['requiredAny'] ?? [];
|
||
if (! is_array($requiredAny)) {
|
||
$requiredAny = [];
|
||
}
|
||
|
||
foreach ($requiredPrdSlugs as $requiredSlug) {
|
||
if (! in_array($requiredSlug, $requiredAny, true)) {
|
||
$issues[] = [
|
||
'type' => 'navigation_requiredAny',
|
||
'message' => sprintf('Navigation segment `integration` missing requiredAny slug `%s`.', $requiredSlug),
|
||
];
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
// API 资源:检查 integration-sites 的路由资源 binding 至少包含对应 action code。
|
||
$resources = AdminAuthorizationRegistry::resources();
|
||
/** @var array<string, array{permission_codes: list<string>}> $resourceByCode */
|
||
$resourceByCode = [];
|
||
foreach ($resources as $resource) {
|
||
$code = $resource['code'] ?? '';
|
||
if (! is_string($code) || $code === '') {
|
||
continue;
|
||
}
|
||
$resourceByCode[$code] = $resource;
|
||
}
|
||
|
||
$viewActionCodes = AdminPermissionLanguage::permissionCodes($pageKey, 'view');
|
||
$manageActionCodes = AdminPermissionLanguage::permissionCodes($pageKey, 'manage');
|
||
|
||
$endpointChecks = [
|
||
// view
|
||
'admin.integration-sites.index' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
|
||
'admin.integration-sites.show' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
|
||
'admin.integration-sites.connectivity-test' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
|
||
'admin.integration-sites.export' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
|
||
|
||
// manage
|
||
'admin.integration-sites.store' => ['expected_permission_codes' => $manageActionCodes, 'expected_bundle' => 'manage'],
|
||
'admin.integration-sites.update' => ['expected_permission_codes' => $manageActionCodes, 'expected_bundle' => 'manage'],
|
||
'admin.integration-sites.rotate-secrets' => ['expected_permission_codes' => $manageActionCodes, 'expected_bundle' => 'manage'],
|
||
];
|
||
|
||
foreach ($endpointChecks as $resourceCode => $check) {
|
||
if (! isset($resourceByCode[$resourceCode])) {
|
||
$issues[] = [
|
||
'type' => 'resource_definitions',
|
||
'message' => sprintf('API resource `%s` not found in AdminAuthorizationRegistry::resources().', $resourceCode),
|
||
];
|
||
continue;
|
||
}
|
||
|
||
$expectedCodes = $check['expected_permission_codes'] ?? [];
|
||
$resourcePermissionCodes = $resourceByCode[$resourceCode]['permission_codes'] ?? [];
|
||
|
||
$resourceSet = array_fill_keys(is_array($resourcePermissionCodes) ? $resourcePermissionCodes : [], true);
|
||
foreach ($expectedCodes as $expectedCode) {
|
||
if (! isset($resourceSet[$expectedCode])) {
|
||
$issues[] = [
|
||
'type' => 'api_resource_action_codes',
|
||
'message' => sprintf('API resource `%s` missing action code `%s`.', $resourceCode, $expectedCode),
|
||
];
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($issues === []) {
|
||
$this->info('Admin permission language check passed.');
|
||
return self::SUCCESS;
|
||
}
|
||
|
||
$this->error(sprintf('Admin permission language check found %d issue(s).', count($issues)));
|
||
foreach ($issues as $issue) {
|
||
$this->line(sprintf('- [%s] %s', $issue['type'], $issue['message']));
|
||
}
|
||
|
||
return self::FAILURE;
|
||
}
|
||
}
|
||
|