mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Merge pull request #16230 from robinmalburn/fix.passwordResetPanelAccess
Gate password reset process with canAccessPanel logic
This commit is contained in:
@@ -32,6 +32,10 @@ return [
|
||||
|
||||
'notifications' => [
|
||||
|
||||
'sent' => [
|
||||
'body' => 'If your account doesn\'t exist, you will not receive the email.',
|
||||
],
|
||||
|
||||
'throttled' => [
|
||||
'title' => 'Too many requests',
|
||||
'body' => 'Please try again in :seconds seconds.',
|
||||
|
||||
@@ -11,6 +11,7 @@ use Filament\Facades\Filament;
|
||||
use Filament\Forms\Components\Component;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Notifications\Auth\ResetPassword as ResetPasswordNotification;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Concerns\InteractsWithFormActions;
|
||||
@@ -62,6 +63,13 @@ class RequestPasswordReset extends SimplePage
|
||||
$status = Password::broker(Filament::getAuthPasswordBroker())->sendResetLink(
|
||||
$this->getCredentialsFromFormData($data),
|
||||
function (CanResetPassword $user, string $token): void {
|
||||
if (
|
||||
($user instanceof FilamentUser) &&
|
||||
(! $user->canAccessPanel(Filament::getCurrentPanel()))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! method_exists($user, 'notify')) {
|
||||
$userClass = $user::class;
|
||||
|
||||
@@ -111,6 +119,7 @@ class RequestPasswordReset extends SimplePage
|
||||
{
|
||||
return Notification::make()
|
||||
->title(__($status))
|
||||
->body(($status === Password::RESET_LINK_SENT) ? __('filament-panels::pages/auth/password-reset/request-password-reset.notifications.sent.body') : null)
|
||||
->success();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use Filament\Forms\Components\Component;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Http\Responses\Auth\Contracts\PasswordResetResponse;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Concerns\InteractsWithFormActions;
|
||||
use Filament\Pages\SimplePage;
|
||||
@@ -76,18 +77,33 @@ class ResetPassword extends SimplePage
|
||||
$data['email'] = $this->email;
|
||||
$data['token'] = $this->token;
|
||||
|
||||
$hasPanelAccess = true;
|
||||
|
||||
$status = Password::broker(Filament::getAuthPasswordBroker())->reset(
|
||||
$this->getCredentialsFromFormData($data),
|
||||
function (CanResetPassword | Model | Authenticatable $user) use ($data) {
|
||||
function (CanResetPassword | Model | Authenticatable $user) use ($data, &$hasPanelAccess) {
|
||||
if (
|
||||
($user instanceof FilamentUser) &&
|
||||
(! $user->canAccessPanel(Filament::getCurrentPanel()))
|
||||
) {
|
||||
$hasPanelAccess = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($data['password']),
|
||||
'remember_token' => Str::random(60),
|
||||
])->save();
|
||||
|
||||
event(new PasswordReset($user));
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if ($hasPanelAccess === false) {
|
||||
$status = Password::INVALID_USER;
|
||||
}
|
||||
|
||||
if ($status === Password::PASSWORD_RESET) {
|
||||
Notification::make()
|
||||
->title(__($status))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Notifications\Auth\ResetPassword;
|
||||
use Filament\Notifications\Notification as FilamentNotification;
|
||||
use Filament\Pages\Auth\PasswordReset\RequestPasswordReset;
|
||||
use Filament\Tests\Models\User;
|
||||
use Filament\Tests\TestCase;
|
||||
@@ -39,11 +40,40 @@ it('can request password reset', function () {
|
||||
'email' => $userToResetPassword->email,
|
||||
])
|
||||
->call('request')
|
||||
->assertNotified();
|
||||
->assertNotified(
|
||||
FilamentNotification::make()
|
||||
->success()
|
||||
->title(__('passwords.sent'))
|
||||
->body(__('filament-panels::pages/auth/password-reset/request-password-reset.notifications.sent.body'))
|
||||
);
|
||||
|
||||
Notification::assertSentTo($userToResetPassword, ResetPassword::class);
|
||||
});
|
||||
|
||||
it('cannot request password reset without panel access', function () {
|
||||
Notification::fake();
|
||||
|
||||
$this->assertGuest();
|
||||
|
||||
$userToResetPassword = User::factory()->create();
|
||||
|
||||
Filament::setCurrentPanel(Filament::getPanel('custom'));
|
||||
|
||||
livewire(RequestPasswordReset::class)
|
||||
->fillForm([
|
||||
'email' => $userToResetPassword->email,
|
||||
])
|
||||
->call('request')
|
||||
->assertNotified(
|
||||
FilamentNotification::make()
|
||||
->success()
|
||||
->title(__('passwords.sent'))
|
||||
->body(__('filament-panels::pages/auth/password-reset/request-password-reset.notifications.sent.body'))
|
||||
);
|
||||
|
||||
Notification::assertNotSentTo($userToResetPassword, ResetPassword::class);
|
||||
});
|
||||
|
||||
it('can throttle requests', function () {
|
||||
Notification::fake();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Auth\PasswordReset\ResetPassword;
|
||||
use Filament\Tests\Models\User;
|
||||
use Filament\Tests\TestCase;
|
||||
@@ -58,7 +59,11 @@ it('can reset password', function () {
|
||||
->set('password', 'new-password')
|
||||
->set('passwordConfirmation', 'new-password')
|
||||
->call('resetPassword')
|
||||
->assertNotified()
|
||||
->assertNotified(
|
||||
Notification::make()
|
||||
->success()
|
||||
->title(__('passwords.reset'))
|
||||
)
|
||||
->assertRedirect(Filament::getLoginUrl());
|
||||
|
||||
Event::assertDispatched(PasswordReset::class);
|
||||
@@ -69,6 +74,37 @@ it('can reset password', function () {
|
||||
]);
|
||||
});
|
||||
|
||||
it('cannot reset password without panel access', function () {
|
||||
Event::fake();
|
||||
|
||||
$this->assertGuest();
|
||||
|
||||
$userToResetPassword = User::factory()->create();
|
||||
$token = Password::createToken($userToResetPassword);
|
||||
|
||||
Filament::setCurrentPanel(Filament::getPanel('custom'));
|
||||
|
||||
livewire(ResetPassword::class, [
|
||||
'email' => $userToResetPassword->email,
|
||||
'token' => $token,
|
||||
])
|
||||
->set('password', 'new-password')
|
||||
->set('passwordConfirmation', 'new-password')
|
||||
->call('resetPassword')
|
||||
->assertNotified(
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('passwords.user'))
|
||||
);
|
||||
|
||||
Event::assertNotDispatched(PasswordReset::class);
|
||||
|
||||
$this->assertCredentials([
|
||||
'email' => $userToResetPassword->email,
|
||||
'password' => 'password',
|
||||
]);
|
||||
});
|
||||
|
||||
it('requires request signature', function () {
|
||||
$userToResetPassword = User::factory()->make();
|
||||
$token = Password::createToken($userToResetPassword);
|
||||
|
||||
Reference in New Issue
Block a user