diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index d93854e23..45e40e6fe 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -4,6 +4,8 @@ namespace BookStack\Http\Controllers\Auth; use BookStack\Http\Controllers\Controller; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; +use Illuminate\Http\Request; +use Password; class ForgotPasswordController extends Controller { @@ -30,4 +32,37 @@ class ForgotPasswordController extends Controller $this->middleware('guest'); parent::__construct(); } + + + /** + * Send a reset link to the given user. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\RedirectResponse + */ + public function sendResetLinkEmail(Request $request) + { + $this->validate($request, ['email' => 'required|email']); + + // We will send the password reset link to this user. Once we have attempted + // to send the link, we will examine the response then see the message we + // need to show to the user. Finally, we'll send out a proper response. + $response = $this->broker()->sendResetLink( + $request->only('email') + ); + + if ($response === Password::RESET_LINK_SENT) { + $message = 'A password reset link has been sent to ' . $request->get('email') . '.'; + session()->flash('success', $message); + return back()->with('status', trans($response)); + } + + // If an error was returned by the password broker, we will get this message + // translated so we can notify a user of the problem. We'll redirect back + // to where the users came from so they can attempt this process again. + return back()->withErrors( + ['email' => trans($response)] + ); + } + } \ No newline at end of file diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 656b8cc42..bd64793f9 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -20,6 +20,8 @@ class ResetPasswordController extends Controller use ResetsPasswords; + protected $redirectTo = '/'; + /** * Create a new controller instance. * @@ -30,4 +32,18 @@ class ResetPasswordController extends Controller $this->middleware('guest'); parent::__construct(); } + + /** + * Get the response for a successful password reset. + * + * @param string $response + * @return \Illuminate\Http\Response + */ + protected function sendResetResponse($response) + { + $message = 'Your password has been successfully reset.'; + session()->flash('success', $message); + return redirect($this->redirectPath()) + ->with('status', trans($response)); + } } \ No newline at end of file diff --git a/config/setting-defaults.php b/config/setting-defaults.php index 5482c1331..c681bb7f5 100644 --- a/config/setting-defaults.php +++ b/config/setting-defaults.php @@ -9,6 +9,8 @@ return [ 'app-name-header' => true, 'app-editor' => 'wysiwyg', 'app-color' => '#0288D1', - 'app-color-light' => 'rgba(21, 101, 192, 0.15)' + 'app-color-light' => 'rgba(21, 101, 192, 0.15)', + 'app-custom-head' => false, + 'registration-enabled' => false, ]; \ No newline at end of file diff --git a/resources/assets/sass/_blocks.scss b/resources/assets/sass/_blocks.scss index 3c7f7490b..727633f75 100644 --- a/resources/assets/sass/_blocks.scss +++ b/resources/assets/sass/_blocks.scss @@ -135,6 +135,7 @@ border-left: 3px solid #BBB; background-color: #EEE; padding: $-s; + display: flex; &:before { font-family: 'Material-Design-Iconic-Font'; padding-right: $-s; diff --git a/resources/assets/sass/_text.scss b/resources/assets/sass/_text.scss index fd993b685..e81061685 100644 --- a/resources/assets/sass/_text.scss +++ b/resources/assets/sass/_text.scss @@ -262,7 +262,7 @@ ul { ol { list-style: decimal; - padding-left: $-m * 1.3; + padding-left: $-m * 2; overflow: hidden; } diff --git a/resources/views/auth/passwords/email.blade.php b/resources/views/auth/passwords/email.blade.php index d8536efa7..115785ab2 100644 --- a/resources/views/auth/passwords/email.blade.php +++ b/resources/views/auth/passwords/email.blade.php @@ -1,5 +1,12 @@ @extends('public') +@section('header-buttons') + Sign in + @if(setting('registration-enabled')) + Sign up + @endif +@stop + @section('content') diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php index 9a9a65ff0..612b50ff8 100644 --- a/resources/views/auth/passwords/reset.blade.php +++ b/resources/views/auth/passwords/reset.blade.php @@ -1,5 +1,12 @@ @extends('public') +@section('header-buttons') + Sign in + @if(setting('registration-enabled')) + Sign up + @endif +@stop + @section('body-class', 'image-cover login') @section('content') diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 1deed0a3f..08acf725d 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -23,7 +23,7 @@ @include('partials/custom-styles') - @if(setting('app-custom-head', false)) + @if(setting('app-custom-head')) {!! setting('app-custom-head') !!} @endif diff --git a/resources/views/pages/pdf.blade.php b/resources/views/pages/pdf.blade.php index 0cbf4df02..5c9fd5eea 100644 --- a/resources/views/pages/pdf.blade.php +++ b/resources/views/pages/pdf.blade.php @@ -14,7 +14,7 @@ table { max-width: 800px !important; font-size: 0.8em; - width: auto !important; + width: 100% !important; } table td { diff --git a/resources/views/public.blade.php b/resources/views/public.blade.php index 542d5c867..16aebe2bb 100644 --- a/resources/views/public.blade.php +++ b/resources/views/public.blade.php @@ -17,6 +17,11 @@ @include('partials/custom-styles') + + + @if(setting('app-custom-head')) + {!! setting('app-custom-head') !!} + @endif diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 08d5ef8ad..0d2e4ac17 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -218,6 +218,37 @@ class AuthTest extends TestCase ->seePageIs('/login'); } + public function test_reset_password_flow() + { + $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'); + + $this->seeInDatabase('password_resets', [ + 'email' => 'admin@admin.com' + ]); + + $reset = DB::table('password_resets')->where('email', '=', 'admin@admin.com')->first(); + $this->visit('/password/reset/' . $reset->token) + ->see('Reset Password') + ->submitForm('Reset Password', [ + 'email' => 'admin@admin.com', + 'password' => 'randompass', + 'password_confirmation' => 'randompass' + ])->seePageIs('/') + ->see('Your password has been successfully reset'); + } + + public function test_reset_password_page_shows_sign_links() + { + $this->setSettings(['registration-enabled' => 'true']); + $this->visit('/password/email') + ->seeLink('Sign in') + ->seeLink('Sign up'); + } + /** * Perform a login * @param string $email diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 8adfd35a3..cfdabdb0a 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -91,6 +91,12 @@ class EntitySearchTest extends TestCase ->see('Book Search Results')->see('.entity-list', $book->name); } + public function test_searching_hypen_doesnt_break() + { + $this->visit('/search/all?term=cat+-') + ->seeStatusCode(200); + } + public function test_ajax_entity_search() { $page = \BookStack\Page::all()->last(); diff --git a/tests/ImageTest.php b/tests/ImageTest.php index 234988ba4..031517cdb 100644 --- a/tests/ImageTest.php +++ b/tests/ImageTest.php @@ -57,7 +57,7 @@ class ImageTest extends TestCase $relPath = $this->uploadImage($imageName, $page->id); $this->assertResponseOk(); - $this->assertTrue(file_exists(public_path($relPath)), 'Uploaded image exists'); + $this->assertTrue(file_exists(public_path($relPath)), 'Uploaded image not found at path: '. public_path($relPath)); $this->deleteImage($relPath); @@ -70,7 +70,6 @@ class ImageTest extends TestCase 'updated_by' => $admin->id, 'name' => $imageName ]); - }