From 7645241a7aca1f71719d2ff0c9e4587a2d7bd3da Mon Sep 17 00:00:00 2001 From: boban Date: Sat, 20 Jun 2026 17:42:06 +0200 Subject: [PATCH] feat(auth): ValidIpOrCidr validation rule --- app/Rules/ValidIpOrCidr.php | 30 +++++++++++++++++++++++++++++ lang/de/settings.php | 3 +++ lang/en/settings.php | 3 +++ tests/Feature/ValidIpOrCidrTest.php | 30 +++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 app/Rules/ValidIpOrCidr.php create mode 100644 tests/Feature/ValidIpOrCidrTest.php diff --git a/app/Rules/ValidIpOrCidr.php b/app/Rules/ValidIpOrCidr.php new file mode 100644 index 0000000..d72114c --- /dev/null +++ b/app/Rules/ValidIpOrCidr.php @@ -0,0 +1,30 @@ + $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])); + } + } +} diff --git a/lang/de/settings.php b/lang/de/settings.php index a54c7fa..0336428 100644 --- a/lang/de/settings.php +++ b/lang/de/settings.php @@ -63,4 +63,7 @@ return [ // Page title 'title' => 'Einstellungen — Clusev', + + // IP/CIDR whitelist validation + 'lp_whitelist_invalid' => ':value ist keine gültige IP/CIDR.', ]; diff --git a/lang/en/settings.php b/lang/en/settings.php index 871eb4d..d4fee99 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -63,4 +63,7 @@ return [ // Page title 'title' => 'Settings — Clusev', + + // IP/CIDR whitelist validation + 'lp_whitelist_invalid' => ':value is not a valid IP/CIDR.', ]; diff --git a/tests/Feature/ValidIpOrCidrTest.php b/tests/Feature/ValidIpOrCidrTest.php new file mode 100644 index 0000000..2fec5bf --- /dev/null +++ b/tests/Feature/ValidIpOrCidrTest.php @@ -0,0 +1,30 @@ + $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/')); + } +}