Files
lotteryLaravel/app/Console/Commands/CheckAdminPermissionLanguageCommand.php
kang a60ce8caad refactor: 优化 DrawHallSnapshotBuilder 和权限管理逻辑
- 在 DrawHallSnapshotBuilder 中简化数据获取逻辑,仅保留必要字段,更新状态表示方式。
- 在 AdminAuthorizationRegistry 中整合接入站点权限定义,提升权限管理的灵活性与可维护性。
- 更新调度任务配置,确保任务在单一服务器上运行,避免重叠执行,提高系统稳定性。
- 增强测试用例,确保新逻辑的正确性与稳定性。
2026-05-27 16:51:08 +08:00

164 lines
6.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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;
}
}