load(); \support\App::loadAllConfig(['route']); use app\miniapi\model\MiniGrant; use app\miniapi\service\Access; $apply = in_array('--apply', $argv, true); $active = MiniGrant::query()->where('status', 1)->orderBy('user_id')->orderBy('id')->get(); $live = []; $stale = []; foreach ($active as $grant) { $model = Access::resourceModel($grant->role); $resource = $model === null ? null : $model::query()->where('id', $grant->resource_id)->where('status', 1)->first(); if ($resource === null) { $stale[] = $grant; continue; } $live[(int) $grant->user_id][] = $grant; } $conflicts = array_filter($live, static fn (array $rows): bool => count($rows) > 1); printf("生效授权 %d 条,其中指向已删除或已停用档案的 %d 条(Access 不计入,不影响登录)。\n", $active->count(), count($stale)); printf("身份冲突账号 %d 个。\n", count($conflicts)); foreach ($conflicts as $userId => $rows) { printf(" user_id=%d 生效身份 %d 个:", $userId, count($rows)); foreach ($rows as $grant) { printf('grant#%d %s/%d ', $grant->id, $grant->role, $grant->resource_id); } printf("(保留最新 grant#%d)\n", end($rows)->id); } if (!$conflicts) { echo "无需处理。\n"; exit; } if (!$apply) { echo "计划:如需停用多余身份,执行 php scripts/audit_mini_identity_conflict.php --apply\n"; exit; } $disabled = []; (new MiniGrant())->getConnection()->transaction(function () use ($conflicts, &$disabled): void { foreach ($conflicts as $userId => $rows) { $keep = end($rows); foreach ($rows as $grant) { if ((int) $grant->id === (int) $keep->id) { continue; } MiniGrant::query()->where('id', $grant->id)->update([ 'status' => 0, 'updated_at' => date('Y-m-d H:i:s'), ]); $disabled[] = [ 'grant_id' => (int) $grant->id, 'role' => $grant->role, 'resource_id' => (int) $grant->resource_id, 'kept_grant_id' => (int) $keep->id, ]; } } }); printf("已停用 %d 条多余授权。受影响的账号可重新登录;如判断有误,将下列授权的 status 改回 1 即可恢复。\n", count($disabled)); echo json_encode($disabled, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . PHP_EOL;