Skip to content

Commit ebf003e

Browse files
committed
Add support for routable_ip_or_net
Joins together the two routable rules to allow user submission of either a routable IP or Subnet
1 parent 3d3ed06 commit ebf003e

File tree

4 files changed

+159
-0
lines changed

4 files changed

+159
-0
lines changed

Diff for: README.md

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Here is a list of the available rules and their usage.
2424
[Private IPv4](#private_ipv4)<br/>
2525
[Private IPv6](#private_ipv6)<br/>
2626
[Private Net](#private_net)<br/>
27+
[Routable IP or Net](#routable_ip_or_net)<br/>
2728
[Routable IP](#routable_ip)<br/>
2829
[Routable IPv4](#routable_ipv4)<br/>
2930
[Routable IPv6](#routable_ipv6)<br/>
@@ -94,6 +95,10 @@ The networks considered private are described in the `private_ip` rule.
9495
The field under validation must be a private IP network in CIDR notation.
9596
The networks considered private are described in the `private_ip` rule.
9697

98+
### routable_ip_or_net
99+
The field under validation must be a globally routable IP address or network in CIDR notation.
100+
This excludes all private and reserved ranges, as detailed the the `private_ip` rule.
101+
97102
### routable_ip
98103
The field under validation must be a globally routable IPv4 or IPv6 address.
99104
This excludes all private and reserved ranges, as detailed the the `private_ip` rule.

Diff for: src/Providers/ValidationProvider.php

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function boot(): void
1818
$validator->extend('routable_ip', Rules\RoutableIp::class . '@extend');
1919
$validator->extend('routable_net', Rules\RoutableNet::class . '@extend');
2020
$validator->extend('ip_or_net', Rules\IpOrNet::class . '@extend');
21+
$validator->extend('routable_ip_or_net', Rules\RoutableIpOrNet::class . '@extend');
2122
$validator->extend('private_ipv4', Rules\PrivateIpv4::class . '@extend');
2223
$validator->extend('routable_ipv4', Rules\RoutableIpv4::class . '@extend');
2324
$validator->extend('netv4', Rules\Netv4::class . '@extend');

Diff for: src/Rules/RoutableIpOrNet.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Miken32\Validation\Network\Rules;
4+
5+
use Miken32\Validation\Network\Util;
6+
7+
class RoutableIpOrNet extends BaseRule
8+
{
9+
public function doValidation(string $attribute, string $value, ...$parameters): bool
10+
{
11+
return Util::validRoutableIPAddress($value) || Util::validRoutableIPNetwork($value);
12+
}
13+
14+
public function message(): string
15+
{
16+
return __("The :attribute field must be a routable IP address or IP network in CIDR notation");
17+
}
18+
}

Diff for: tests/Feature/RoutableIpOrNetTest.php

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
namespace Miken32\Validation\Tests\Feature;
4+
5+
use Illuminate\Support\Facades\Validator;
6+
use Illuminate\Validation\ValidationException;
7+
use Miken32\Validation\Network\Rules;
8+
use Miken32\Validation\Tests\TestCase;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\Attributes\Test;
11+
12+
#[CoversClass(\Miken32\Validation\Network\Rules\RoutableIpOrNet::class)]
13+
class RoutableIpOrNetTest extends TestCase
14+
{
15+
#[Test]
16+
public function stringAccepts(): void
17+
{
18+
$this->expectNotToPerformAssertions();
19+
Validator::validate(
20+
['input_test' => '1.1.1.1'],
21+
['input_test' => 'routable_ip_or_net']
22+
);
23+
Validator::validate(
24+
['input_test' => '2600:482e:1948::21'],
25+
['input_test' => 'routable_ip_or_net']
26+
);
27+
Validator::validate(
28+
['input_test' => '1.1.1.1/29'],
29+
['input_test' => 'routable_ip_or_net']
30+
);
31+
Validator::validate(
32+
['input_test' => '2600:2345:23ac::/56'],
33+
['input_test' => 'routable_ip_or_net']
34+
);
35+
}
36+
37+
#[Test]
38+
public function instanceAccepts(): void
39+
{
40+
$this->expectNotToPerformAssertions();
41+
Validator::validate(
42+
['input_test' => '1.1.1.1'],
43+
['input_test' => new Rules\RoutableIpOrNet()]
44+
);
45+
Validator::validate(
46+
['input_test' => '2600:482e:1948::21'],
47+
['input_test' => new Rules\RoutableIpOrNet()]
48+
);
49+
Validator::validate(
50+
['input_test' => '1.1.1.1/29'],
51+
['input_test' => new Rules\RoutableIpOrNet()]
52+
);
53+
Validator::validate(
54+
['input_test' => '2600:2345:23ac::/56'],
55+
['input_test' => new Rules\RoutableIpOrNet()]
56+
);
57+
}
58+
59+
#[Test]
60+
public function stringRejectsIpv4(): void
61+
{
62+
$this->expectException(ValidationException::class);
63+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
64+
Validator::validate(
65+
['input_test' => '10.5.38.218'],
66+
['input_test' => 'routable_ip_or_net']
67+
);
68+
69+
$this->expectException(ValidationException::class);
70+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
71+
Validator::validate(
72+
['input_test' => $this->faker->localIpv4 . '/23'],
73+
['input_test' => 'routable_ip_or_net']
74+
);
75+
}
76+
77+
#[Test]
78+
public function stringRejectsIpv6(): void
79+
{
80+
$this->expectException(ValidationException::class);
81+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
82+
Validator::validate(
83+
['input_test' => '2001:0000:0000::f298'],
84+
['input_test' => 'routable_ip_or_net']
85+
);
86+
87+
$this->expectException(ValidationException::class);
88+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
89+
$v6 = $this->faker->ipv6;
90+
$v6 = 'fd00' . substr($v6, strpos($v6, ':')) . '/64';
91+
Validator::validate(
92+
['input_test' => $v6],
93+
['input_test' => 'routable_ip_or_net']
94+
);
95+
}
96+
97+
#[Test]
98+
public function instanceRejectsIpv4(): void
99+
{
100+
$this->expectException(ValidationException::class);
101+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
102+
Validator::validate(
103+
['input_test' => '10.5.38.218'],
104+
['input_test' => new Rules\RoutableIpOrNet()]
105+
);
106+
107+
$this->expectException(ValidationException::class);
108+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
109+
Validator::validate(
110+
['input_test' => $this->faker->localIpv4 . '/23'],
111+
['input_test' => new Rules\RoutableIpOrNet()]
112+
);
113+
}
114+
115+
#[Test]
116+
public function instanceRejectsIpv6(): void
117+
{
118+
$this->expectException(ValidationException::class);
119+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
120+
Validator::validate(
121+
['input_test' => '2001:0000:0000::f298'],
122+
['input_test' => new Rules\RoutableIpOrNet()]
123+
);
124+
125+
$this->expectException(ValidationException::class);
126+
$this->expectExceptionMessage('The input test field must be a routable IP address or IP network in CIDR notation');
127+
$v6 = $this->faker->ipv6;
128+
$v6 = 'fd00' . substr($v6, strpos($v6, ':')) . '/64';
129+
Validator::validate(
130+
['input_test' => $v6],
131+
['input_test' => new Rules\RoutableIpOrNet()]
132+
);
133+
}
134+
135+
}

0 commit comments

Comments
 (0)