PasswordResetService.php 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <?php
  2. namespace App\Services;
  3. use App\Mail\PasswordResetCode;
  4. use App\Models\User;
  5. use App\Enums\UserTypeEnum;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Hash;
  8. use Illuminate\Support\Facades\Mail;
  9. use Carbon\Carbon;
  10. class PasswordResetService
  11. {
  12. private const CODE_TTL_MINUTES = 15;
  13. public function sendCode(string $email, string $tipo): bool
  14. {
  15. $user = User::where('email', $email)->first();
  16. if (!$user || $user->type->value !== $tipo) {
  17. return false;
  18. }
  19. $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
  20. DB::table('password_reset_tokens')->updateOrInsert(
  21. ['email' => $email],
  22. [
  23. 'token' => Hash::make($code),
  24. 'created_at' => Carbon::now(),
  25. ]
  26. );
  27. Mail::to($email)->send(new PasswordResetCode($code, $user->name));
  28. return true;
  29. }
  30. public function verifyCode(string $email, string $code): bool
  31. {
  32. $record = DB::table('password_reset_tokens')
  33. ->where('email', $email)
  34. ->first();
  35. if (!$record) {
  36. return false;
  37. }
  38. if (Carbon::parse($record->created_at)->addMinutes(self::CODE_TTL_MINUTES)->isPast()) {
  39. return false;
  40. }
  41. return Hash::check($code, $record->token);
  42. }
  43. public function resetPassword(string $email, string $code, string $password): ?User
  44. {
  45. if (!$this->verifyCode($email, $code)) {
  46. return null;
  47. }
  48. $user = User::where('email', $email)->first();
  49. if (!$user) {
  50. return null;
  51. }
  52. $user->update(['password' => Hash::make($password)]);
  53. DB::table('password_reset_tokens')->where('email', $email)->delete();
  54. return $user;
  55. }
  56. }