use BookStack\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Password;
class ResetPasswordController extends Controller
{
return redirect($this->redirectPath())
->with('status', trans($response));
}
+
+ /**
+ * Get the response for a failed password reset.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param string $response
+ * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
+ */
+ protected function sendResetFailedResponse(Request $request, $response)
+ {
+ // We show invalid users as invalid tokens as to not leak what
+ // users may exist in the system.
+ if ($response === Password::INVALID_USER) {
+ $response = Password::INVALID_TOKEN;
+ }
+
+ return redirect()->back()
+ ->withInput($request->only('email'))
+ ->withErrors(['email' => trans($response)]);
+ }
}
<?php namespace Tests\Auth;
+use BookStack\Auth\Role;
use BookStack\Auth\User;
use BookStack\Entities\Page;
use BookStack\Notifications\ConfirmEmail;
+use BookStack\Notifications\ResetPassword;
use BookStack\Settings\SettingService;
+use DB;
+use Hash;
use Illuminate\Support\Facades\Notification;
use Tests\BrowserKitTest;
->press('Resend Confirmation Email');
// Get confirmation and confirm notification matches
- $emailConfirmation = \DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first();
+ $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first();
Notification::assertSentTo($dbUser, ConfirmEmail::class, function($notification, $channels) use ($emailConfirmation) {
return $notification->token === $emailConfirmation->token;
});
->seePageIs('/settings/users');
$userPassword = User::find($user->id)->password;
- $this->assertTrue(\Hash::check('newpassword', $userPassword));
+ $this->assertTrue(Hash::check('newpassword', $userPassword));
}
public function test_user_deletion()
public function test_user_cannot_be_deleted_if_last_admin()
{
- $adminRole = \BookStack\Auth\Role::getRole('admin');
+ $adminRole = Role::getRole('admin');
// Delete all but one admin user if there are more than one
$adminUsers = $adminRole->users;
public function test_reset_password_flow()
{
-
Notification::fake();
$this->visit('/login')->click('Forgot Password?')
->seePageIs('/password/email')
->type('admin@admin.com', 'email')
->press('Send Reset Link')
- ->see('A password reset link has been sent to admin@admin.com');
+ ->see('A password reset link will be sent to admin@admin.com if that email address is found in the system.');
$this->seeInDatabase('password_resets', [
'email' => 'admin@admin.com'
$user = User::where('email', '=', 'admin@admin.com')->first();
- Notification::assertSentTo($user, \BookStack\Notifications\ResetPassword::class);
- $n = Notification::sent($user, \BookStack\Notifications\ResetPassword::class);
+ Notification::assertSentTo($user, ResetPassword::class);
+ $n = Notification::sent($user, ResetPassword::class);
$this->visit('/password/reset/' . $n->first()->token)
->see('Reset Password')
->see('Your password has been successfully reset');
}
+ public function test_reset_password_flow_shows_success_message_even_if_wrong_password_to_prevent_user_discovery()
+ {
+ $this->visit('/login')->click('Forgot Password?')
+ ->seePageIs('/password/email')
+ ->type('barry@admin.com', 'email')
+ ->press('Send Reset Link')
+ ->see('A password reset link will be sent to barry@admin.com if that email address is found in the system.')
+ ->dontSee('We can\'t find a user');
+
+
+ $this->visit('/password/reset/arandometokenvalue')
+ ->see('Reset Password')
+ ->submitForm('Reset Password', [
+ 'email' => 'barry@admin.com',
+ 'password' => 'randompass',
+ 'password_confirmation' => 'randompass'
+ ])->followRedirects()
+ ->seePageIs('/password/reset/arandometokenvalue')
+ ->dontSee('We can\'t find a user')
+ ->see('The password reset token is invalid for this email address.');
+ }
+
public function test_reset_password_page_shows_sign_links()
{
$this->setSettings(['registration-enabled' => 'true']);