From 5710fdb8bf36df501405c705f7d2ea4720d2b9d3 Mon Sep 17 00:00:00 2001
From: Matt Jones <msjwozere@gmail.com>
Date: Mon, 6 May 2024 19:51:32 +0100
Subject: [PATCH] [11.x] Adding PasswordResetLinkSent event (#51253)

* Adding PasswordResetLinkSent event

* formatting

* formatting

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
---
 .../Auth/Events/PasswordResetLinkSent.php     | 28 +++++++++++++++++++
 .../Auth/Passwords/PasswordBroker.php         | 17 ++++++++++-
 .../Auth/Passwords/PasswordBrokerManager.php  |  3 +-
 tests/Integration/Auth/ForgotPasswordTest.php | 21 ++++++++++++++
 4 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100644 src/Illuminate/Auth/Events/PasswordResetLinkSent.php

diff --git a/src/Illuminate/Auth/Events/PasswordResetLinkSent.php b/src/Illuminate/Auth/Events/PasswordResetLinkSent.php
new file mode 100644
index 000000000000..233e92db34fd
--- /dev/null
+++ b/src/Illuminate/Auth/Events/PasswordResetLinkSent.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Illuminate\Auth\Events;
+
+use Illuminate\Queue\SerializesModels;
+
+class PasswordResetLinkSent
+{
+    use SerializesModels;
+
+    /**
+     * The user instance.
+     *
+     * @var \Illuminate\Contracts\Auth\CanResetPassword
+     */
+    public $user;
+
+    /**
+     * Create a new event instance.
+     *
+     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
+     * @return void
+     */
+    public function __construct($user)
+    {
+        $this->user = $user;
+    }
+}
diff --git a/src/Illuminate/Auth/Passwords/PasswordBroker.php b/src/Illuminate/Auth/Passwords/PasswordBroker.php
index eb213c498876..5f99fa3e00be 100755
--- a/src/Illuminate/Auth/Passwords/PasswordBroker.php
+++ b/src/Illuminate/Auth/Passwords/PasswordBroker.php
@@ -3,9 +3,11 @@
 namespace Illuminate\Auth\Passwords;
 
 use Closure;
+use Illuminate\Auth\Events\PasswordResetLinkSent;
 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
 use Illuminate\Contracts\Auth\PasswordBroker as PasswordBrokerContract;
 use Illuminate\Contracts\Auth\UserProvider;
+use Illuminate\Contracts\Events\Dispatcher;
 use Illuminate\Support\Arr;
 use UnexpectedValueException;
 
@@ -25,17 +27,26 @@ class PasswordBroker implements PasswordBrokerContract
      */
     protected $users;
 
+    /**
+     * The event dispatcher instance.
+     *
+     * @var \Illuminate\Contracts\Events\Dispatcher
+     */
+    protected $events;
+
     /**
      * Create a new password broker instance.
      *
      * @param  \Illuminate\Auth\Passwords\TokenRepositoryInterface  $tokens
      * @param  \Illuminate\Contracts\Auth\UserProvider  $users
+     * @param  \Illuminate\Contracts\Events\Dispatcher  $users
      * @return void
      */
-    public function __construct(TokenRepositoryInterface $tokens, UserProvider $users)
+    public function __construct(TokenRepositoryInterface $tokens, UserProvider $users, ?Dispatcher $dispatcher = null)
     {
         $this->users = $users;
         $this->tokens = $tokens;
+        $this->events = $dispatcher;
     }
 
     /**
@@ -71,6 +82,10 @@ public function sendResetLink(array $credentials, ?Closure $callback = null)
         // the current URI having nothing set in the session to indicate errors.
         $user->sendPasswordResetNotification($token);
 
+        if ($this->events) {
+            $this->events->dispatch(new PasswordResetLinkSent($user));
+        }
+
         return static::RESET_LINK_SENT;
     }
 
diff --git a/src/Illuminate/Auth/Passwords/PasswordBrokerManager.php b/src/Illuminate/Auth/Passwords/PasswordBrokerManager.php
index 5c80dcf3499a..e11e44499894 100644
--- a/src/Illuminate/Auth/Passwords/PasswordBrokerManager.php
+++ b/src/Illuminate/Auth/Passwords/PasswordBrokerManager.php
@@ -69,7 +69,8 @@ protected function resolve($name)
         // aggregate service of sorts providing a convenient interface for resets.
         return new PasswordBroker(
             $this->createTokenRepository($config),
-            $this->app['auth']->createUserProvider($config['provider'] ?? null)
+            $this->app['auth']->createUserProvider($config['provider'] ?? null),
+            $this->app['events'] ?? null,
         );
     }
 
diff --git a/tests/Integration/Auth/ForgotPasswordTest.php b/tests/Integration/Auth/ForgotPasswordTest.php
index 1bdee928b130..3d38f74179ea 100644
--- a/tests/Integration/Auth/ForgotPasswordTest.php
+++ b/tests/Integration/Auth/ForgotPasswordTest.php
@@ -2,9 +2,11 @@
 
 namespace Illuminate\Tests\Integration\Auth;
 
+use Illuminate\Auth\Events\PasswordResetLinkSent;
 use Illuminate\Auth\Notifications\ResetPassword;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Support\Facades\Event;
 use Illuminate\Support\Facades\Notification;
 use Illuminate\Support\Facades\Password;
 use Illuminate\Support\Str;
@@ -66,6 +68,25 @@ function (ResetPassword $notification, $channels) use ($user) {
         );
     }
 
+    public function testItCanTriggerPasswordResetSentEvent()
+    {
+        Event::fake([PasswordResetLinkSent::class]);
+
+        UserFactory::new()->create();
+
+        $user = AuthenticationTestUser::first();
+
+        Password::broker()->sendResetLink([
+            'email' => $user->email,
+        ]);
+
+        Event::assertDispatched(PasswordResetLinkSent::class, function ($event) {
+            $this->assertEquals(1, $event->user->id);
+
+            return true;
+        });
+    }
+
     public function testItCanSendForgotPasswordEmailViaCreateUrlUsing()
     {
         Notification::fake();