clusev/tests/Feature/Settings/LoginProtectionTabTest.php

105 lines
3.9 KiB
PHP

<?php
namespace Tests\Feature\Settings;
use App\Livewire\Settings\LoginProtection;
use App\Models\BannedIp;
use App\Models\Setting;
use App\Models\User;
use App\Support\Confirm\ConfirmToken;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Livewire\Livewire;
use Tests\TestCase;
class LoginProtectionTabTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
Cache::flush();
}
public function test_saving_persists_cast_settings(): void
{
$user = User::factory()->create();
Livewire::actingAs($user)->test(LoginProtection::class)
->set('enabled', false)->set('maxretry', 7)->set('findtime', 15)->set('bantime', 120)
->set('whitelist', '203.0.113.0/24')
->call('save');
$this->assertSame('0', Setting::get('bruteforce_enabled'));
$this->assertSame('7', Setting::get('bruteforce_maxretry'));
$this->assertSame('203.0.113.0/24', Setting::get('bruteforce_whitelist'));
}
public function test_invalid_whitelist_is_rejected(): void
{
$user = User::factory()->create();
Livewire::actingAs($user)->test(LoginProtection::class)
->set('whitelist', 'junk-not-a-cidr')->call('save')
->assertHasErrors('whitelist');
$this->assertNull(Setting::get('bruteforce_maxretry'));
}
public function test_table_lists_active_bans_and_unban_removes_one(): void
{
$user = User::factory()->create();
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->addHour(), 'attempts' => 10]);
// Must authenticate before issuing so the token's uid matches Auth::id() at consume time.
$this->actingAs($user);
$token = ConfirmToken::issue('banCleared', ['ip' => '203.0.113.5']);
ConfirmToken::confirm($token);
Livewire::actingAs($user)->test(LoginProtection::class)
->assertSee('203.0.113.5')
->call('unban', $token);
$this->assertDatabaseCount('banned_ips', 0);
$this->assertDatabaseHas('audit_events', ['action' => 'auth.ip_unbanned', 'target' => '203.0.113.5']);
}
public function test_unban_all_clears_every_ban(): void
{
$user = User::factory()->create();
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->addHour(), 'attempts' => 10]);
BannedIp::create(['ip' => '203.0.113.6', 'banned_until' => now()->addHour(), 'attempts' => 10]);
$this->actingAs($user);
$token = ConfirmToken::issue('bansClearedAll');
ConfirmToken::confirm($token);
Livewire::actingAs($user)->test(LoginProtection::class)->call('unbanAll', $token);
$this->assertDatabaseCount('banned_ips', 0);
$this->assertDatabaseHas('audit_events', ['action' => 'auth.ip_unbanned', 'target' => 'all']);
}
public function test_widening_whitelist_clears_now_exempt_bans(): void
{
$user = User::factory()->create();
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->addHour(), 'attempts' => 10]);
Livewire::actingAs($user)->test(LoginProtection::class)
->set('whitelist', '203.0.113.0/24')->call('save');
$this->assertDatabaseCount('banned_ips', 0); // 203.0.113.5 now exempt → purged
}
public function test_whitelist_my_ip_adds_current_ip(): void
{
$user = User::factory()->create();
// Inject the public IP into every request bound to the container,
// using the same rebinding mechanism as BruteforceHooksTest (Task 6).
app()->rebinding('request', static function ($app, $request) {
$request->server->set('REMOTE_ADDR', '198.51.100.7');
});
Livewire::actingAs($user)->test(LoginProtection::class)
->call('whitelistMyIp')
->assertSet('whitelist', fn ($w) => str_contains($w, '198.51.100.7'));
}
}