Skip to content

Commit 43befc6

Browse files
authored
DNS Validation Feature (#10)
1 parent 01e99e6 commit 43befc6

File tree

4 files changed

+813
-9
lines changed

4 files changed

+813
-9
lines changed

.github/workflows/run-tests.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,24 @@ jobs:
1515
strategy:
1616
fail-fast: true
1717
matrix:
18-
php: [8.1, 8.2, 8.3]
19-
laravel: ['10.*', '11.*', '12.*']
18+
php: [8.1, 8.2, 8.3, 8.4]
19+
laravel: ["10.*", "11.*", "12.*", "13.*"]
2020
include:
2121
- laravel: 10.*
2222
- laravel: 11.*
2323
- laravel: 12.*
24+
- laravel: 13.*
2425
exclude:
26+
- laravel: 10.*
27+
php: 8.4
2528
- laravel: 11.*
2629
php: 8.1
2730
- laravel: 12.*
2831
php: 8.1
32+
- laravel: 13.*
33+
php: 8.1
34+
- laravel: 13.*
35+
php: 8.2
2936

3037
name: P${{ matrix.php }} - L${{ matrix.laravel }}
3138

readme.md

Lines changed: 244 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,30 @@
44
![GitHub](https://img.shields.io/github/license/dacoto/laravel-domain-validation)
55
![GitHub release (latest by date)](https://img.shields.io/github/v/release/dacoto/laravel-domain-validation)
66

7-
A domain validator rule for Laravel 10.x and higher.
7+
A domain validator rule for Laravel 10.x and higher with optional DNS record verification.
88

9-
## Usage
9+
## Features
1010

11+
- Validates domain format using regex
12+
- Optional DNS record checking (A, AAAA, CNAME, TXT, MX records)
13+
- Verify DNS records resolve to expected values
14+
- Fluent API for chaining multiple DNS checks
15+
- String-based validation syntax support
16+
- Designed for external domains with DNS records
17+
18+
## Installation
19+
20+
```bash
21+
composer require dacoto/laravel-domain-validation
1122
```
23+
24+
## Basic Usage
25+
26+
### Simple Domain Validation
27+
28+
Validates that the input is a properly formatted domain:
29+
30+
```php
1231
use dacoto\DomainValidator\Validator\Domain;
1332

1433
public function rules()
@@ -18,3 +37,226 @@ public function rules()
1837
];
1938
}
2039
```
40+
41+
### String Syntax with DNS Checks
42+
43+
You can use the string syntax to check for the presence of DNS records:
44+
45+
```php
46+
public function rules()
47+
{
48+
return [
49+
50+
// Require DNS records to exist (any type)
51+
'hostname' => ['required', 'domain:dns'],
52+
// Require MX records
53+
'domain' => ['required', 'domain:mx'],
54+
55+
// Require multiple DNS record types
56+
'website' => ['required', 'domain:a,mx'],
57+
58+
];
59+
}
60+
```
61+
62+
### Fluent API
63+
64+
For more control, use the fluent API:
65+
66+
```php
67+
use dacoto\DomainValidator\Validator\Domain;
68+
69+
public function rules()
70+
{
71+
return [
72+
// Check for DNS records
73+
'hostname' => ['required', (new Domain)->requireDns()],
74+
// Check for MX records
75+
'email_domain' => ['required', (new Domain)->requireMx()],
76+
77+
// Chain multiple DNS checks
78+
'website' => ['required', (new Domain)->requireA()->requireMx()],
79+
80+
];
81+
}
82+
```
83+
84+
## DNS Record Type Checks
85+
86+
### Available DNS Record Types
87+
88+
- `dns` - Checks for presence of any DNS record (A, AAAA, CNAME, TXT, MX, NS, or SOA)
89+
- `a` - IPv4 address records
90+
- `aaaa` - IPv6 address records
91+
- `cname` - Canonical name records
92+
- `txt` - Text records
93+
- `mx` - Mail exchange records
94+
95+
### Verifying DNS Records Match Expected Values
96+
97+
You can verify that DNS records resolve to specific values using the fluent API:
98+
99+
```php
100+
use dacoto\DomainValidator\Validator\Domain;
101+
102+
public function rules()
103+
{
104+
return [
105+
// Require A record pointing to specific IP
106+
'domain' => ['required', (new Domain)->requireA('192.0.2.1')],
107+
108+
// Require MX record pointing to specific mail server
109+
'email_domain' => ['required', (new Domain)->requireMx('mail.example.com')],
110+
111+
// Multiple checks with specific values
112+
'website' => [
113+
'required',
114+
(new Domain)
115+
->requireA('192.0.2.1')
116+
->requireMx('mail.example.com')
117+
],
118+
];
119+
}
120+
```
121+
122+
#### Multiple Expected Values
123+
124+
When a domain has multiple DNS records of the same type (e.g., multiple A records for load balancing), the validator passes if **ANY** of the records match the expected value. You can chain multiple calls to verify multiple specific values:
125+
126+
```php
127+
public function rules()
128+
{
129+
return [
130+
// Verify domain has BOTH specific IPs
131+
// (each requireA checks if that IP exists among the A records)
132+
'cdn_domain' => [
133+
'required',
134+
(new Domain)
135+
->requireA('104.16.132.229')
136+
->requireA('104.16.133.229')
137+
],
138+
139+
// Example with Google's public DNS (dns.google.com)
140+
// which resolves to both 8.8.8.8 and 8.8.4.4
141+
'google_dns' => [
142+
'required',
143+
(new Domain)
144+
->requireA('8.8.8.8') // Passes if this IP is found
145+
->requireA('8.8.4.4') // Also passes if this IP is found
146+
],
147+
];
148+
}
149+
```
150+
151+
## Advanced Examples
152+
153+
### Form Request Validation
154+
155+
```php
156+
use Illuminate\Foundation\Http\FormRequest;
157+
use dacoto\DomainValidator\Validator\Domain;
158+
159+
class CreateWebsiteRequest extends FormRequest
160+
{
161+
public function rules()
162+
{
163+
return [
164+
'domain' => [
165+
'required',
166+
'string',
167+
(new Domain)->requireA()->requireMx()
168+
],
169+
];
170+
}
171+
}
172+
```
173+
174+
### Manual Validator
175+
176+
```php
177+
use Illuminate\Support\Facades\Validator;
178+
use dacoto\DomainValidator\Validator\Domain;
179+
180+
$validator = Validator::make($request->all(), [
181+
'domain' => ['required', new Domain('mx', 'a')],
182+
]);
183+
184+
if ($validator->fails()) {
185+
return redirect()->back()->withErrors($validator);
186+
}
187+
```
188+
189+
### Conditional DNS Checks
190+
191+
```php
192+
use dacoto\DomainValidator\Validator\Domain;
193+
194+
public function rules()
195+
{
196+
return [
197+
'domain' => [
198+
'required',
199+
(new Domain)
200+
->requireA()
201+
->when($this->check_email, function ($rule) {
202+
return $rule->requireMx();
203+
})
204+
],
205+
];
206+
}
207+
```
208+
209+
## Error Messages
210+
211+
The validator provides specific error messages for different validation failures:
212+
213+
- **Invalid format**: "The {attribute} is not a valid domain."
214+
- **Missing DNS records**: "The {attribute} must have valid {TYPE} records."
215+
- **Missing any DNS**: "The {attribute} must have valid DNS records."
216+
- **Value mismatch**: "The {attribute} must have a {TYPE} record pointing to {value}."
217+
218+
### Custom Error Messages
219+
220+
You can customize error messages in your language files:
221+
222+
```php
223+
// resources/lang/en/validation.php
224+
225+
return [
226+
'domain' => 'The :attribute must be a valid domain name.',
227+
'domain_dns' => 'The :attribute must have valid :type DNS records.',
228+
'domain_dns_any' => 'The :attribute must have valid DNS records configured.',
229+
'domain_dns_value' => 'The :attribute must have a :type record pointing to :value.',
230+
];
231+
```
232+
233+
## Requirements
234+
235+
- PHP 8.1 or higher
236+
- Laravel 10.x or higher
237+
238+
## Testing
239+
240+
Run the test suite:
241+
242+
```bash
243+
composer test
244+
```
245+
246+
The package includes comprehensive tests covering:
247+
248+
- ✅ Basic domain format validation
249+
- ✅ String-based syntax (via constructor: `new Domain('a')`, `new Domain('a', 'mx')`)
250+
- ✅ Fluent API methods (chaining, expected values)
251+
- ✅ All DNS record types (A, AAAA, CNAME, TXT, MX, ANY)
252+
- ✅ Multiple expected values (load balancing scenarios)
253+
- ✅ Error messages and edge cases
254+
- ✅ Uses reliable test domain (dns.google.com)
255+
256+
**Test Results:** 20 tests, 37 assertions, 100% passing ✅
257+
258+
## License
259+
260+
This package is open-sourced software licensed under the MIT license.
261+
262+

0 commit comments

Comments
 (0)