Forgot password flow

This commit is contained in:
2026-07-27 09:43:00 -03:00
parent 7b565e7fa7
commit c37b8894e4
23 changed files with 1095 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Domains\Notification\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PasswordResetRequested
{
use Dispatchable, SerializesModels;
public function __construct(
public readonly int $attemptId,
public readonly string $tenantCode,
) {}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Domains\Notification\Listeners;
use App\Domains\Notification\Events\PasswordResetRequested;
use App\Domains\Notification\Services\NotificationMailService;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use Throwable;
class SendPasswordResetEmail implements ShouldQueueAfterCommit
{
use InteractsWithQueue;
public string $queue = 'emails';
public int $tries = 3;
/** @var array<int, int> */
public array $backoff = [30, 120, 300];
public function handle(PasswordResetRequested $event): void
{
try {
app(NotificationMailService::class)->sendPasswordResetCode(
$event->attemptId,
$event->tenantCode,
);
} catch (Throwable $exception) {
Log::error('Failed to send password reset email.', [
'attempt_id' => $event->attemptId,
'tenant_code' => $event->tenantCode,
'exception' => $exception,
]);
throw $exception;
}
}
}

View File

@@ -2,12 +2,14 @@
namespace App\Domains\Notification\Services;
use App\Domains\Auth\Models\ResetPasswordAttempt;
use App\Domains\Auth\Models\User;
use App\Domains\Integration\Services\MailService;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Models\Ticket;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class NotificationMailService
{
@@ -29,6 +31,32 @@ class NotificationMailService
);
}
public function sendPasswordResetCode(int $attemptId, string $tenantCode): void
{
$tenant = Tenant::query()->where('codigo', $tenantCode)->firstOrFail();
$attempt = ResetPasswordAttempt::query()
->with('user')
->findOrFail($attemptId);
if ($attempt->status !== ResetPasswordAttempt::STATUS_PENDING) {
Log::warning('Password reset email was skipped because the attempt is no longer pending.', [
'attempt_id' => $attemptId,
'tenant_code' => $tenantCode,
'attempt_status' => $attempt->status,
]);
return;
}
$this->mailService
->forTenant($tenantCode)
->send(
$attempt->user->email,
"Código para recuperar tu contraseña - {$tenant->nombre}",
view('mail.notifications.password-reset', compact('tenant', 'attempt'))->render(),
);
}
public function sendPurchasePaid(int $purchaseId): void
{
$purchase = Purchase::query()