diff --git a/be/app/Http/Controllers/UserController.php b/be/app/Http/Controllers/UserController.php index f36fe17..edfe616 100644 --- a/be/app/Http/Controllers/UserController.php +++ b/be/app/Http/Controllers/UserController.php @@ -3,32 +3,59 @@ namespace App\Http\Controllers; use App\Http\Resources\UserResource; +use App\Mail\PasswordReset; use App\Models\User; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Validator; -class UserController extends Controller -{ - public function update($id, Request $request) - { +class UserController extends Controller { + public function update( $id, Request $request ) { - $validator = Validator::make($request->all(), [ + $validator = Validator::make( $request->all(), [ 'data.work_start' => 'required', - 'data.work_end' => 'required', - ]); + 'data.work_end' => 'required', + ] ); - if($validator->fails()){ - return response()->json($validator->errors(), 400); + if ( $validator->fails() ) { + return response()->json( $validator->errors(), 400 ); } - $user = User::find($id); + $user = User::find( $id ); - $user->update($request->all()['data']); + $user->update( $request->all()['data'] ); - return response()->json([ + return response()->json( [ 'message' => 'User updated successfully', - 'user' => new UserResource($user) - ], 201); + 'user' => new UserResource( $user ) + ], 201 ); + } + + public function sendPasswordResetLink( Request $request ) { + $user = User::where( 'email', $request->all()['data']['email'] )->first(); + + if ( ! $user ) { + return response()->json( [ + 'message' => 'User not found.', + ], 400 ); + } + + $token = $user->createToken( 'password-reset', [ 'password-reset' ] )->plainTextToken; + $url = env( 'APP_URL_FE' ) . '#/auth/reset-password?token=' . $token . '&email=' . $user->email; + + Mail::to( 'michal.feher@gmail.com' )->send( new PasswordReset( $url ) ); + + return [ 'message' => 'Email sent.' ]; + } + + public function resetPassword( Request $request ) + { + $userId = User::getUserIdFromBearerToken($request->bearerToken()); + + User::find($userId)->update(['password' => Hash::make($request->all()['data']['password'])]); + + return [ 'message' => 'Password changed.' ]; } } diff --git a/be/app/Http/Kernel.php b/be/app/Http/Kernel.php index 9cf5f01..7911e07 100644 --- a/be/app/Http/Kernel.php +++ b/be/app/Http/Kernel.php @@ -63,5 +63,7 @@ class Kernel extends HttpKernel 'signed' => \App\Http\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class, + 'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class, ]; } diff --git a/be/app/Mail/PasswordReset.php b/be/app/Mail/PasswordReset.php new file mode 100644 index 0000000..c4fa59f --- /dev/null +++ b/be/app/Mail/PasswordReset.php @@ -0,0 +1,61 @@ +url = $url; + } + + /** + * Get the message envelope. + * + * @return \Illuminate\Mail\Mailables\Envelope + */ + public function envelope() + { + return new Envelope( + subject: 'Password Reset', + ); + } + + /** + * Get the message content definition. + * + * @return \Illuminate\Mail\Mailables\Content + */ + public function content() + { + return new Content( + view: 'emails.password.reset', + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments() + { + return []; + } +} diff --git a/be/app/Models/User.php b/be/app/Models/User.php index 93469e2..921c465 100644 --- a/be/app/Models/User.php +++ b/be/app/Models/User.php @@ -2,9 +2,12 @@ namespace App\Models; +use App\Mail\PasswordReset; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; +use Illuminate\Http\Request; use Illuminate\Notifications\Notifiable; +use Illuminate\Support\Facades\Mail; use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\PersonalAccessToken; @@ -58,5 +61,4 @@ class User extends Authenticatable return $token->tokenable_id; } - } diff --git a/be/resources/views/emails/password/reset.blade.php b/be/resources/views/emails/password/reset.blade.php new file mode 100644 index 0000000..1c9c505 --- /dev/null +++ b/be/resources/views/emails/password/reset.blade.php @@ -0,0 +1 @@ +Click here for resetting your password. diff --git a/be/routes/api.php b/be/routes/api.php index de61fd1..fc49363 100644 --- a/be/routes/api.php +++ b/be/routes/api.php @@ -35,7 +35,7 @@ use Illuminate\Http\Request; | */ -Route::middleware(['auth:sanctum'])->group(function () { +Route::middleware(['auth:sanctum', 'abilities:full-access'])->group(function () { Route::get('/user', function (Request $request) { return $request->user(); }); @@ -105,10 +105,23 @@ Route::middleware(['auth:sanctum'])->group(function () { Route::put('/v1/users/{id}', UserController::class . '@update'); }); +Route::middleware(['auth:sanctum', 'abilities:password-reset'])->group(function () { + Route::post('/v1/users/reset', UserController::class . '@resetPassword'); +}); + +Route::post('/v1/users/forgot', UserController::class . '@sendPasswordResetLink'); + + Route::post('/v1/tokens/create', function (Request $request) { $user = User::where('email', $request->all()['data']['email'])->first(); - $token = $user->createToken($user->email . '-' . now()); + if (!$user) + return response()->json(['message' => 'E-mail address doesnt exist.'], 401); + + if (! Hash::check($request->all()['data']['password'], $user->password)) + return response()->json(['message' => 'Incorrect password.'], 401); + + $token = $user->createToken($user->email . '-' . now(), ['full-access']); return ['token' => $token->plainTextToken, 'user' => new UserResource($user)]; });