Skip to content

Commit 2f99e60

Browse files
committed
Improve username validation
1 parent 7d875cd commit 2f99e60

5 files changed

Lines changed: 75 additions & 7 deletions

File tree

app/Console/Commands/CreateAdminUser.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,10 @@ private function validateUsernameForPrompt(string $username): ?string
225225
if (strlen($username) < 3) {
226226
return 'Username must be at least 3 characters.';
227227
}
228-
if (strlen($username) > 30) {
229-
return 'Username must not exceed 30 characters.';
228+
if (strlen($username) > 24) {
229+
return 'Username must not exceed 24 characters.';
230230
}
231-
if (! preg_match('/^[a-zA-Z0-9_-]+$/', $username)) {
231+
if (! preg_match('/^[a-zA-Z0-9_.-]+$/', $username)) {
232232
return 'Username can only contain letters, numbers, underscores, and hyphens.';
233233
}
234234
if (User::where('username', $username)->exists()) {

app/Http/Controllers/Auth/RegisterController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use App\Http\Controllers\Controller;
66
use App\Models\User;
7+
use App\Rules\ValidUsername;
78
use App\Services\UsernameService;
89
use Illuminate\Foundation\Auth\RegistersUsers;
910
use Illuminate\Support\Facades\Hash;
@@ -52,10 +53,10 @@ protected function validator(array $data)
5253
'name' => ['required', 'string', 'max:255'],
5354
'username' => [
5455
'required',
55-
'alpha_dash',
5656
'min:2',
57-
'max:30',
57+
'max:24',
5858
'unique:users,username',
59+
new ValidUsername,
5960
function ($attribute, $value, $fail) {
6061
if (app(UsernameService::class)->isReserved($value)) {
6162
$fail('This username is reserved.');

app/Http/Requests/StoreRegisterUsernameRequest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Http\Requests;
44

55
use App\Models\AdminSetting;
6+
use App\Rules\ValidUsername;
67
use App\Services\UsernameService;
78
use Illuminate\Auth\Access\AuthorizationException;
89
use Illuminate\Foundation\Http\FormRequest;
@@ -39,10 +40,10 @@ public function rules(): array
3940
return [
4041
'username' => [
4142
'required',
42-
'alpha_dash',
4343
'min:2',
44-
'max:30',
44+
'max:24',
4545
'unique:users,username',
46+
new ValidUsername,
4647
function ($attribute, $value, $fail) {
4748
if (app(UsernameService::class)->isReserved($value)) {
4849
$fail('This username is reserved.');

app/Rules/ValidUsername.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace App\Rules;
4+
5+
use Closure;
6+
use Illuminate\Contracts\Validation\ValidationRule;
7+
8+
class ValidUsername implements ValidationRule
9+
{
10+
/**
11+
* Run the validation rule.
12+
*
13+
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
14+
*/
15+
public function validate(string $attribute, mixed $value, Closure $fail): void
16+
{
17+
if (! preg_match('/^[a-zA-Z0-9_.-]+$/', $value)) {
18+
$fail('The :attribute can only contain letters, numbers, underscores, hyphens, and periods.');
19+
20+
return;
21+
}
22+
23+
if (str_starts_with($value, '.')) {
24+
$fail('The :attribute cannot start with a period.');
25+
26+
return;
27+
}
28+
29+
if (str_starts_with($value, '_')) {
30+
$fail('The :attribute cannot start with an underscore.');
31+
32+
return;
33+
}
34+
35+
if (str_starts_with($value, '-')) {
36+
$fail('The :attribute cannot start with a hyphen.');
37+
38+
return;
39+
}
40+
41+
if (str_ends_with($value, '.')) {
42+
$fail('The :attribute cannot end with a period.');
43+
44+
return;
45+
}
46+
47+
if (str_ends_with($value, '-')) {
48+
$fail('The :attribute cannot end with a hyphen.');
49+
50+
return;
51+
}
52+
53+
if (str_contains($value, '--')) {
54+
$fail('The :attribute cannot contain consecutive hyphens.');
55+
56+
return;
57+
}
58+
59+
if (str_contains($value, '..')) {
60+
$fail('The :attribute cannot contain consecutive periods.');
61+
62+
return;
63+
}
64+
}
65+
}

resources/js/components/AuthModal.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@
452452
v-model="form.username"
453453
type="text"
454454
required
455+
maxlength="24"
455456
class="w-full px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:border-blue-500 dark:focus:border-blue-400 focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 transition-colors"
456457
:placeholder="t('common.chooseAUsername')"
457458
/>

0 commit comments

Comments
 (0)