Roberto Santini 1 месяц назад
Родитель
Сommit
a2dbd4fbd7

+ 1
- 1
app/Actions/Fortify/CreateNewUser.php Просмотреть файл

24
             'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
24
             'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
25
             'password' => $this->passwordRules(),
25
             'password' => $this->passwordRules(),
26
             'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
26
             'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
27
-        ])->validate();
27
+        ], $this->passwordValidationMessages())->validate();
28
 
28
 
29
         return User::create([
29
         return User::create([
30
             'name' => $input['name'],
30
             'name' => $input['name'],

+ 10
- 2
app/Actions/Fortify/PasswordValidationRules.php Просмотреть файл

2
 
2
 
3
 namespace App\Actions\Fortify;
3
 namespace App\Actions\Fortify;
4
 
4
 
5
-use Illuminate\Validation\Rules\Password;
5
+use App\Support\PasswordRequirements;
6
 
6
 
7
 trait PasswordValidationRules
7
 trait PasswordValidationRules
8
 {
8
 {
13
      */
13
      */
14
     protected function passwordRules(): array
14
     protected function passwordRules(): array
15
     {
15
     {
16
-        return ['required', 'string', Password::default(), 'confirmed'];
16
+        return ['required', 'string', PasswordRequirements::rule(), 'confirmed'];
17
+    }
18
+
19
+    /**
20
+     * @return array<string, string>
21
+     */
22
+    protected function passwordValidationMessages(): array
23
+    {
24
+        return PasswordRequirements::messages();
17
     }
25
     }
18
 }
26
 }

+ 1
- 1
app/Actions/Fortify/ResetUserPassword.php Просмотреть файл

20
     {
20
     {
21
         Validator::make($input, [
21
         Validator::make($input, [
22
             'password' => $this->passwordRules(),
22
             'password' => $this->passwordRules(),
23
-        ])->validate();
23
+        ], $this->passwordValidationMessages())->validate();
24
 
24
 
25
         $user->forceFill([
25
         $user->forceFill([
26
             'password' => Hash::make($input['password']),
26
             'password' => Hash::make($input['password']),

+ 2
- 2
app/Actions/Fortify/UpdateUserPassword.php Просмотреть файл

21
         Validator::make($input, [
21
         Validator::make($input, [
22
             'current_password' => ['required', 'string', 'current_password:web'],
22
             'current_password' => ['required', 'string', 'current_password:web'],
23
             'password' => $this->passwordRules(),
23
             'password' => $this->passwordRules(),
24
-        ], [
24
+        ], array_merge($this->passwordValidationMessages(), [
25
             'current_password.current_password' => __('The provided password does not match your current password.'),
25
             'current_password.current_password' => __('The provided password does not match your current password.'),
26
-        ])->validateWithBag('updatePassword');
26
+        ]))->validateWithBag('updatePassword');
27
 
27
 
28
         $user->forceFill([
28
         $user->forceFill([
29
             'password' => Hash::make($input['password']),
29
             'password' => Hash::make($input['password']),

+ 4
- 4
app/Http/Controllers/UserController.php Просмотреть файл

26
 use Intervention\Image\Drivers\Gd\Driver;
26
 use Intervention\Image\Drivers\Gd\Driver;
27
 use Illuminate\Support\Facades\Validator;
27
 use Illuminate\Support\Facades\Validator;
28
 use App\Models\Role;
28
 use App\Models\Role;
29
+use App\Support\PasswordRequirements;
29
 
30
 
30
 class UserController extends Controller implements HasMiddleware
31
 class UserController extends Controller implements HasMiddleware
31
 {
32
 {
252
 
253
 
253
           $validated = $request->validate([
254
           $validated = $request->validate([
254
             'current_password' => ['required', 'string', 'current_password:web'],
255
             'current_password' => ['required', 'string', 'current_password:web'],
255
-            'password' => ['required', 'string', 'confirmed', \Illuminate\Validation\Rules\Password::default()],
256
-          ], [
256
+            'password' => ['required', 'string', 'confirmed', PasswordRequirements::rule()],
257
+          ], array_merge(PasswordRequirements::messages(), [
257
             'current_password.current_password' => 'La password attuale non è corretta.',
258
             'current_password.current_password' => 'La password attuale non è corretta.',
258
-            'password.confirmed' => 'La conferma password non coincide.',
259
-          ]);
259
+          ]));
260
 
260
 
261
           $user->forceFill([
261
           $user->forceFill([
262
             'password' => Hash::make($validated['password']),
262
             'password' => Hash::make($validated['password']),

+ 6
- 0
app/Models/User.php Просмотреть файл

1
 <?php
1
 <?php
2
 namespace App\Models;
2
 namespace App\Models;
3
 
3
 
4
+use App\Notifications\ResetPasswordNotification;
4
 use Illuminate\Database\Eloquent\Factories\HasFactory;
5
 use Illuminate\Database\Eloquent\Factories\HasFactory;
5
 use Illuminate\Foundation\Auth\User as Authenticatable;
6
 use Illuminate\Foundation\Auth\User as Authenticatable;
6
 use Illuminate\Notifications\Notifiable;
7
 use Illuminate\Notifications\Notifiable;
156
       ->whereNotNull('email')
157
       ->whereNotNull('email')
157
       ->get();
158
       ->get();
158
   }
159
   }
160
+
161
+  public function sendPasswordResetNotification($token): void
162
+  {
163
+    $this->notify(new ResetPasswordNotification($token));
164
+  }
159
 }
165
 }

+ 14
- 47
app/Notifications/ResetPasswordNotification.php Просмотреть файл

2
 
2
 
3
 namespace App\Notifications;
3
 namespace App\Notifications;
4
 
4
 
5
+use Illuminate\Auth\Notifications\ResetPassword;
5
 use Illuminate\Bus\Queueable;
6
 use Illuminate\Bus\Queueable;
6
 use Illuminate\Contracts\Queue\ShouldQueue;
7
 use Illuminate\Contracts\Queue\ShouldQueue;
7
 use Illuminate\Notifications\Messages\MailMessage;
8
 use Illuminate\Notifications\Messages\MailMessage;
8
-use Illuminate\Notifications\Notification;
9
 
9
 
10
-class ResetPasswordNotification extends Notification implements ShouldQueue
10
+class ResetPasswordNotification extends ResetPassword implements ShouldQueue
11
 {
11
 {
12
   use Queueable;
12
   use Queueable;
13
-  public $url = "";
14
 
13
 
15
   /**
14
   /**
16
-  * Create a new notification instance.
17
-  *
18
-  * @return void
19
-  */
20
-  public function __construct($url)
21
-  {
22
-    $this->url = $url;
23
-  }
24
-
25
-  /**
26
-  * Get the notification's delivery channels.
27
-  *
28
-  * @param  mixed  $notifiable
29
-  * @return array
30
-  */
31
-  public function via($notifiable)
32
-  {
33
-    return ['mail'];
34
-  }
35
-
36
-  /**
37
-  * Get the mail representation of the notification.
38
-  *
39
-  * @param  mixed  $notifiable
40
-  * @return \Illuminate\Notifications\Messages\MailMessage
41
-  */
15
+   * Get the mail representation of the notification.
16
+   *
17
+   * @param  mixed  $notifiable
18
+   * @return \Illuminate\Notifications\Messages\MailMessage
19
+   */
42
   public function toMail($notifiable)
20
   public function toMail($notifiable)
43
   {
21
   {
44
-    return (new MailMessage)
45
-    ->subject('Reset password')
46
-    ->line('Hai ricevuto questa email perché abbiamo ricevuto una richiesta di reimpostazione della password per il tuo account.')
47
-    ->action('Reset Password', $this->url)
48
-    ->line('Questo link per la reimpostazione della password scadrà tra 60 minuti.')
49
-    ->line('Se non hai richiesto la reimpostazione della password, non sono necessarie ulteriori azioni.');
50
-  }
22
+    $expire = (int) config('auth.passwords.users.expire', 60);
51
 
23
 
52
-  /**
53
-  * Get the array representation of the notification.
54
-  *
55
-  * @param  mixed  $notifiable
56
-  * @return array
57
-  */
58
-  public function toArray($notifiable)
59
-  {
60
-    return [
61
-      //
62
-    ];
24
+    return (new MailMessage)
25
+      ->subject('Reimposta la password')
26
+      ->line('Hai ricevuto questa email perché abbiamo ricevuto una richiesta di reimpostazione della password per il tuo account.')
27
+      ->action('Reimposta la password', $this->resetUrl($notifiable))
28
+      ->line("Questo link per la reimpostazione della password scadrà tra {$expire} minuti.")
29
+      ->line('Se non hai richiesto la reimpostazione della password, non sono necessarie ulteriori azioni.');
63
   }
30
   }
64
 }
31
 }

+ 28
- 0
app/Support/PasswordRequirements.php Просмотреть файл

1
+<?php
2
+
3
+namespace App\Support;
4
+
5
+use Illuminate\Validation\Rules\Password;
6
+
7
+class PasswordRequirements
8
+{
9
+    public const HINT = 'La password deve contenere almeno 6 caratteri, un numero e un simbolo.';
10
+
11
+    public static function rule(): Password
12
+    {
13
+        return Password::min(6)->numbers()->symbols();
14
+    }
15
+
16
+    /**
17
+     * @return array<string, string>
18
+     */
19
+    public static function messages(): array
20
+    {
21
+        return [
22
+            'password.min' => 'La password deve contenere almeno 6 caratteri.',
23
+            'password.numbers' => 'La password deve contenere almeno un numero.',
24
+            'password.symbols' => 'La password deve contenere almeno un simbolo.',
25
+            'password.confirmed' => 'La conferma della password non corrisponde.',
26
+        ];
27
+    }
28
+}

+ 6
- 0
lang/it.json Просмотреть файл

89
   "Resend Verification Email": "Invia nuovamente email di verifica",
89
   "Resend Verification Email": "Invia nuovamente email di verifica",
90
   "Reset Content": "Resetta il contenuto",
90
   "Reset Content": "Resetta il contenuto",
91
   "Reset Password": "Resetta la password",
91
   "Reset Password": "Resetta la password",
92
+  "Reset Password Notification": "Reimposta la password",
93
+  "You are receiving this email because we received a password reset request for your account.": "Hai ricevuto questa email perché abbiamo ricevuto una richiesta di reimpostazione della password per il tuo account.",
94
+  "This password reset link will expire in :count minutes.": "Questo link per la reimpostazione della password scadrà tra :count minuti.",
95
+  "If you did not request a password reset, no further action is required.": "Se non hai richiesto la reimpostazione della password, non sono necessarie ulteriori azioni.",
96
+  "Hello!": "Ciao!",
97
+  "Regards": "Cordiali saluti",
92
   "Retry With": "Riprova con",
98
   "Retry With": "Riprova con",
93
   "Save": "Salva",
99
   "Save": "Salva",
94
   "Saved.": "Salvato.",
100
   "Saved.": "Salvato.",

+ 1
- 0
resources/views/profile/edit_profile.blade.php Просмотреть файл

260
           <div class="mb-3">
260
           <div class="mb-3">
261
             <label class="form-label" for="password">Nuova password</label>
261
             <label class="form-label" for="password">Nuova password</label>
262
             <input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password" autocomplete="new-password" required>
262
             <input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password" autocomplete="new-password" required>
263
+            <div class="form-text">{{ \App\Support\PasswordRequirements::HINT }}</div>
263
             @error('password')
264
             @error('password')
264
             <div class="invalid-feedback">{{ $message }}</div>
265
             <div class="invalid-feedback">{{ $message }}</div>
265
             @enderror
266
             @enderror

+ 6
- 6
tests/Feature/PasswordResetTest.php Просмотреть файл

3
 namespace Tests\Feature;
3
 namespace Tests\Feature;
4
 
4
 
5
 use App\Models\User;
5
 use App\Models\User;
6
-use Illuminate\Auth\Notifications\ResetPassword;
6
+use App\Notifications\ResetPasswordNotification;
7
 use Illuminate\Foundation\Testing\RefreshDatabase;
7
 use Illuminate\Foundation\Testing\RefreshDatabase;
8
 use Illuminate\Support\Facades\Notification;
8
 use Illuminate\Support\Facades\Notification;
9
 use Laravel\Fortify\Features;
9
 use Laravel\Fortify\Features;
38
             'email' => $user->email,
38
             'email' => $user->email,
39
         ]);
39
         ]);
40
 
40
 
41
-        Notification::assertSentTo($user, ResetPassword::class);
41
+        Notification::assertSentTo($user, ResetPasswordNotification::class);
42
     }
42
     }
43
 
43
 
44
     public function test_reset_password_screen_can_be_rendered(): void
44
     public function test_reset_password_screen_can_be_rendered(): void
55
             'email' => $user->email,
55
             'email' => $user->email,
56
         ]);
56
         ]);
57
 
57
 
58
-        Notification::assertSentTo($user, ResetPassword::class, function (object $notification) {
58
+        Notification::assertSentTo($user, ResetPasswordNotification::class, function (object $notification) {
59
             $response = $this->get('/reset-password/'.$notification->token);
59
             $response = $this->get('/reset-password/'.$notification->token);
60
 
60
 
61
             $response->assertStatus(200);
61
             $response->assertStatus(200);
78
             'email' => $user->email,
78
             'email' => $user->email,
79
         ]);
79
         ]);
80
 
80
 
81
-        Notification::assertSentTo($user, ResetPassword::class, function (object $notification) use ($user) {
81
+        Notification::assertSentTo($user, ResetPasswordNotification::class, function (object $notification) use ($user) {
82
             $response = $this->post('/reset-password', [
82
             $response = $this->post('/reset-password', [
83
                 'token' => $notification->token,
83
                 'token' => $notification->token,
84
                 'email' => $user->email,
84
                 'email' => $user->email,
85
-                'password' => 'password',
86
-                'password_confirmation' => 'password',
85
+                'password' => 'Password1!',
86
+                'password_confirmation' => 'Password1!',
87
             ]);
87
             ]);
88
 
88
 
89
             $response->assertSessionHasNoErrors();
89
             $response->assertSessionHasNoErrors();

+ 2
- 2
tests/Feature/RegistrationTest.php Просмотреть файл

42
         $response = $this->post('/register', [
42
         $response = $this->post('/register', [
43
             'name' => 'Test User',
43
             'name' => 'Test User',
44
             'email' => 'test@example.com',
44
             'email' => 'test@example.com',
45
-            'password' => 'password',
46
-            'password_confirmation' => 'password',
45
+            'password' => 'Password1!',
46
+            'password_confirmation' => 'Password1!',
47
             'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
47
             'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
48
         ]);
48
         ]);
49
 
49
 

+ 6
- 6
tests/Feature/UpdatePasswordTest.php Просмотреть файл

20
         Livewire::test(UpdatePasswordForm::class)
20
         Livewire::test(UpdatePasswordForm::class)
21
             ->set('state', [
21
             ->set('state', [
22
                 'current_password' => 'password',
22
                 'current_password' => 'password',
23
-                'password' => 'new-password',
24
-                'password_confirmation' => 'new-password',
23
+                'password' => 'Password1!',
24
+                'password_confirmation' => 'Password1!',
25
             ])
25
             ])
26
             ->call('updatePassword');
26
             ->call('updatePassword');
27
 
27
 
28
-        $this->assertTrue(Hash::check('new-password', $user->fresh()->password));
28
+        $this->assertTrue(Hash::check('Password1!', $user->fresh()->password));
29
     }
29
     }
30
 
30
 
31
     public function test_current_password_must_be_correct(): void
31
     public function test_current_password_must_be_correct(): void
35
         Livewire::test(UpdatePasswordForm::class)
35
         Livewire::test(UpdatePasswordForm::class)
36
             ->set('state', [
36
             ->set('state', [
37
                 'current_password' => 'wrong-password',
37
                 'current_password' => 'wrong-password',
38
-                'password' => 'new-password',
39
-                'password_confirmation' => 'new-password',
38
+                'password' => 'Password1!',
39
+                'password_confirmation' => 'Password1!',
40
             ])
40
             ])
41
             ->call('updatePassword')
41
             ->call('updatePassword')
42
             ->assertHasErrors(['current_password']);
42
             ->assertHasErrors(['current_password']);
51
         Livewire::test(UpdatePasswordForm::class)
51
         Livewire::test(UpdatePasswordForm::class)
52
             ->set('state', [
52
             ->set('state', [
53
                 'current_password' => 'password',
53
                 'current_password' => 'password',
54
-                'password' => 'new-password',
54
+                'password' => 'Password1!',
55
                 'password_confirmation' => 'wrong-password',
55
                 'password_confirmation' => 'wrong-password',
56
             ])
56
             ])
57
             ->call('updatePassword')
57
             ->call('updatePassword')

+ 15
- 0
tests/Unit/PasswordRequirementsTest.php Просмотреть файл

1
+<?php
2
+
3
+namespace Tests\Unit;
4
+
5
+use App\Support\PasswordRequirements;
6
+use Tests\TestCase;
7
+
8
+class PasswordRequirementsTest extends TestCase
9
+{
10
+    public function test_hint_is_defined(): void
11
+    {
12
+        $this->assertNotEmpty(PasswordRequirements::HINT);
13
+        $this->assertStringContainsString('6 caratteri', PasswordRequirements::HINT);
14
+    }
15
+}

Загрузка…
Отмена
Сохранить