From 2a2cc858f0f95c606f2ad2542f915d3bd761775f Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Thu, 19 Sep 2019 15:12:10 +0100
Subject: [PATCH] Refactored notification showing and global view data

---
 .../Auth/ConfirmEmailController.php           | 10 ++--
 .../Auth/ForgotPasswordController.php         |  2 +-
 .../Controllers/Auth/RegisterController.php   |  4 +-
 .../Auth/ResetPasswordController.php          |  2 +-
 .../Controllers/Auth/UserInviteController.php |  4 +-
 app/Http/Controllers/BookController.php       |  2 +-
 app/Http/Controllers/BookshelfController.php  |  4 +-
 app/Http/Controllers/ChapterController.php    |  6 +--
 app/Http/Controllers/Controller.php           | 49 ++++++++++++-------
 app/Http/Controllers/PageController.php       | 18 +++----
 app/Http/Controllers/PermissionController.php |  8 +--
 app/Http/Controllers/SettingController.php    |  8 +--
 app/Http/Controllers/UserController.php       | 12 ++---
 app/Http/Kernel.php                           |  3 +-
 app/Http/Middleware/GlobalViewData.php        | 28 +++++++++++
 15 files changed, 102 insertions(+), 58 deletions(-)
 create mode 100644 app/Http/Middleware/GlobalViewData.php

diff --git a/app/Http/Controllers/Auth/ConfirmEmailController.php b/app/Http/Controllers/Auth/ConfirmEmailController.php
index 4300ab458..3959fe685 100644
--- a/app/Http/Controllers/Auth/ConfirmEmailController.php
+++ b/app/Http/Controllers/Auth/ConfirmEmailController.php
@@ -65,14 +65,14 @@ class ConfirmEmailController extends Controller
             $userId = $this->emailConfirmationService->checkTokenAndGetUserId($token);
         } catch (Exception $exception) {
             if ($exception instanceof UserTokenNotFoundException) {
-                session()->flash('error', trans('errors.email_confirmation_invalid'));
+                $this->showErrorNotification( trans('errors.email_confirmation_invalid'));
                 return redirect('/register');
             }
 
             if ($exception instanceof UserTokenExpiredException) {
                 $user = $this->userRepo->getById($exception->userId);
                 $this->emailConfirmationService->sendConfirmation($user);
-                session()->flash('error', trans('errors.email_confirmation_expired'));
+                $this->showErrorNotification( trans('errors.email_confirmation_expired'));
                 return redirect('/register/confirm');
             }
 
@@ -84,7 +84,7 @@ class ConfirmEmailController extends Controller
         $user->save();
 
         auth()->login($user);
-        session()->flash('success', trans('auth.email_confirm_success'));
+        $this->showSuccessNotification( trans('auth.email_confirm_success'));
         $this->emailConfirmationService->deleteByUser($user);
 
         return redirect('/');
@@ -106,11 +106,11 @@ class ConfirmEmailController extends Controller
         try {
             $this->emailConfirmationService->sendConfirmation($user);
         } catch (Exception $e) {
-            session()->flash('error', trans('auth.email_confirm_send_error'));
+            $this->showErrorNotification( trans('auth.email_confirm_send_error'));
             return redirect('/register/confirm');
         }
 
-        session()->flash('success', trans('auth.email_confirm_resent'));
+        $this->showSuccessNotification( trans('auth.email_confirm_resent'));
         return redirect('/register/confirm');
     }
 }
diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php
index a0cbae9c6..4a0a69ae4 100644
--- a/app/Http/Controllers/Auth/ForgotPasswordController.php
+++ b/app/Http/Controllers/Auth/ForgotPasswordController.php
@@ -53,7 +53,7 @@ class ForgotPasswordController extends Controller
 
         if ($response === Password::RESET_LINK_SENT) {
             $message = trans('auth.reset_password_sent_success', ['email' => $request->get('email')]);
-            session()->flash('success', $message);
+            $this->showSuccessNotification( $message);
             return back()->with('status', trans($response));
         }
 
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
index 70090fed0..304d3bed2 100644
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -166,14 +166,14 @@ class RegisterController extends Controller
             try {
                 $this->emailConfirmationService->sendConfirmation($newUser);
             } catch (Exception $e) {
-                session()->flash('error', trans('auth.email_confirm_send_error'));
+                $this->showErrorNotification(trans('auth.email_confirm_send_error'));
             }
 
             return redirect('/register/confirm');
         }
 
         auth()->login($newUser);
-        session()->flash('success', trans('auth.register_success'));
+        $this->showSuccessNotification(trans('auth.register_success'));
         return redirect($this->redirectPath());
     }
 
diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php
index d7005b739..540d2e679 100644
--- a/app/Http/Controllers/Auth/ResetPasswordController.php
+++ b/app/Http/Controllers/Auth/ResetPasswordController.php
@@ -44,7 +44,7 @@ class ResetPasswordController extends Controller
     protected function sendResetResponse(Request $request, $response)
     {
         $message = trans('auth.reset_password_success');
-        session()->flash('success', $message);
+        $this->showSuccessNotification( $message);
         return redirect($this->redirectPath())
             ->with('status', trans($response));
     }
diff --git a/app/Http/Controllers/Auth/UserInviteController.php b/app/Http/Controllers/Auth/UserInviteController.php
index 8799d264c..313faf5bc 100644
--- a/app/Http/Controllers/Auth/UserInviteController.php
+++ b/app/Http/Controllers/Auth/UserInviteController.php
@@ -77,7 +77,7 @@ class UserInviteController extends Controller
         $user->save();
 
         auth()->login($user);
-        session()->flash('success', trans('auth.user_invite_success', ['appName' => setting('app-name')]));
+        $this->showSuccessNotification( trans('auth.user_invite_success', ['appName' => setting('app-name')]));
         $this->inviteService->deleteByUser($user);
 
         return redirect('/');
@@ -96,7 +96,7 @@ class UserInviteController extends Controller
         }
 
         if ($exception instanceof UserTokenExpiredException) {
-            session()->flash('error', trans('errors.invite_token_expired'));
+            $this->showErrorNotification( trans('errors.invite_token_expired'));
             return redirect('/password/email');
         }
 
diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php
index 97659ed96..7a0ee0f0e 100644
--- a/app/Http/Controllers/BookController.php
+++ b/app/Http/Controllers/BookController.php
@@ -380,7 +380,7 @@ class BookController extends Controller
         $book = $this->bookRepo->getBySlug($bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $book);
         $this->bookRepo->updateEntityPermissionsFromRequest($request, $book);
-        session()->flash('success', trans('entities.books_permissions_updated'));
+        $this->showSuccessNotification(trans('entities.books_permissions_updated'));
         return redirect($book->getUrl());
     }
 
diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php
index 32d08dc77..c369ce655 100644
--- a/app/Http/Controllers/BookshelfController.php
+++ b/app/Http/Controllers/BookshelfController.php
@@ -254,7 +254,7 @@ class BookshelfController extends Controller
         $this->checkOwnablePermission('restrictions-manage', $shelf);
 
         $this->entityRepo->updateEntityPermissionsFromRequest($request, $shelf);
-        session()->flash('success', trans('entities.shelves_permissions_updated'));
+        $this->showSuccessNotification( trans('entities.shelves_permissions_updated'));
         return redirect($shelf->getUrl());
     }
 
@@ -270,7 +270,7 @@ class BookshelfController extends Controller
         $this->checkOwnablePermission('restrictions-manage', $shelf);
 
         $updateCount = $this->entityRepo->copyBookshelfPermissions($shelf);
-        session()->flash('success', trans('entities.shelves_copy_permission_success', ['count' => $updateCount]));
+        $this->showSuccessNotification( trans('entities.shelves_copy_permission_success', ['count' => $updateCount]));
         return redirect($shelf->getUrl());
     }
 
diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php
index 796689c66..a4a1dbf24 100644
--- a/app/Http/Controllers/ChapterController.php
+++ b/app/Http/Controllers/ChapterController.php
@@ -197,13 +197,13 @@ class ChapterController extends Controller
         }
 
         if ($parent === false || $parent === null) {
-            session()->flash('error', trans('errors.selected_book_not_found'));
+            $this->showErrorNotification( trans('errors.selected_book_not_found'));
             return redirect()->back();
         }
 
         $this->entityRepo->changeBook('chapter', $parent->id, $chapter, true);
         Activity::add($chapter, 'chapter_move', $chapter->book->id);
-        session()->flash('success', trans('entities.chapter_move_success', ['bookName' => $parent->name]));
+        $this->showSuccessNotification( trans('entities.chapter_move_success', ['bookName' => $parent->name]));
 
         return redirect($chapter->getUrl());
     }
@@ -240,7 +240,7 @@ class ChapterController extends Controller
         $chapter = $this->entityRepo->getEntityBySlug('chapter', $chapterSlug, $bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $chapter);
         $this->entityRepo->updateEntityPermissionsFromRequest($request, $chapter);
-        session()->flash('success', trans('entities.chapters_permissions_success'));
+        $this->showSuccessNotification( trans('entities.chapters_permissions_success'));
         return redirect($chapter->getUrl());
     }
 }
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
index 5bc62c601..e34cb7e59 100644
--- a/app/Http/Controllers/Controller.php
+++ b/app/Http/Controllers/Controller.php
@@ -18,6 +18,7 @@ abstract class Controller extends BaseController
      * @var User static
      */
     protected $currentUser;
+
     /**
      * @var bool
      */
@@ -28,28 +29,15 @@ abstract class Controller extends BaseController
      */
     public function __construct()
     {
-        $this->middleware(function ($request, $next) {
-
-            // Get a user instance for the current user
-            $user = user();
-
-            // Share variables with controllers
-            $this->currentUser = $user;
-            $this->signedIn = auth()->check();
-
-            // Share variables with views
-            view()->share('signedIn', $this->signedIn);
-            view()->share('currentUser', $user);
-
-            return $next($request);
-        });
+        $this->currentUser = user();
+        $this->signedIn = auth()->check();
     }
 
     /**
      * Stops the application and shows a permission error if
      * the application is in demo mode.
      */
-    protected function preventAccessForDemoUsers()
+    protected function preventAccessInDemoMode()
     {
         if (config('app.env') === 'demo') {
             $this->showPermissionError();
@@ -75,7 +63,7 @@ abstract class Controller extends BaseController
             $response = response()->json(['error' => trans('errors.permissionJson')], 403);
         } else {
             $response = redirect('/');
-            session()->flash('error', trans('errors.permission'));
+            $this->showErrorNotification( trans('errors.permission'));
         }
 
         throw new HttpResponseException($response);
@@ -178,4 +166,31 @@ abstract class Controller extends BaseController
             'Content-Disposition' => 'attachment; filename="' . $fileName . '"'
         ]);
     }
+
+    /**
+     * Show a positive, successful notification to the user on next view load.
+     * @param string $message
+     */
+    protected function showSuccessNotification(string $message)
+    {
+        session()->flash('success', $message);
+    }
+
+    /**
+     * Show a warning notification to the user on next view load.
+     * @param string $message
+     */
+    protected function showWarningNotification(string $message)
+    {
+        session()->flash('warning', $message);
+    }
+
+    /**
+     * Show an error notification to the user on next view load.
+     * @param string $message
+     */
+    protected function showErrorNotification(string $message)
+    {
+        session()->flash('error', $message);
+    }
 }
diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php
index 45aa8f934..30f58ab6a 100644
--- a/app/Http/Controllers/PageController.php
+++ b/app/Http/Controllers/PageController.php
@@ -240,7 +240,7 @@ class PageController extends Controller
         }
 
         if (count($warnings) > 0) {
-            session()->flash('warning', implode("\n", $warnings));
+            $this->showWarningNotification( implode("\n", $warnings));
         }
 
         $draftsEnabled = $this->signedIn;
@@ -359,7 +359,7 @@ class PageController extends Controller
         $this->pageRepo->destroyPage($page);
 
         Activity::addMessage('page_delete', $book->id, $page->name);
-        session()->flash('success', trans('entities.pages_delete_success'));
+        $this->showSuccessNotification( trans('entities.pages_delete_success'));
         return redirect($book->getUrl());
     }
 
@@ -375,7 +375,7 @@ class PageController extends Controller
         $page = $this->pageRepo->getById('page', $pageId, true);
         $book = $page->book;
         $this->checkOwnablePermission('page-update', $page);
-        session()->flash('success', trans('entities.pages_delete_draft_success'));
+        $this->showSuccessNotification( trans('entities.pages_delete_draft_success'));
         $this->pageRepo->destroyPage($page);
         return redirect($book->getUrl());
     }
@@ -491,12 +491,12 @@ class PageController extends Controller
 
         // Check if its the latest revision, cannot delete latest revision.
         if (intval($currentRevision->id) === intval($revId)) {
-            session()->flash('error', trans('entities.revision_cannot_delete_latest'));
+            $this->showErrorNotification( trans('entities.revision_cannot_delete_latest'));
             return response()->view('pages.revisions', ['page' => $page, 'book' => $page->book, 'current' => $page], 400);
         }
 
         $revision->delete();
-        session()->flash('success', trans('entities.revision_delete_success'));
+        $this->showSuccessNotification( trans('entities.revision_delete_success'));
         return redirect($page->getUrl('/revisions'));
     }
 
@@ -568,7 +568,7 @@ class PageController extends Controller
 
         $this->pageRepo->changePageParent($page, $parent);
         Activity::add($page, 'page_move', $page->book->id);
-        session()->flash('success', trans('entities.pages_move_success', ['parentName' => $parent->name]));
+        $this->showSuccessNotification( trans('entities.pages_move_success', ['parentName' => $parent->name]));
 
         return redirect($page->getUrl());
     }
@@ -616,7 +616,7 @@ class PageController extends Controller
             try {
                 $parent = $this->pageRepo->getById($entityType, $entityId);
             } catch (Exception $e) {
-                session()->flash(trans('entities.selected_book_chapter_not_found'));
+                $this->showErrorNotification(trans('entities.selected_book_chapter_not_found'));
                 return redirect()->back();
             }
         }
@@ -626,7 +626,7 @@ class PageController extends Controller
         $pageCopy = $this->pageRepo->copyPage($page, $parent, $request->get('name', ''));
 
         Activity::add($pageCopy, 'page_create', $pageCopy->book->id);
-        session()->flash('success', trans('entities.pages_copy_success'));
+        $this->showSuccessNotification( trans('entities.pages_copy_success'));
 
         return redirect($pageCopy->getUrl());
     }
@@ -663,7 +663,7 @@ class PageController extends Controller
         $page = $this->pageRepo->getBySlug($pageSlug, $bookSlug);
         $this->checkOwnablePermission('restrictions-manage', $page);
         $this->pageRepo->updateEntityPermissionsFromRequest($request, $page);
-        session()->flash('success', trans('entities.pages_permissions_success'));
+        $this->showSuccessNotification( trans('entities.pages_permissions_success'));
         return redirect($page->getUrl());
     }
 }
diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/PermissionController.php
index f19e7e763..b8ca5a646 100644
--- a/app/Http/Controllers/PermissionController.php
+++ b/app/Http/Controllers/PermissionController.php
@@ -53,7 +53,7 @@ class PermissionController extends Controller
         ]);
 
         $this->permissionsRepo->saveNewRole($request->all());
-        session()->flash('success', trans('settings.role_create_success'));
+        $this->showSuccessNotification( trans('settings.role_create_success'));
         return redirect('/settings/roles');
     }
 
@@ -90,7 +90,7 @@ class PermissionController extends Controller
         ]);
 
         $this->permissionsRepo->updateRole($id, $request->all());
-        session()->flash('success', trans('settings.role_update_success'));
+        $this->showSuccessNotification( trans('settings.role_update_success'));
         return redirect('/settings/roles');
     }
 
@@ -124,11 +124,11 @@ class PermissionController extends Controller
         try {
             $this->permissionsRepo->deleteRole($id, $request->get('migrate_role_id'));
         } catch (PermissionsException $e) {
-            session()->flash('error', $e->getMessage());
+            $this->showErrorNotification( $e->getMessage());
             return redirect()->back();
         }
 
-        session()->flash('success', trans('settings.role_delete_success'));
+        $this->showSuccessNotification( trans('settings.role_delete_success'));
         return redirect('/settings/roles');
     }
 }
diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php
index 650833c7f..68687dc95 100644
--- a/app/Http/Controllers/SettingController.php
+++ b/app/Http/Controllers/SettingController.php
@@ -47,7 +47,7 @@ class SettingController extends Controller
      */
     public function update(Request $request)
     {
-        $this->preventAccessForDemoUsers();
+        $this->preventAccessInDemoMode();
         $this->checkPermission('settings-manage');
         $this->validate($request, [
             'app_logo' => $this->imageRepo->getImageValidationRules(),
@@ -76,7 +76,7 @@ class SettingController extends Controller
             setting()->remove('app-logo');
         }
 
-        session()->flash('success', trans('settings.settings_save_success'));
+        $this->showSuccessNotification( trans('settings.settings_save_success'));
         return redirect('/settings');
     }
 
@@ -111,14 +111,14 @@ class SettingController extends Controller
         $imagesToDelete = $imageService->deleteUnusedImages($checkRevisions, $dryRun);
         $deleteCount = count($imagesToDelete);
         if ($deleteCount === 0) {
-            session()->flash('warning', trans('settings.maint_image_cleanup_nothing_found'));
+            $this->showWarningNotification( trans('settings.maint_image_cleanup_nothing_found'));
             return redirect('/settings/maintenance')->withInput();
         }
 
         if ($dryRun) {
             session()->flash('cleanup-images-warning', trans('settings.maint_image_cleanup_warning', ['count' => $deleteCount]));
         } else {
-            session()->flash('success', trans('settings.maint_image_cleanup_success', ['count' => $deleteCount]));
+            $this->showSuccessNotification( trans('settings.maint_image_cleanup_success', ['count' => $deleteCount]));
         }
 
         return redirect('/settings/maintenance#image-cleanup')->withInput();
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index 4f4f98104..6984fef1e 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -144,7 +144,7 @@ class UserController extends Controller
      */
     public function update(Request $request, $id)
     {
-        $this->preventAccessForDemoUsers();
+        $this->preventAccessInDemoMode();
         $this->checkPermissionOrCurrentUser('users-manage', $id);
 
         $this->validate($request, [
@@ -202,7 +202,7 @@ class UserController extends Controller
         }
 
         $user->save();
-        session()->flash('success', trans('settings.users_edit_success'));
+        $this->showSuccessNotification( trans('settings.users_edit_success'));
 
         $redirectUrl = userCan('users-manage') ? '/settings/users' : ('/settings/users/' . $user->id);
         return redirect($redirectUrl);
@@ -230,23 +230,23 @@ class UserController extends Controller
      */
     public function destroy($id)
     {
-        $this->preventAccessForDemoUsers();
+        $this->preventAccessInDemoMode();
         $this->checkPermissionOrCurrentUser('users-manage', $id);
 
         $user = $this->userRepo->getById($id);
 
         if ($this->userRepo->isOnlyAdmin($user)) {
-            session()->flash('error', trans('errors.users_cannot_delete_only_admin'));
+            $this->showErrorNotification( trans('errors.users_cannot_delete_only_admin'));
             return redirect($user->getEditUrl());
         }
 
         if ($user->system_name === 'public') {
-            session()->flash('error', trans('errors.users_cannot_delete_guest'));
+            $this->showErrorNotification( trans('errors.users_cannot_delete_guest'));
             return redirect($user->getEditUrl());
         }
 
         $this->userRepo->destroy($user);
-        session()->flash('success', trans('settings.users_delete_success'));
+        $this->showSuccessNotification( trans('settings.users_delete_success'));
 
         return redirect('/settings/users');
     }
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 004f30139..f9752da09 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -32,7 +32,8 @@ class Kernel extends HttpKernel
             \Illuminate\Routing\Middleware\ThrottleRequests::class,
             \BookStack\Http\Middleware\VerifyCsrfToken::class,
             \Illuminate\Routing\Middleware\SubstituteBindings::class,
-            \BookStack\Http\Middleware\Localization::class
+            \BookStack\Http\Middleware\Localization::class,
+            \BookStack\Http\Middleware\GlobalViewData::class,
         ],
         'api' => [
             'throttle:60,1',
diff --git a/app/Http/Middleware/GlobalViewData.php b/app/Http/Middleware/GlobalViewData.php
new file mode 100644
index 000000000..0c2419016
--- /dev/null
+++ b/app/Http/Middleware/GlobalViewData.php
@@ -0,0 +1,28 @@
+<?php namespace BookStack\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+
+/**
+ * Class GlobalViewData
+ * Sets up data that is accessible to any view rendered by the web routes.
+ */
+class GlobalViewData
+{
+
+    /**
+     * Handle an incoming request.
+     *
+     * @param Request $request
+     * @param Closure $next
+     * @return mixed
+     */
+    public function handle(Request $request, Closure $next)
+    {
+        view()->share('signedIn', auth()->check());
+        view()->share('currentUser', user());
+
+        return $next($request);
+    }
+
+}
\ No newline at end of file