diff --git a/docs/01-getting-started.md b/docs/01-getting-started.md index e96ba26151..5d82de72ef 100644 --- a/docs/01-getting-started.md +++ b/docs/01-getting-started.md @@ -96,6 +96,27 @@ public function isFilamentAdmin() } ``` +Finally, for the correct reset password URL to be sent, you should implement a `sendPasswordResetNotification($token)` function. You can use the `Filament\Models\Concerns\SendsFilamentPasswordResetNotification` trait to add this functionality to your User model, fully integrated with Filament: + +```php +sendResetLink($this->validate()); + // Use the `filament_users` broker only with the `filament` guard. + $broker = config('filament.auth.guard') === 'filament' ? 'filament_users' : null; + + $requestStatus = Password::broker($broker)->sendResetLink($this->validate()); if (Password::RESET_LINK_SENT !== $requestStatus) { $this->addError('email', __("filament::auth/request-password.messages.{$requestStatus}")); diff --git a/src/Http/Livewire/Auth/ResetPassword.php b/src/Http/Livewire/Auth/ResetPassword.php index 6fcb585969..426519d4bf 100644 --- a/src/Http/Livewire/Auth/ResetPassword.php +++ b/src/Http/Livewire/Auth/ResetPassword.php @@ -43,7 +43,10 @@ class ResetPassword extends Component { $this->validate(); - $resetStatus = Password::broker('filament_users') + // Use the `filament_users` broker only with the `filament` guard. + $broker = config('filament.auth.guard') === 'filament' ? 'filament_users' : null; + + $resetStatus = Password::broker($broker) ->reset( $this->only(['email', 'password', 'token']), function ($user, $password) { @@ -55,7 +58,7 @@ class ResetPassword extends Component ); if (Password::PASSWORD_RESET !== $resetStatus) { - $this->addError('email', __("filament::auth/request-password.messages.{$resetStatus}")); + $this->addError('email', __("filament::auth/reset-password.messages.{$resetStatus}")); return; } diff --git a/src/Models/Concerns/SendsFilamentPasswordResetNotification.php b/src/Models/Concerns/SendsFilamentPasswordResetNotification.php new file mode 100644 index 0000000000..23a3ff0e25 --- /dev/null +++ b/src/Models/Concerns/SendsFilamentPasswordResetNotification.php @@ -0,0 +1,26 @@ +createUrlUsing(function ($notifiable, $token) { + return URL::signedRoute( + 'filament.auth.password.reset', + [ + 'email' => $notifiable->getEmailForPasswordReset(), + 'token' => $token, + ], + now()->addMinutes(config('auth.passwords.filament_users.expire')), + ); + }); + + $this->notify($notification); + } +} diff --git a/src/Models/User.php b/src/Models/User.php index 1e3b67d966..47d68dbb2c 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -4,18 +4,18 @@ namespace Filament\Models; use Filament\Database\Factories\UserFactory; use Filament\Models\Concerns\IsFilamentUser; +use Filament\Models\Concerns\SendsFilamentPasswordResetNotification; use Filament\Models\Contracts\FilamentUser; -use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Illuminate\Support\Facades\URL; class User extends Authenticatable implements FilamentUser { use HasFactory; use IsFilamentUser; use Notifiable; + use SendsFilamentPasswordResetNotification; public static $filamentAdminColumn = 'is_admin'; @@ -37,23 +37,6 @@ class User extends Authenticatable implements FilamentUser protected $table = 'filament_users'; - public function sendPasswordResetNotification($token) - { - $notification = new ResetPasswordNotification($token); - $notification->createUrlUsing(function ($notifiable, $token) { - return URL::signedRoute( - 'filament.auth.password.reset', - [ - 'email' => $notifiable->getEmailForPasswordReset(), - 'token' => $token, - ], - now()->addMinutes(config('auth.passwords.filament_users.expire')), - ); - }); - - $this->notify($notification); - } - protected static function newFactory() { return UserFactory::new(); diff --git a/tests/Feature/Auth/RequestPasswordTest.php b/tests/Feature/Auth/RequestPasswordTest.php index 76fa7ba329..46cf11d426 100644 --- a/tests/Feature/Auth/RequestPasswordTest.php +++ b/tests/Feature/Auth/RequestPasswordTest.php @@ -6,6 +6,7 @@ use Filament\Http\Livewire\Auth\RequestPassword; use Filament\Models\User; use Filament\Tests\TestCase; use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Notification; use Livewire\Livewire; @@ -27,6 +28,15 @@ class RequestPasswordTest extends TestCase Notification::assertSentTo($user, ResetPasswordNotification::class); } + /** @test */ + public function can_request_password_reset_with_custom_user_model() + { + Config::set('filament.auth.guard', 'web'); + Config::set('auth.providers.users.model', User::class); + + $this->can_request_password_reset(); + } + /** @test */ public function can_view_password_reset_request_page() { diff --git a/tests/Feature/Auth/ResetPasswordTest.php b/tests/Feature/Auth/ResetPasswordTest.php index 3270517489..d07af07e8d 100644 --- a/tests/Feature/Auth/ResetPasswordTest.php +++ b/tests/Feature/Auth/ResetPasswordTest.php @@ -6,6 +6,7 @@ use Filament\Filament; use Filament\Http\Livewire\Auth\ResetPassword; use Filament\Models\User; use Filament\Tests\TestCase; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Password; use Illuminate\Support\Facades\URL; use Illuminate\Support\Str; @@ -29,7 +30,7 @@ class ResetPasswordTest extends TestCase ->assertHasNoErrors() ->assertRedirect(route('filament.dashboard')); - $this->assertAuthenticatedAs($user); + $this->assertAuthenticatedAs($user, config('filament.auth.guard')); $this->assertTrue(Filament::auth()->attempt([ 'email' => $user->email, @@ -37,6 +38,15 @@ class ResetPasswordTest extends TestCase ])); } + /** @test */ + public function can_reset_password_with_custom_user_model() + { + Config::set('filament.auth.guard', 'web'); + Config::set('auth.providers.users.model', User::class); + + $this->can_reset_password(); + } + /** @test */ public function can_view_password_reset_page() { @@ -137,6 +147,9 @@ class ResetPasswordTest extends TestCase $user = User::factory()->create(); } - return Password::broker('filament_users')->createToken($user); + // Use filament_users broker only when we're using filament guard. Otherwise, use Laravel's default + $broker = config('filament.auth.guard') === 'filament' ? 'filament_users' : null; + + return Password::broker($broker)->createToken($user); } }