Skip to content

Commit 6fd4567

Browse files
authored
✨ Mis en place de la fonctionnalite de rappel et reinitialisation du mot de passe (#74)
1 parent b8870b6 commit 6fd4567

11 files changed

+200
-31
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ APP_ENV=local
33
APP_KEY=
44
APP_DEBUG=true
55
APP_URL=http://laravel.cm.test
6+
FRONTEND_APP_URL=http://localhost::4200
67

78
LOG_CHANNEL=stack
89
LOG_LEVEL=debug
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Api\Auth;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Http\Requests\Api\ForgotPasswordRequest;
7+
use Illuminate\Http\JsonResponse;
8+
use Illuminate\Support\Facades\Password;
9+
10+
class ForgotPasswordController extends Controller
11+
{
12+
public function __invoke(ForgotPasswordRequest $request): JsonResponse
13+
{
14+
$status = Password::sendResetLink(
15+
$request->only('email')
16+
);
17+
18+
return $status === Password::RESET_LINK_SENT
19+
? response()->json(['message' => __('L\'e-mail de réinitialisation du mot de passe a été envoyé avec succès !')])
20+
: response()->json(['error' => __('Un courriel ne pourrait être envoyé à cette adresse électronique !')], 401);
21+
}
22+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Api\Auth;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Http\Requests\Api\ResetPasswordRequest;
7+
use Illuminate\Auth\Events\PasswordReset;
8+
use Illuminate\Http\JsonResponse;
9+
use Illuminate\Support\Facades\Hash;
10+
use Illuminate\Support\Facades\Password;
11+
use Illuminate\Support\Str;
12+
13+
class ResetPasswordController extends Controller
14+
{
15+
public function __invoke(ResetPasswordRequest $request): JsonResponse
16+
{
17+
$status = Password::reset(
18+
$request->only('email', 'password', 'password_confirmation', 'token'),
19+
function ($user) use ($request) {
20+
$user->forceFill([
21+
'password' => Hash::make($request->password),
22+
'remember_token' => Str::random(60),
23+
])->save();
24+
25+
event(new PasswordReset($user));
26+
}
27+
);
28+
29+
return $status === Password::PASSWORD_RESET
30+
? response()->json(['message' => __('Votre mot de passe a été réinitialisé avec succès !')])
31+
: response()->json(['error' => __('Le jeton de réinitialisation du mot de passe est invalide !')], 401);
32+
}
33+
}

app/Http/Controllers/Api/Auth/VerifyEmailController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ public function verify(Request $request): RedirectResponse
1717
$user = User::find($request->route('id'));
1818

1919
if ($user->hasVerifiedEmail()) {
20-
return redirect(env('FRONTEND_APP_URL') . '/email/verify/already-success');
20+
return redirect(config('lcm.spa_url') . '/email/verify/already');
2121
}
2222

2323
if ($user->markEmailAsVerified()) {
2424
event(new Verified($user));
2525
}
2626

27-
return redirect(env('FRONTEND_APP_URL') . '/email/verify/success');
27+
return redirect(config('lcm.spa_url') . '/email/verify/success');
2828
}
2929

3030
public function resend(Request $request): JsonResponse
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace App\Http\Requests\Api;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class ForgotPasswordRequest extends FormRequest
8+
{
9+
/**
10+
* Determine if the user is authorized to make this request.
11+
*
12+
* @return bool
13+
*/
14+
public function authorize(): bool
15+
{
16+
return true;
17+
}
18+
19+
/**
20+
* Get the validation rules that apply to the request.
21+
*
22+
* @return array<string, mixed>
23+
*/
24+
public function rules(): array
25+
{
26+
return [
27+
'email' => 'required|email|exists:users,email',
28+
];
29+
}
30+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Http\Requests\Api;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
use Illuminate\Validation\Rules\Password;
7+
8+
class ResetPasswordRequest extends FormRequest
9+
{
10+
/**
11+
* Determine if the user is authorized to make this request.
12+
*
13+
* @return bool
14+
*/
15+
public function authorize(): bool
16+
{
17+
return true;
18+
}
19+
20+
/**
21+
* Get the validation rules that apply to the request.
22+
*
23+
* @return array<string, mixed>
24+
*/
25+
public function rules(): array
26+
{
27+
return [
28+
'token' => 'required',
29+
'email' => ['required', 'email', 'exists:users,email'],
30+
'password' => [
31+
'required',
32+
'confirmed',
33+
app()->environment('local')
34+
? Password::min(8)
35+
: Password::min(8)->mixedCase()->numbers()->symbols(),
36+
],
37+
];
38+
}
39+
}

app/Providers/AuthServiceProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use App\Policies\NotificationPolicy;
1212
use App\Policies\ReplyPolicy;
1313
use App\Policies\ThreadPolicy;
14+
use Illuminate\Auth\Notifications\ResetPassword;
1415
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
1516
use Illuminate\Notifications\DatabaseNotification as Notification;
1617
use Illuminate\Support\Facades\Gate;
@@ -34,6 +35,10 @@ public function boot(): void
3435
{
3536
$this->registerPolicies();
3637

38+
ResetPassword::createUrlUsing(function ($user, string $token) {
39+
return config('lcm.spa_url').'/auth/password/reset?token='.$token;
40+
});
41+
3742
Gate::before(function ($user) {
3843
return $user->hasRole('admin') ? true : null;
3944
});

config/lcm.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@
2323
'token' => env('SLACK_API_TOKEN', null),
2424
],
2525

26+
'spa_url' => env('FRONTEND_APP_URL', 'http://localhost:4200'),
27+
2628
];

resources/lang/en/validation.php

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
'accepted' => 'The :attribute must be accepted.',
17+
'accepted_if' => 'The :attribute must be accepted when :other is :value.',
1718
'active_url' => 'The :attribute is not a valid URL.',
1819
'after' => 'The :attribute must be a date after :date.',
1920
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
@@ -24,37 +25,43 @@
2425
'before' => 'The :attribute must be a date before :date.',
2526
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
2627
'between' => [
27-
'numeric' => 'The :attribute must be between :min and :max.',
28+
'array' => 'The :attribute must have between :min and :max items.',
2829
'file' => 'The :attribute must be between :min and :max kilobytes.',
30+
'numeric' => 'The :attribute must be between :min and :max.',
2931
'string' => 'The :attribute must be between :min and :max characters.',
30-
'array' => 'The :attribute must have between :min and :max items.',
3132
],
3233
'boolean' => 'The :attribute field must be true or false.',
3334
'confirmed' => 'The :attribute confirmation does not match.',
35+
'current_password' => 'The password is incorrect.',
3436
'date' => 'The :attribute is not a valid date.',
3537
'date_equals' => 'The :attribute must be a date equal to :date.',
3638
'date_format' => 'The :attribute does not match the format :format.',
39+
'declined' => 'The :attribute must be declined.',
40+
'declined_if' => 'The :attribute must be declined when :other is :value.',
3741
'different' => 'The :attribute and :other must be different.',
3842
'digits' => 'The :attribute must be :digits digits.',
3943
'digits_between' => 'The :attribute must be between :min and :max digits.',
4044
'dimensions' => 'The :attribute has invalid image dimensions.',
4145
'distinct' => 'The :attribute field has a duplicate value.',
46+
'doesnt_end_with' => 'The :attribute may not end with one of the following: :values.',
47+
'doesnt_start_with' => 'The :attribute may not start with one of the following: :values.',
4248
'email' => 'The :attribute must be a valid email address.',
4349
'ends_with' => 'The :attribute must end with one of the following: :values.',
50+
'enum' => 'The selected :attribute is invalid.',
4451
'exists' => 'The selected :attribute is invalid.',
4552
'file' => 'The :attribute must be a file.',
4653
'filled' => 'The :attribute field must have a value.',
4754
'gt' => [
48-
'numeric' => 'The :attribute must be greater than :value.',
55+
'array' => 'The :attribute must have more than :value items.',
4956
'file' => 'The :attribute must be greater than :value kilobytes.',
57+
'numeric' => 'The :attribute must be greater than :value.',
5058
'string' => 'The :attribute must be greater than :value characters.',
51-
'array' => 'The :attribute must have more than :value items.',
5259
],
5360
'gte' => [
54-
'numeric' => 'The :attribute must be greater than or equal :value.',
55-
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
56-
'string' => 'The :attribute must be greater than or equal :value characters.',
5761
'array' => 'The :attribute must have :value items or more.',
62+
'file' => 'The :attribute must be greater than or equal to :value kilobytes.',
63+
'numeric' => 'The :attribute must be greater than or equal to :value.',
64+
'string' => 'The :attribute must be greater than or equal to :value characters.',
5865
],
5966
'image' => 'The :attribute must be an image.',
6067
'in' => 'The selected :attribute is invalid.',
@@ -64,62 +71,75 @@
6471
'ipv4' => 'The :attribute must be a valid IPv4 address.',
6572
'ipv6' => 'The :attribute must be a valid IPv6 address.',
6673
'json' => 'The :attribute must be a valid JSON string.',
74+
'lowercase' => 'The :attribute must be lowercase.',
6775
'lt' => [
68-
'numeric' => 'The :attribute must be less than :value.',
76+
'array' => 'The :attribute must have less than :value items.',
6977
'file' => 'The :attribute must be less than :value kilobytes.',
78+
'numeric' => 'The :attribute must be less than :value.',
7079
'string' => 'The :attribute must be less than :value characters.',
71-
'array' => 'The :attribute must have less than :value items.',
7280
],
7381
'lte' => [
74-
'numeric' => 'The :attribute must be less than or equal :value.',
75-
'file' => 'The :attribute must be less than or equal :value kilobytes.',
76-
'string' => 'The :attribute must be less than or equal :value characters.',
7782
'array' => 'The :attribute must not have more than :value items.',
83+
'file' => 'The :attribute must be less than or equal to :value kilobytes.',
84+
'numeric' => 'The :attribute must be less than or equal to :value.',
85+
'string' => 'The :attribute must be less than or equal to :value characters.',
7886
],
87+
'mac_address' => 'The :attribute must be a valid MAC address.',
7988
'max' => [
80-
'numeric' => 'The :attribute must not be greater than :max.',
89+
'array' => 'The :attribute must not have more than :max items.',
8190
'file' => 'The :attribute must not be greater than :max kilobytes.',
91+
'numeric' => 'The :attribute must not be greater than :max.',
8292
'string' => 'The :attribute must not be greater than :max characters.',
83-
'array' => 'The :attribute must not have more than :max items.',
8493
],
94+
'max_digits' => 'The :attribute must not have more than :max digits.',
8595
'mimes' => 'The :attribute must be a file of type: :values.',
8696
'mimetypes' => 'The :attribute must be a file of type: :values.',
8797
'min' => [
88-
'numeric' => 'The :attribute must be at least :min.',
98+
'array' => 'The :attribute must have at least :min items.',
8999
'file' => 'The :attribute must be at least :min kilobytes.',
100+
'numeric' => 'The :attribute must be at least :min.',
90101
'string' => 'The :attribute must be at least :min characters.',
91-
'array' => 'The :attribute must have at least :min items.',
92102
],
103+
'min_digits' => 'The :attribute must have at least :min digits.',
93104
'multiple_of' => 'The :attribute must be a multiple of :value.',
94105
'not_in' => 'The selected :attribute is invalid.',
95106
'not_regex' => 'The :attribute format is invalid.',
96107
'numeric' => 'The :attribute must be a number.',
97-
'password' => 'The password is incorrect.',
108+
'password' => [
109+
'letters' => 'The :attribute must contain at least one letter.',
110+
'mixed' => 'The :attribute must contain at least one uppercase and one lowercase letter.',
111+
'numbers' => 'The :attribute must contain at least one number.',
112+
'symbols' => 'The :attribute must contain at least one symbol.',
113+
'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
114+
],
98115
'present' => 'The :attribute field must be present.',
116+
'prohibited' => 'The :attribute field is prohibited.',
117+
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
118+
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
119+
'prohibits' => 'The :attribute field prohibits :other from being present.',
99120
'regex' => 'The :attribute format is invalid.',
100121
'required' => 'The :attribute field is required.',
122+
'required_array_keys' => 'The :attribute field must contain entries for: :values.',
101123
'required_if' => 'The :attribute field is required when :other is :value.',
124+
'required_if_accepted' => 'The :attribute field is required when :other is accepted.',
102125
'required_unless' => 'The :attribute field is required unless :other is in :values.',
103126
'required_with' => 'The :attribute field is required when :values is present.',
104127
'required_with_all' => 'The :attribute field is required when :values are present.',
105128
'required_without' => 'The :attribute field is required when :values is not present.',
106129
'required_without_all' => 'The :attribute field is required when none of :values are present.',
107-
'prohibited' => 'The :attribute field is prohibited.',
108-
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
109-
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
110130
'same' => 'The :attribute and :other must match.',
111131
'size' => [
112-
'numeric' => 'The :attribute must be :size.',
132+
'array' => 'The :attribute must contain :size items.',
113133
'file' => 'The :attribute must be :size kilobytes.',
134+
'numeric' => 'The :attribute must be :size.',
114135
'string' => 'The :attribute must be :size characters.',
115-
'array' => 'The :attribute must contain :size items.',
116136
],
117137
'starts_with' => 'The :attribute must start with one of the following: :values.',
118138
'string' => 'The :attribute must be a string.',
119-
'timezone' => 'The :attribute must be a valid zone.',
139+
'timezone' => 'The :attribute must be a valid timezone.',
120140
'unique' => 'The :attribute has already been taken.',
121141
'uploaded' => 'The :attribute failed to upload.',
122-
'url' => 'The :attribute format is invalid.',
142+
'url' => 'The :attribute must be a valid URL.',
123143
'uuid' => 'The :attribute must be a valid UUID.',
124144

125145
/*

resources/lang/fr/validation.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,27 @@
2525
'before' => 'Le champ :attribute doit être une date antérieure au :date.',
2626
'before_or_equal' => 'Le champ :attribute doit être une date antérieure ou égale au :date.',
2727
'between' => [
28-
'array' => 'Le tableau :attribute doit contenir entre :min et :max éléments.',
29-
'file' => 'La taille du fichier de :attribute doit être comprise entre :min et :max kilo-octets.',
30-
'numeric' => 'La valeur de :attribute doit être comprise entre :min et :max.',
31-
'string' => 'Le texte :attribute doit contenir entre :min et :max caractères.',
28+
'array' => 'The :attribute must have between :min and :max items.',
29+
'file' => 'The :attribute must be between :min and :max kilobytes.',
30+
'numeric' => 'The :attribute must be between :min and :max.',
31+
'string' => 'The :attribute must be between :min and :max characters.',
3232
],
3333
'boolean' => 'Le champ :attribute doit être vrai ou faux.',
3434
'confirmed' => 'Le champ de confirmation :attribute ne correspond pas.',
35+
'current_password' => 'Le mot de passe est incorrect.',
3536
'date' => 'Le champ :attribute n\'est pas une date valide.',
3637
'date_equals' => 'Le champ :attribute doit être une date égale à :date.',
3738
'date_format' => 'Le champ :attribute ne correspond pas au format :format.',
39+
'declined' => 'Le champ :attribute doit être refusé.',
40+
'declined_if' => 'Le champ :attribute doit être décliné lorsque :other est :value.',
3841
'different' => 'Les champs :attribute et :other doivent être différents.',
3942
'digits' => 'Le champ :attribute doit contenir :digits chiffres.',
4043
'digits_between' => 'Le champ :attribute doit contenir entre :min et :max chiffres.',
4144
'dimensions' => 'La taille de l\'image :attribute n\'est pas conforme.',
4245
'distinct' => 'Le champ :attribute a une valeur en double.',
4346
'email' => 'Le champ :attribute doit être une adresse email valide.',
4447
'ends_with' => 'Le champ :attribute doit se terminer par une des valeurs suivantes : :values',
48+
'enum' => 'Le champ :attribute sélectionné n\'est pas valide.',
4549
'exists' => 'Le champ :attribute sélectionné est invalide.',
4650
'file' => 'Le champ :attribute doit être un fichier.',
4751
'filled' => 'Le champ :attribute doit avoir une valeur.',
@@ -65,6 +69,7 @@
6569
'ipv4' => 'Le champ :attribute doit être une adresse IPv4 valide.',
6670
'ipv6' => 'Le champ :attribute doit être une adresse IPv6 valide.',
6771
'json' => 'Le champ :attribute doit être un document JSON valide.',
72+
'lowercase' => 'The :attribute must be lowercase.',
6873
'lt' => [
6974
'array' => 'Le tableau :attribute doit contenir moins de :value éléments.',
7075
'file' => 'La taille du fichier de :attribute doit être inférieure à :value kilo-octets.',
@@ -95,7 +100,13 @@
95100
'not_in' => 'Le champ :attribute sélectionné n\'est pas valide.',
96101
'not_regex' => 'Le format du champ :attribute n\'est pas valide.',
97102
'numeric' => 'Le champ :attribute doit contenir un nombre.',
98-
'password' => 'Le mot de passe est incorrect',
103+
'password' => [
104+
'letters' => 'Le champ :attribute doit contenir au moins une lettre.',
105+
'mixed' => 'Le champ :attribute doit contenir au moins une lettre majuscule et une lettre minuscule.',
106+
'numbers' => 'Le champ :attribute doit contenir au moins un chiffre.',
107+
'symbols' => 'Le champ :attribute doit contenir au moins un symbole.',
108+
'uncompromised' => 'Le champ :attribute donné est apparu dans une fuite de données. Veuillez choisir un autre :attribut.',
109+
],
99110
'present' => 'Le champ :attribute doit être présent.',
100111
'prohibited' => 'Le champ :attribute est interdit.',
101112
'prohibited_if' => 'Le champ :attribute est interdit quand :other a la valeur :value.',

0 commit comments

Comments
 (0)