feat(auth): ValidIpOrCidr validation rule
parent
df32275fd9
commit
7645241a7a
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Rules;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
class ValidIpOrCidr implements ValidationRule
|
||||||
|
{
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
$v = is_string($value) ? trim($value) : '';
|
||||||
|
|
||||||
|
if (filter_var($v, FILTER_VALIDATE_IP) !== false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! str_contains($v, '/')) {
|
||||||
|
$fail(__('settings.lp_whitelist_invalid', ['value' => $v]));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[$ip, $mask] = explode('/', $v, 2);
|
||||||
|
$max = str_contains($ip, ':') ? 128 : 32;
|
||||||
|
if (filter_var($ip, FILTER_VALIDATE_IP) === false || ! ctype_digit($mask) || (int) $mask < 0 || (int) $mask > $max) {
|
||||||
|
$fail(__('settings.lp_whitelist_invalid', ['value' => $v]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,4 +63,7 @@ return [
|
||||||
|
|
||||||
// Page title
|
// Page title
|
||||||
'title' => 'Einstellungen — Clusev',
|
'title' => 'Einstellungen — Clusev',
|
||||||
|
|
||||||
|
// IP/CIDR whitelist validation
|
||||||
|
'lp_whitelist_invalid' => ':value ist keine gültige IP/CIDR.',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -63,4 +63,7 @@ return [
|
||||||
|
|
||||||
// Page title
|
// Page title
|
||||||
'title' => 'Settings — Clusev',
|
'title' => 'Settings — Clusev',
|
||||||
|
|
||||||
|
// IP/CIDR whitelist validation
|
||||||
|
'lp_whitelist_invalid' => ':value is not a valid IP/CIDR.',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Rules\ValidIpOrCidr;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class ValidIpOrCidrTest extends TestCase
|
||||||
|
{
|
||||||
|
private function passes(string $value): bool
|
||||||
|
{
|
||||||
|
return Validator::make(['v' => $value], ['v' => [new ValidIpOrCidr]])->passes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_accepts_ips_and_cidrs(): void
|
||||||
|
{
|
||||||
|
$this->assertTrue($this->passes('203.0.113.4'));
|
||||||
|
$this->assertTrue($this->passes('10.0.0.0/8'));
|
||||||
|
$this->assertTrue($this->passes('::1'));
|
||||||
|
$this->assertTrue($this->passes('2001:db8::/32'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_rejects_junk(): void
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->passes('nope'));
|
||||||
|
$this->assertFalse($this->passes('10.0.0.0/99'));
|
||||||
|
$this->assertFalse($this->passes('1.2.3.4/'));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue