From 0d8ca22487ee28bd2a5b9f0847137b6ac8e442ce Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 31 Dec 2015 17:32:03 +0000 Subject: [PATCH 1/4] Swapped vue for angular js --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 2d4c84b3b..b1570a1f4 100644 --- a/readme.md +++ b/readme.md @@ -82,7 +82,7 @@ BookStack is provided under the MIT License. These are the great projects used to help build BookStack: * [Laravel](http://laravel.com/) -* [VueJS](http://vuejs.org/) +* [AngularJS](https://angularjs.org/) * [jQuery](https://jquery.com/) * [TinyMCE](https://www.tinymce.com/) * [highlight.js](https://highlightjs.org/) From 9a470b07fdc2bbada54735bb9d07045b6ff937a9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 31 Dec 2015 17:57:34 +0000 Subject: [PATCH 2/4] Added public build folder and support for a demo mode --- .gitignore | 1 - app/Http/Controllers/Controller.php | 32 +++++++++++++++++++--- app/Http/Controllers/SettingController.php | 3 ++ app/Http/Controllers/UserController.php | 4 +++ public/build/.gitignore | 2 ++ 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 public/build/.gitignore diff --git a/.gitignore b/.gitignore index ca7858438..66a7c0f9b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ Homestead.yaml /public/js /public/uploads /public/bower -/public/build /storage/images _ide_helper.php /storage/debugbar \ No newline at end of file diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 5dc79eb02..ca022f7ca 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -42,6 +42,15 @@ abstract class Controller extends BaseController $this->signedIn = auth()->check(); } + /** + * Stops the application and shows a permission error if + * the application is in demo mode. + */ + protected function preventAccessForDemoUsers() + { + if (env('APP_ENV', 'production') === 'demo') $this->showPermissionError(); + } + /** * Adds the page title into the view. * @param $title @@ -51,6 +60,18 @@ abstract class Controller extends BaseController view()->share('pageTitle', $title); } + /** + * On a permission error redirect to home and display + * the error as a notification. + */ + protected function showPermissionError() + { + Session::flash('error', trans('errors.permission')); + throw new HttpResponseException( + redirect('/') + ); + } + /** * Checks for a permission. * @@ -60,15 +81,18 @@ abstract class Controller extends BaseController protected function checkPermission($permissionName) { if (!$this->currentUser || !$this->currentUser->can($permissionName)) { - Session::flash('error', trans('errors.permission')); - throw new HttpResponseException( - redirect('/') - ); + $this->showPermissionError(); } return true; } + /** + * Check if a user has a permission or bypass if the callback is true. + * @param $permissionName + * @param $callback + * @return bool + */ protected function checkPermissionOr($permissionName, $callback) { $callbackResult = $callback(); diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index bca48807f..1739e0b53 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -31,13 +31,16 @@ class SettingController extends Controller */ public function update(Request $request) { + $this->preventAccessForDemoUsers(); $this->checkPermission('settings-update'); + // Cycles through posted settings and update them foreach($request->all() as $name => $value) { if(strpos($name, 'setting-') !== 0) continue; $key = str_replace('setting-', '', trim($name)); Setting::put($key, $value); } + session()->flash('success', 'Settings Saved'); return redirect('/settings'); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 3f41b2d0e..fe25c44ae 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -108,9 +108,11 @@ class UserController extends Controller */ public function update(Request $request, $id) { + $this->preventAccessForDemoUsers(); $this->checkPermissionOr('user-update', function () use ($id) { return $this->currentUser->id == $id; }); + $this->validate($request, [ 'name' => 'required', 'email' => 'required|email|unique:users,email,' . $id, @@ -144,6 +146,7 @@ class UserController extends Controller $this->checkPermissionOr('user-delete', function () use ($id) { return $this->currentUser->id == $id; }); + $user = $this->user->findOrFail($id); $this->setPageTitle('Delete User ' . $user->name); return view('users/delete', ['user' => $user]); @@ -156,6 +159,7 @@ class UserController extends Controller */ public function destroy($id) { + $this->preventAccessForDemoUsers(); $this->checkPermissionOr('user-delete', function () use ($id) { return $this->currentUser->id == $id; }); diff --git a/public/build/.gitignore b/public/build/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/public/build/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore From f60a0c3b7606577e089832eee74f90e6a4d958e6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 1 Jan 2016 09:03:40 +0000 Subject: [PATCH 3/4] Improved 404 page and updated tests for empty search --- app/Services/ActivityService.php | 2 +- resources/views/base.blade.php | 6 +++--- resources/views/errors/404.blade.php | 5 +++-- tests/EntityTest.php | 8 ++++++++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/Services/ActivityService.php b/app/Services/ActivityService.php index 4da928fad..2ef5f9cfe 100644 --- a/app/Services/ActivityService.php +++ b/app/Services/ActivityService.php @@ -107,7 +107,7 @@ class ActivityService } /** - * Filters out similar acitivity. + * Filters out similar activity. * @param Activity[] $activity * @return array */ diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 25559bd40..a2979f858 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -43,14 +43,14 @@
- @if($signedIn) + @if(isset($signedIn) && $signedIn) diff --git a/tests/AuthTest.php b/tests/AuthTest.php index befa0214d..3faae6506 100644 --- a/tests/AuthTest.php +++ b/tests/AuthTest.php @@ -102,10 +102,10 @@ class AuthTest extends TestCase ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => true]); } - public function testUserControl() + public function testUserCreation() { $user = factory(\BookStack\User::class)->make(); - // Test creation + $this->asAdmin() ->visit('/users') ->click('Add new user') @@ -118,9 +118,12 @@ class AuthTest extends TestCase ->seeInDatabase('users', $user->toArray()) ->seePageIs('/users') ->see($user->name); - $user = $user->where('email', '=', $user->email)->first(); + } - // Test editing + public function testUserUpdating() + { + $user = \BookStack\User::all()->last(); + $password = $user->password; $this->asAdmin() ->visit('/users') ->click($user->name) @@ -129,20 +132,58 @@ class AuthTest extends TestCase ->type('Barry Scott', '#name') ->press('Save') ->seePageIs('/users') - ->seeInDatabase('users', ['id' => $user->id, 'name' => 'Barry Scott']) + ->seeInDatabase('users', ['id' => $user->id, 'name' => 'Barry Scott', 'password' => $password]) ->notSeeInDatabase('users', ['name' => $user->name]); - $user = $user->find($user->id); + } + + public function testUserPasswordUpdate() + { + $user = \BookStack\User::all()->last(); + $userProfilePage = '/users/' . $user->id; + $this->asAdmin() + ->visit($userProfilePage) + ->type('newpassword', '#password') + ->press('Save') + ->seePageIs($userProfilePage) + ->see('Password confirmation required') + + ->type('newpassword', '#password') + ->type('newpassword', '#password-confirm') + ->press('Save') + ->seePageIs('/users'); + + $userPassword = \BookStack\User::find($user->id)->password; + $this->assertTrue(Hash::check('newpassword', $userPassword)); + } + + public function testUserDeletion() + { + $userDetails = factory(\BookStack\User::class)->make(); + $user = $this->getNewUser($userDetails->toArray()); - // Test Deletion $this->asAdmin() ->visit('/users/' . $user->id) - ->click('Delete user') + ->click('Delete User') ->see($user->name) ->press('Confirm') ->seePageIs('/users') ->notSeeInDatabase('users', ['name' => $user->name]); } + public function testUserCannotBeDeletedIfLastAdmin() + { + $adminRole = \BookStack\Role::getRole('admin'); + // Ensure we currently only have 1 admin user + $this->assertEquals(1, $adminRole->users()->count()); + $user = $adminRole->users->first(); + + $this->asAdmin()->visit('/users/' . $user->id) + ->click('Delete User') + ->press('Confirm') + ->seePageIs('/users/' . $user->id) + ->see('You cannot delete the only admin'); + } + public function testLogout() { $this->asAdmin() diff --git a/tests/EntityTest.php b/tests/EntityTest.php index 4c4195fd9..1eda7c73c 100644 --- a/tests/EntityTest.php +++ b/tests/EntityTest.php @@ -188,6 +188,29 @@ class EntityTest extends TestCase ->seePageIs('/'); } + public function testBookSearch() + { + $book = \BookStack\Book::all()->first(); + $page = $book->pages->last(); + $chapter = $book->chapters->last(); + + $this->asAdmin() + ->visit('/search/book/' . $book->id . '?term=' . urlencode($page->name)) + ->see($page->name) + + ->visit('/search/book/' . $book->id . '?term=' . urlencode($chapter->name)) + ->see($chapter->name); + } + + public function testEmptyBookSearchRedirectsBack() + { + $book = \BookStack\Book::all()->first(); + $this->asAdmin() + ->visit('/books') + ->visit('/search/book/' . $book->id . '?term=') + ->seePageIs('/books'); + } + public function testEntitiesViewableAfterCreatorDeletion() {