test(auth): BruteforceGuard record/ban/unban/cache
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>feat/v1-foundation
parent
49d5c0aed3
commit
df32275fd9
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\BannedIp;
|
||||
use App\Models\Setting;
|
||||
use App\Services\BruteforceGuard;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Tests\TestCase;
|
||||
|
||||
class BruteforceGuardBanTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
Cache::flush();
|
||||
}
|
||||
|
||||
private function guard(): BruteforceGuard
|
||||
{
|
||||
return app(BruteforceGuard::class);
|
||||
}
|
||||
|
||||
public function test_records_until_threshold_then_bans(): void
|
||||
{
|
||||
$g = $this->guard();
|
||||
Setting::put('bruteforce_maxretry', '3');
|
||||
|
||||
$g->record('203.0.113.5', 'login');
|
||||
$g->record('203.0.113.5', 'login');
|
||||
$this->assertFalse($g->isBanned('203.0.113.5'));
|
||||
|
||||
$g->record('203.0.113.5', 'login'); // 3rd → ban
|
||||
$this->assertTrue($g->isBanned('203.0.113.5'));
|
||||
$this->assertDatabaseHas('banned_ips', ['ip' => '203.0.113.5', 'reason' => 'login']);
|
||||
$this->assertDatabaseHas('audit_events', ['action' => 'auth.ip_banned', 'ip' => '203.0.113.5']);
|
||||
}
|
||||
|
||||
public function test_exempt_ip_is_never_banned(): void
|
||||
{
|
||||
$g = $this->guard();
|
||||
Setting::put('bruteforce_maxretry', '1');
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$g->record('192.168.1.50', 'login'); // private = default whitelist
|
||||
}
|
||||
$this->assertFalse($g->isBanned('192.168.1.50'));
|
||||
$this->assertDatabaseCount('banned_ips', 0);
|
||||
}
|
||||
|
||||
public function test_disabled_records_nothing(): void
|
||||
{
|
||||
Setting::put('bruteforce_enabled', '0');
|
||||
Setting::put('bruteforce_maxretry', '1');
|
||||
$this->guard()->record('203.0.113.9', 'login');
|
||||
$this->assertDatabaseCount('banned_ips', 0);
|
||||
}
|
||||
|
||||
public function test_unban_clears_row_and_cache(): void
|
||||
{
|
||||
$g = $this->guard();
|
||||
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->addHour(), 'attempts' => 10]);
|
||||
$this->assertTrue($g->isBanned('203.0.113.5')); // populates cache
|
||||
$g->unban('203.0.113.5');
|
||||
$this->assertFalse($g->isBanned('203.0.113.5')); // no stale positive
|
||||
$this->assertDatabaseCount('banned_ips', 0);
|
||||
}
|
||||
|
||||
public function test_expired_ban_is_not_active(): void
|
||||
{
|
||||
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->subMinute(), 'attempts' => 10]);
|
||||
$this->assertFalse($this->guard()->isBanned('203.0.113.5'));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue