115 lines
4.3 KiB
PHP
115 lines
4.3 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'));
|
|
}
|
|
|
|
public function test_unban_rejects_a_forged_token(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->addHour(), 'attempts' => 10]);
|
|
|
|
Livewire::actingAs($user)->test(LoginProtection::class)->call('unban', 'not-a-real-token');
|
|
|
|
$this->assertDatabaseCount('banned_ips', 1); // forged token → no-op, ban remains
|
|
}
|
|
}
|