Files
Investidor-V2/tests/Feature/Auth/QaAccountSelectionTest.php
T
nala 6ddafc95ba
tests / ci (push) Canceled after 0s
oportunidades 4
2026-10-10 07:03:59 +02:00

89 lines
4.1 KiB
PHP

<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Encryption\Encrypter;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Session\Middleware\StartSession;
use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
use Laravel\Fortify\Fortify;
use PragmaRX\Google2FA\Google2FA;
use Tests\TestCase;
class QaAccountSelectionTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
require_once base_path('tools/portal-qa-account-selection.php');
config(['portal.qa_synthetic_accounts_only' => true]);
$kernel = app(Kernel::class);
$kernel->appendMiddlewareToGroup('web', \PortalQaAccountSelection::class);
$kernel->addToMiddlewarePriorityAfter(StartSession::class, \PortalQaAccountSelection::class);
}
private function restored(): User
{
$user = User::factory()->create(['email' => 'restored-source@source.invalid']);
$user->forceFill(['two_factor_secret' => (new Encrypter(random_bytes(32), 'AES-256-CBC'))->encrypt('SYNTHETICONLY'),
'two_factor_confirmed_at' => now()])->save();
return $user;
}
public function test_restored_account_is_stopped_before_mfa_without_changing_its_row(): void
{
$user = $this->restored();
$original = hash('sha256', json_encode($user->fresh()->getRawOriginal(), JSON_THROW_ON_ERROR));
$this->post('/login', ['email' => $user->email, 'password' => 'password'])
->assertRedirect('/login')->assertSessionHasErrors('email')->assertSessionMissing('login.id');
$this->assertGuest();
$this->assertSame($original, hash('sha256', json_encode($user->fresh()->getRawOriginal(), JSON_THROW_ON_ERROR)));
}
public function test_json_restored_login_and_stale_challenge_remain_unauthenticated(): void
{
$user = $this->restored();
$this->postJson('/login', ['email' => $user->email, 'password' => 'password'])
->assertUnprocessable()->assertJsonValidationErrors('email')->assertSessionMissing('login.id');
$this->withSession(['login.id' => $user->id])->get('/two-factor-challenge')
->assertRedirect('/login')->assertSessionHasErrors('email')->assertSessionMissing('login.id');
$this->assertGuest();
}
public function test_synthetic_login_requires_valid_mfa_then_recovers_after_logout(): void
{
$user = User::factory()->create(['email' => 'synthetic-investor@example.invalid']);
app(EnableTwoFactorAuthentication::class)($user);
$user->forceFill(['two_factor_confirmed_at' => now()])->save();
$secret = Fortify::currentEncrypter()->decrypt($user->two_factor_secret);
$credentials = ['email' => $user->email, 'password' => 'password'];
$this->post('/login', $credentials)->assertRedirect('/two-factor-challenge');
$this->assertGuest();
$this->post('/two-factor-challenge', ['code' => 'invalid'])->assertRedirect('/two-factor-challenge');
$this->assertGuest();
$engine = new Google2FA;
$this->post('/two-factor-challenge', ['code' => $engine->getCurrentOtp($secret)])->assertRedirect('/dashboard');
$this->assertAuthenticatedAs($user);
$this->get('/dashboard')->assertOk();
$this->post('/logout')->assertRedirect('/');
$this->assertGuest();
$this->post('/login', $credentials)->assertRedirect('/two-factor-challenge');
// A new login uses a fresh code in Fortify's normal accepted window, not the consumed code.
$this->post('/two-factor-challenge', ['code' => $engine->oathTotp($secret, $engine->getTimestamp() + 1)])->assertRedirect('/dashboard');
$this->assertAuthenticatedAs($user);
}
public function test_qa_account_policy_does_not_apply_when_flag_is_absent(): void
{
config(['portal.qa_synthetic_accounts_only' => false]);
$user = User::factory()->create(['email' => 'ordinary-user@source.invalid']);
$this->post('/login', ['email' => $user->email, 'password' => 'password'])->assertRedirect('/dashboard');
$this->assertAuthenticatedAs($user);
}
}