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

48 lines
2.8 KiB
PHP

<?php
use App\Models\User;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
// Existing synthetic QA provisioning only. Never change MFA or display QR bytes in tool output.
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();
portalQaAssertTarget($target);
$connection = DB::connection();
$connection->statement('BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY');
try {
$account = (int) ($argv[1] ?? 18);
abort_unless(in_array($account, [18, 21], true), 403);
$name = $account === 18 ? 'investor-mfa-qa' : 'promoter-qa21';
$local = json_decode(file_get_contents(storage_path('app/private/investmoz-v2/portal-audit/'.($account === 18 ? 'investor-mfa-qa-private.json' : 'profiles-v1-actors-private.json'))), true, 512, JSON_THROW_ON_ERROR);
if ($account === 21) {
$local = $local['promoter'];
}
$actor = User::findOrFail($account);
abort_unless($actor->email === $local['email'] && str_ends_with($actor->email, '@example.invalid') && $actor->two_factor_confirmed_at, 403);
abort_unless(hash_equals(app('encrypter')->decrypt($actor->two_factor_secret), $local['totp_secret'])
&& Hash::check($local['password'], $actor->password), 409);
$label = 'QA'.$account;
$email = htmlspecialchars($actor->email, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
$svg = $actor->twoFactorQrCodeSvg();
$file = storage_path('app/private/investmoz-v2/portal-audit/'.$name.'-2fas-local.html');
$html = '<!doctype html><html lang="pt"><meta charset="utf-8"><title>'.$label.' — configuração local 2FAS</title>'
.'<style>body{font:18px system-ui;max-width:650px;margin:32px auto;padding:16px}svg{width:300px;height:300px}</style>'
.'<h1>Conta '.$label.' no 2FAS Auth</h1><p>'.$email.' · servidor QA 127.0.0.1:18097</p>'
.'<p>Este QR recupera a configuração MFA existente. Não altera a conta, o segredo nem a base ativa.</p>'
.$svg.'<p>No 2FAS: adicionar serviço → ler este QR → identificar a entrada como InvestMoz '.$label.'.</p>'
.'<p>Ative a data e hora automáticas do telefone. Use o código desta entrada em /two-factor-challenge.</p>'
.'<p>Ficheiro privado: não o anexe, fotografe ou partilhe nesta conversa. Não remova as entradas antigas do portal.</p></html>';
file_put_contents($file, $html);
chmod($file, 0600);
unset($actor, $svg, $html, $local);
} finally {
$connection->statement('ROLLBACK');
}
echo json_encode(['prepared' => true, 'local_file' => $file, 'account_id' => $account, 'target' => $target,
'mfa_changed' => false, 'database_writes' => 0, 'active_writes' => 0, 'qr_or_secret_exported' => false], JSON_THROW_ON_ERROR);