feat(auth): clusev:unban CLI + host wrapper escape hatch
parent
01867dba09
commit
96f86e2761
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\BannedIp;
|
||||
use App\Services\BruteforceGuard;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class UnbanIp extends Command
|
||||
{
|
||||
protected $signature = 'clusev:unban {ip? : Zu entsperrende IP-Adresse} {--all : Alle aktiven Bänne entfernen}';
|
||||
|
||||
protected $description = 'Entfernt App-Level-IP-Bänne des Anmeldeschutzes per Shell (Aussperr-Rettung)';
|
||||
|
||||
public function handle(BruteforceGuard $guard): int
|
||||
{
|
||||
if ($this->option('all')) {
|
||||
$count = BannedIp::query()->count();
|
||||
foreach (BannedIp::query()->pluck('ip') as $ip) {
|
||||
Cache::forget('bruteforce:banned:'.$ip);
|
||||
}
|
||||
BannedIp::query()->delete();
|
||||
$this->info("{$count} Bann/Bänne entfernt.");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$ip = (string) $this->argument('ip');
|
||||
if ($ip === '') {
|
||||
$this->error('Bitte eine IP angeben oder --all verwenden.');
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$guard->unban($ip);
|
||||
$this->info("Bann für {$ip} entfernt (falls vorhanden).");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ clusev — Fleet-Control Verwaltung (Host)
|
|||
|
||||
sudo clusev update Update holen, Image neu bauen, Migrationen anwenden (root)
|
||||
clusev reset-admin Admin-Zugang zuruecksetzen (2FA entfernen, Passwort neu setzen)
|
||||
clusev unban <ip> Gebannte IP entsperren (--all fuer alle)
|
||||
clusev restart Stack neu starten
|
||||
clusev logs [dienst] Logs folgen (Strg-C beendet)
|
||||
clusev ps Dienst-Status (Alias: status)
|
||||
|
|
@ -38,6 +39,7 @@ cmd="${1:-help}"; shift 2>/dev/null || true
|
|||
case "$cmd" in
|
||||
update) exec "${CLUSEV_DIR}/update.sh" "$@" ;;
|
||||
reset-admin) compose exec app php artisan clusev:reset-admin "$@" ;;
|
||||
unban) compose exec app php artisan clusev:unban "$@" ;;
|
||||
restart) compose up -d "$@" ;;
|
||||
logs) compose logs -f "$@" ;;
|
||||
ps|status) compose ps "$@" ;;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\BannedIp;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UnbanCommandTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_unban_single_ip(): void
|
||||
{
|
||||
BannedIp::create(['ip' => '203.0.113.5', 'banned_until' => now()->addHour(), 'attempts' => 10]);
|
||||
$this->artisan('clusev:unban', ['ip' => '203.0.113.5'])->assertSuccessful();
|
||||
$this->assertDatabaseCount('banned_ips', 0);
|
||||
}
|
||||
|
||||
public function test_unban_all(): void
|
||||
{
|
||||
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->artisan('clusev:unban', ['--all' => true])->assertSuccessful();
|
||||
$this->assertDatabaseCount('banned_ips', 0);
|
||||
}
|
||||
|
||||
public function test_unban_without_args_fails(): void
|
||||
{
|
||||
$this->artisan('clusev:unban')->assertFailed();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue