Files
Investidor-V2/tools/portal-consumer-revoke-browser-session-qa.php
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

56 lines
3.0 KiB
PHP

<?php
use App\Models\User;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
// Revoke only synthetic QA21 sessions from this failed browser batch.
require dirname(__DIR__).'/vendor/autoload.php';
require __DIR__.'/portal-qa-environment.php';
$target = portalQaEnvironment();
$app = require dirname(__DIR__).'/bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
$identity = portalQaAssertTarget($target);
$actor = User::findOrFail(21);
throw_unless(str_ends_with($actor->email, '@example.invalid'), RuntimeException::class, 'Only synthetic QA actor');
$count = DB::table('sessions')->where('user_id', 21)->where('last_activity', '>=', strtotime('2026-10-10 20:15:00 UTC'))->delete();
$qaSessionRoot = realpath(storage_path('app/private/investmoz-v2/qa-opportunity-resources-sessions'));
throw_unless($qaSessionRoot && str_starts_with($qaSessionRoot, realpath(storage_path('app/private/investmoz-v2'))), RuntimeException::class, 'QA session directory outside allowed target');
$cutoff = 0;
foreach (glob(storage_path('app/private/investmoz-v2/portal-audit/consumer-workflow-chromium-20261010-attempt-*.json')) as $receipt) {
$r = json_decode(file_get_contents($receipt), true);
if (($r['result'] ?? null) === 'failed') {
$cutoff = max($cutoff, strtotime($r['finished_at'] ?? '1970-01-01'));
}
}
throw_unless($cutoff > 0, RuntimeException::class, 'Failed browser batch cutoff required');
$filesRevoked = 0;
foreach (glob($qaSessionRoot.DIRECTORY_SEPARATOR.'*') as $file) {
if (! is_file($file) || filemtime($file) < strtotime('2026-10-10 20:15:00 UTC') || filemtime($file) > $cutoff) {
continue;
}
$raw = file_get_contents($file);
$data = json_decode($raw, true) ?? @unserialize($raw, ['allowed_classes' => false]);
if (! is_array($data)) {
try {
$raw = Crypt::decrypt($raw);
$data = json_decode($raw, true) ?? @unserialize($raw, ['allowed_classes' => false]);
} catch (Throwable) {
continue;
}
}
if (! is_array($data)) {
continue;
}
foreach ($data as $key => $value) {
if (str_starts_with((string) $key, 'login_web_') && (int) $value === 21) {
throw_unless(unlink($file), RuntimeException::class, 'Could not revoke synthetic QA session');
$filesRevoked++;
break;
}
}
}
file_put_contents(storage_path('app/private/investmoz-v2/portal-audit/consumer-browser-session-revocation-qa.json'), json_encode(['at' => gmdate('c'), 'target' => $identity, 'actor_id' => 21, 'revoked_database_sessions' => $count, 'revoked_file_sessions' => $filesRevoked, 'failed_batch_cutoff_utc' => gmdate('c', $cutoff), 'scope' => 'synthetic QA21 failed batch since20:15UTC; later sessions excluded', 'mfa_changed' => false, 'active_writes' => 0], JSON_PRETTY_PRINT));
echo json_encode(['actor_id' => 21, 'revoked_database_sessions' => $count, 'revoked_file_sessions' => $filesRevoked, 'target' => $identity, 'active_writes' => 0]).PHP_EOL;