diff --git a/app/Activity.php b/app/Activity.php
index 34daa2760..a1fe608f0 100644
--- a/app/Activity.php
+++ b/app/Activity.php
@@ -19,11 +19,7 @@ class Activity extends Model
      */
     public function entity()
     {
-        if ($this->entity_id) {
-            return $this->morphTo('entity')->first();
-        } else {
-            return false;
-        }
+        return $this->morphTo('entity');
     }
 
     /**
diff --git a/app/Providers/CustomFacadeProvider.php b/app/Providers/CustomFacadeProvider.php
index 1df14a076..9b290039c 100644
--- a/app/Providers/CustomFacadeProvider.php
+++ b/app/Providers/CustomFacadeProvider.php
@@ -28,11 +28,17 @@ class CustomFacadeProvider extends ServiceProvider
     public function register()
     {
         $this->app->bind('activity', function() {
-            return new ActivityService($this->app->make('BookStack\Activity'));
+            return new ActivityService(
+                $this->app->make('BookStack\Activity'),
+                $this->app->make('BookStack\Services\RestrictionService')
+            );
         });
 
         $this->app->bind('views', function() {
-            return new ViewService($this->app->make('BookStack\View'));
+            return new ViewService(
+                $this->app->make('BookStack\View'),
+                $this->app->make('BookStack\Services\RestrictionService')
+            );
         });
 
         $this->app->bind('setting', function() {
@@ -41,6 +47,7 @@ class CustomFacadeProvider extends ServiceProvider
                 $this->app->make('Illuminate\Contracts\Cache\Repository')
             );
         });
+
         $this->app->bind('images', function() {
             return new ImageService(
                 $this->app->make('Intervention\Image\ImageManager'),
diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php
index dbf95623e..572030d43 100644
--- a/app/Repos/BookRepo.php
+++ b/app/Repos/BookRepo.php
@@ -1,6 +1,7 @@
 <?php namespace BookStack\Repos;
 
 use Activity;
+use BookStack\Services\RestrictionService;
 use Illuminate\Support\Str;
 use BookStack\Book;
 use Views;
@@ -11,18 +12,31 @@ class BookRepo
     protected $book;
     protected $pageRepo;
     protected $chapterRepo;
+    protected $restrictionService;
 
     /**
      * BookRepo constructor.
      * @param Book $book
      * @param PageRepo $pageRepo
      * @param ChapterRepo $chapterRepo
+     * @param RestrictionService $restrictionService
      */
-    public function __construct(Book $book, PageRepo $pageRepo, ChapterRepo $chapterRepo)
+    public function __construct(Book $book, PageRepo $pageRepo, ChapterRepo $chapterRepo, RestrictionService $restrictionService)
     {
         $this->book = $book;
         $this->pageRepo = $pageRepo;
         $this->chapterRepo = $chapterRepo;
+        $this->restrictionService = $restrictionService;
+    }
+
+    /**
+     * Base query for getting books.
+     * Takes into account any restrictions.
+     * @return mixed
+     */
+    private function bookQuery()
+    {
+        return $this->restrictionService->enforceBookRestrictions($this->book, 'view');
     }
 
     /**
@@ -32,7 +46,7 @@ class BookRepo
      */
     public function getById($id)
     {
-        return $this->book->findOrFail($id);
+        return $this->bookQuery()->findOrFail($id);
     }
 
     /**
@@ -42,7 +56,7 @@ class BookRepo
      */
     public function getAll($count = 10)
     {
-        $bookQuery = $this->book->orderBy('name', 'asc');
+        $bookQuery = $this->bookQuery()->orderBy('name', 'asc');
         if (!$count) return $bookQuery->get();
         return $bookQuery->take($count)->get();
     }
@@ -54,7 +68,8 @@ class BookRepo
      */
     public function getAllPaginated($count = 10)
     {
-        return $this->book->orderBy('name', 'asc')->paginate($count);
+        return $this->bookQuery()
+            ->orderBy('name', 'asc')->paginate($count);
     }
 
 
@@ -65,7 +80,7 @@ class BookRepo
      */
     public function getLatest($count = 10)
     {
-        return $this->book->orderBy('created_at', 'desc')->take($count)->get();
+        return $this->bookQuery()->orderBy('created_at', 'desc')->take($count)->get();
     }
 
     /**
@@ -76,6 +91,7 @@ class BookRepo
      */
     public function getRecentlyViewed($count = 10, $page = 0)
     {
+        // TODO restrict
         return Views::getUserRecentlyViewed($count, $page, $this->book);
     }
 
@@ -87,6 +103,7 @@ class BookRepo
      */
     public function getPopular($count = 10, $page = 0)
     {
+        // TODO - Restrict
         return Views::getPopular($count, $page, $this->book);
     }
 
@@ -97,7 +114,7 @@ class BookRepo
      */
     public function getBySlug($slug)
     {
-        $book = $this->book->where('slug', '=', $slug)->first();
+        $book = $this->bookQuery()->where('slug', '=', $slug)->first();
         if ($book === null) abort(404);
         return $book;
     }
@@ -109,7 +126,7 @@ class BookRepo
      */
     public function exists($id)
     {
-        return $this->book->where('id', '=', $id)->exists();
+        return $this->bookQuery()->where('id', '=', $id)->exists();
     }
 
     /**
@@ -119,17 +136,7 @@ class BookRepo
      */
     public function newFromInput($input)
     {
-        return $this->book->fill($input);
-    }
-
-    /**
-     * Count the amount of books that have a specific slug.
-     * @param $slug
-     * @return mixed
-     */
-    public function countBySlug($slug)
-    {
-        return $this->book->where('slug', '=', $slug)->count();
+        return $this->bookQuery()->fill($input);
     }
 
     /**
@@ -202,8 +209,13 @@ class BookRepo
      */
     public function getChildren(Book $book)
     {
-        $pages = $book->pages()->where('chapter_id', '=', 0)->get();
-        $chapters = $book->chapters()->with('pages')->get();
+        $pageQuery = $book->pages()->where('chapter_id', '=', 0);
+        $this->restrictionService->enforcePageRestrictions($pageQuery, 'view');
+        $pages = $pageQuery->get();
+
+        $chapterQuery = $book->chapters()->with('pages');
+        $this->restrictionService->enforceChapterRestrictions($chapterQuery, 'view');
+        $chapters = $chapterQuery->get();
         $children = $pages->merge($chapters);
         $bookSlug = $book->slug;
         $children->each(function ($child) use ($bookSlug) {
@@ -227,7 +239,7 @@ class BookRepo
     public function getBySearch($term, $count = 20, $paginationAppends = [])
     {
         $terms = explode(' ', $term);
-        $books = $this->book->fullTextSearchQuery(['name', 'description'], $terms)
+        $books = $this->restrictionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms))
             ->paginate($count)->appends($paginationAppends);
         $words = join('|', explode(' ', preg_quote(trim($term), '/')));
         foreach ($books as $book) {
@@ -249,11 +261,11 @@ class BookRepo
         $book->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
         $book->restrictions()->delete();
         if ($request->has('restrictions')) {
-            foreach($request->get('restrictions') as $roleId => $restrictions) {
+            foreach ($request->get('restrictions') as $roleId => $restrictions) {
                 foreach ($restrictions as $action => $value) {
                     $book->restrictions()->create([
                         'role_id' => $roleId,
-                        'action'  => strtolower($action)
+                        'action' => strtolower($action)
                     ]);
                 }
             }
diff --git a/app/Repos/ChapterRepo.php b/app/Repos/ChapterRepo.php
index 7e3560f2b..90f2f8c54 100644
--- a/app/Repos/ChapterRepo.php
+++ b/app/Repos/ChapterRepo.php
@@ -2,6 +2,7 @@
 
 
 use Activity;
+use BookStack\Services\RestrictionService;
 use Illuminate\Support\Str;
 use BookStack\Chapter;
 
@@ -9,14 +10,26 @@ class ChapterRepo
 {
 
     protected $chapter;
+    protected $restrictionService;
 
     /**
      * ChapterRepo constructor.
-     * @param $chapter
+     * @param Chapter $chapter
+     * @param RestrictionService $restrictionService
      */
-    public function __construct(Chapter $chapter)
+    public function __construct(Chapter $chapter, RestrictionService $restrictionService)
     {
         $this->chapter = $chapter;
+        $this->restrictionService = $restrictionService;
+    }
+
+    /**
+     * Base query for getting chapters, Takes restrictions into account.
+     * @return mixed
+     */
+    private function chapterQuery()
+    {
+        return $this->restrictionService->enforceChapterRestrictions($this->chapter, 'view');
     }
 
     /**
@@ -26,7 +39,7 @@ class ChapterRepo
      */
     public function idExists($id)
     {
-        return $this->chapter->where('id', '=', $id)->count() > 0;
+        return $this->chapterQuery()->where('id', '=', $id)->count() > 0;
     }
 
     /**
@@ -36,7 +49,7 @@ class ChapterRepo
      */
     public function getById($id)
     {
-        return $this->chapter->findOrFail($id);
+        return $this->chapterQuery()->findOrFail($id);
     }
 
     /**
@@ -45,7 +58,7 @@ class ChapterRepo
      */
     public function getAll()
     {
-        return $this->chapter->all();
+        return $this->chapterQuery()->all();
     }
 
     /**
@@ -56,7 +69,7 @@ class ChapterRepo
      */
     public function getBySlug($slug, $bookId)
     {
-        $chapter = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
+        $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
         if ($chapter === null) abort(404);
         return $chapter;
     }
@@ -132,7 +145,7 @@ class ChapterRepo
     public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
     {
         $terms = explode(' ', $term);
-        $chapters = $this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms)
+        $chapters = $this->restrictionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms))
             ->paginate($count)->appends($paginationAppends);
         $words = join('|', explode(' ', preg_quote(trim($term), '/')));
         foreach ($chapters as $chapter) {
diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php
index 28942d94a..46e1d98a5 100644
--- a/app/Repos/EntityRepo.php
+++ b/app/Repos/EntityRepo.php
@@ -4,6 +4,7 @@
 use BookStack\Book;
 use BookStack\Chapter;
 use BookStack\Page;
+use BookStack\Services\RestrictionService;
 
 class EntityRepo
 {
@@ -11,18 +12,21 @@ class EntityRepo
     public $book;
     public $chapter;
     public $page;
+    private $restrictionService;
 
     /**
      * EntityService constructor.
-     * @param $book
-     * @param $chapter
-     * @param $page
+     * @param Book $book
+     * @param Chapter $chapter
+     * @param Page $page
+     * @param RestrictionService $restrictionService
      */
-    public function __construct(Book $book, Chapter $chapter, Page $page)
+    public function __construct(Book $book, Chapter $chapter, Page $page, RestrictionService $restrictionService)
     {
         $this->book = $book;
         $this->chapter = $chapter;
         $this->page = $page;
+        $this->restrictionService = $restrictionService;
     }
 
     /**
@@ -32,7 +36,8 @@ class EntityRepo
      */
     public function getRecentlyCreatedBooks($count = 20, $page = 0)
     {
-        return $this->book->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get();
+        return $this->restrictionService->enforceBookRestrictions($this->book)
+            ->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get();
     }
 
     /**
@@ -43,7 +48,8 @@ class EntityRepo
      */
     public function getRecentlyUpdatedBooks($count = 20, $page = 0)
     {
-        return $this->book->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get();
+        return $this->restrictionService->enforceBookRestrictions($this->book)
+            ->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get();
     }
 
     /**
@@ -53,7 +59,8 @@ class EntityRepo
      */
     public function getRecentlyCreatedPages($count = 20, $page = 0)
     {
-        return $this->page->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get();
+        return $this->restrictionService->enforcePageRestrictions($this->page)
+            ->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get();
     }
 
     /**
@@ -64,7 +71,8 @@ class EntityRepo
      */
     public function getRecentlyUpdatedPages($count = 20, $page = 0)
     {
-        return $this->page->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get();
+        return $this->restrictionService->enforcePageRestrictions($this->page)
+            ->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get();
     }
 
 
diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php
index 1a98255ab..c4cf00e7c 100644
--- a/app/Repos/PageRepo.php
+++ b/app/Repos/PageRepo.php
@@ -4,6 +4,7 @@
 use Activity;
 use BookStack\Book;
 use BookStack\Chapter;
+use BookStack\Services\RestrictionService;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Log;
@@ -16,26 +17,28 @@ class PageRepo
 {
     protected $page;
     protected $pageRevision;
+    protected $restrictionService;
 
     /**
      * PageRepo constructor.
-     * @param Page         $page
+     * @param Page $page
      * @param PageRevision $pageRevision
+     * @param RestrictionService $restrictionService
      */
-    public function __construct(Page $page, PageRevision $pageRevision)
+    public function __construct(Page $page, PageRevision $pageRevision, RestrictionService $restrictionService)
     {
         $this->page = $page;
         $this->pageRevision = $pageRevision;
+        $this->restrictionService = $restrictionService;
     }
 
     /**
-     * Check if a page id exists.
-     * @param $id
-     * @return bool
+     * Base query for getting pages, Takes restrictions into account.
+     * @return mixed
      */
-    public function idExists($id)
+    private function pageQuery()
     {
-        return $this->page->where('page_id', '=', $id)->count() > 0;
+        return $this->restrictionService->enforcePageRestrictions($this->page, 'view');
     }
 
     /**
@@ -45,16 +48,7 @@ class PageRepo
      */
     public function getById($id)
     {
-        return $this->page->findOrFail($id);
-    }
-
-    /**
-     * Get all pages.
-     * @return \Illuminate\Database\Eloquent\Collection|static[]
-     */
-    public function getAll()
-    {
-        return $this->page->all();
+        return $this->pageQuery()->findOrFail($id);
     }
 
     /**
@@ -65,7 +59,7 @@ class PageRepo
      */
     public function getBySlug($slug, $bookId)
     {
-        $page = $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
+        $page = $this->pageQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
         if ($page === null) throw new NotFoundHttpException('Page not found');
         return $page;
     }
@@ -81,6 +75,9 @@ class PageRepo
     public function findPageUsingOldSlug($pageSlug, $bookSlug)
     {
         $revision = $this->pageRevision->where('slug', '=', $pageSlug)
+            ->whereHas('page', function($query) {
+                $this->restrictionService->enforcePageRestrictions($query);
+            })
             ->where('book_slug', '=', $bookSlug)->orderBy('created_at', 'desc')
             ->with('page')->first();
         return $revision !== null ? $revision->page : null;
@@ -97,16 +94,6 @@ class PageRepo
         return $page;
     }
 
-    /**
-     * Count the pages with a particular slug within a book.
-     * @param $slug
-     * @param $bookId
-     * @return mixed
-     */
-    public function countBySlug($slug, $bookId)
-    {
-        return $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->count();
-    }
 
     /**
      * Save a new page into the system.
@@ -202,7 +189,7 @@ class PageRepo
     public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
     {
         $terms = explode(' ', $term);
-        $pages = $this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms)
+        $pages = $this->restrictionService->enforcePageRestrictions($this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms))
             ->paginate($count)->appends($paginationAppends);
 
         // Add highlights to page text.
@@ -240,7 +227,7 @@ class PageRepo
      */
     public function searchForImage($imageString)
     {
-        $pages = $this->page->where('html', 'like', '%' . $imageString . '%')->get();
+        $pages = $this->pageQuery()->where('html', 'like', '%' . $imageString . '%')->get();
         foreach ($pages as $page) {
             $page->url = $page->getUrl();
             $page->html = '';
@@ -395,7 +382,7 @@ class PageRepo
      */
     public function getRecentlyCreatedPaginated($count = 20)
     {
-        return $this->page->orderBy('created_at', 'desc')->paginate($count);
+        return $this->pageQuery()->orderBy('created_at', 'desc')->paginate($count);
     }
 
     /**
@@ -404,7 +391,7 @@ class PageRepo
      */
     public function getRecentlyUpdatedPaginated($count = 20)
     {
-        return $this->page->orderBy('updated_at', 'desc')->paginate($count);
+        return $this->pageQuery()->orderBy('updated_at', 'desc')->paginate($count);
     }
 
     /**
diff --git a/app/Services/ActivityService.php b/app/Services/ActivityService.php
index a065ae01f..a57210b8d 100644
--- a/app/Services/ActivityService.php
+++ b/app/Services/ActivityService.php
@@ -9,14 +9,17 @@ class ActivityService
 {
     protected $activity;
     protected $user;
+    protected $restrictionService;
 
     /**
      * ActivityService constructor.
-     * @param $activity
+     * @param Activity $activity
+     * @param RestrictionService $restrictionService
      */
-    public function __construct(Activity $activity)
+    public function __construct(Activity $activity, RestrictionService $restrictionService)
     {
         $this->activity = $activity;
+        $this->restrictionService = $restrictionService;
         $this->user = auth()->user();
     }
 
@@ -86,8 +89,10 @@ class ActivityService
      */
     public function latest($count = 20, $page = 0)
     {
-        $activityList =  $this->activity->orderBy('created_at', 'desc')
-            ->skip($count * $page)->take($count)->get();
+        $activityList =  $this->restrictionService
+            ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type')
+            ->orderBy('created_at', 'desc')->skip($count * $page)->take($count)->get();
+
         return $this->filterSimilar($activityList);
     }
 
diff --git a/app/Services/RestrictionService.php b/app/Services/RestrictionService.php
new file mode 100644
index 000000000..87dcbf0b3
--- /dev/null
+++ b/app/Services/RestrictionService.php
@@ -0,0 +1,230 @@
+<?php namespace BookStack\Services;
+
+class RestrictionService
+{
+
+    protected $userRoles;
+    protected $isAdmin;
+    protected $currentAction;
+
+    /**
+     * RestrictionService constructor.
+     */
+    public function __construct()
+    {
+        $this->userRoles = auth()->user()->roles->pluck('id');
+        $this->isAdmin = auth()->user()->hasRole('admin');
+    }
+
+    /**
+     * Add restrictions for a page query
+     * @param $query
+     * @param string $action
+     * @return mixed
+     */
+    public function enforcePageRestrictions($query, $action = 'view')
+    {
+        if ($this->isAdmin) return $query;
+        $this->currentAction = $action;
+        return $this->pageRestrictionQuery($query);
+    }
+
+    /**
+     * The base query for restricting pages.
+     * @param $query
+     * @return mixed
+     */
+    private function pageRestrictionQuery($query)
+    {
+        return $query->where(function ($parentWhereQuery) {
+
+            $parentWhereQuery
+                // (Book & chapter & page) or (Book & page & NO CHAPTER) unrestricted
+                ->where(function ($query) {
+                    $query->where(function ($query) {
+                        $query->whereExists(function ($query) {
+                            $query->select('*')->from('chapters')
+                                ->whereRaw('chapters.id=pages.chapter_id')
+                                ->where('restricted', '=', false);
+                        })->whereExists(function ($query) {
+                            $query->select('*')->from('books')
+                                ->whereRaw('books.id=pages.book_id')
+                                ->where('restricted', '=', false);
+                        })->where('restricted', '=', false);
+                    })->orWhere(function ($query) {
+                        $query->where('restricted', '=', false)->where('chapter_id', '=', 0)
+                            ->whereExists(function ($query) {
+                                $query->select('*')->from('books')
+                                    ->whereRaw('books.id=pages.book_id')
+                                    ->where('restricted', '=', false);
+                            });
+                    });
+                })
+                // Page unrestricted, Has no chapter & book has accepted restrictions
+                ->orWhere(function ($query) {
+                    $query->where('restricted', '=', false)
+                        ->whereExists(function ($query) {
+                            $query->select('*')->from('chapters')
+                                ->whereRaw('chapters.id=pages.chapter_id');
+                        }, 'and', true)
+                        ->whereExists(function ($query) {
+                            $query->select('*')->from('books')
+                                ->whereRaw('books.id=pages.book_id')
+                                ->whereExists(function ($query) {
+                                    $this->checkRestrictionsQuery($query, 'books', 'Book');
+                                });
+                        });
+                })
+                // Page unrestricted, Has a chapter with accepted permissions
+                ->orWhere(function ($query) {
+                    $query->where('restricted', '=', false)
+                        ->whereExists(function ($query) {
+                            $query->select('*')->from('chapters')
+                                ->whereRaw('chapters.id=pages.chapter_id')
+                                ->whereExists(function ($query) {
+                                    $this->checkRestrictionsQuery($query, 'chapters', 'Chapter');
+                                });
+                        });
+                })
+                // Page has accepted permissions
+                ->orWhereExists(function ($query) {
+                    $this->checkRestrictionsQuery($query, 'pages', 'Page');
+                });
+        });
+    }
+
+    /**
+     * Add on permission restrictions to a chapter query.
+     * @param $query
+     * @param string $action
+     * @return mixed
+     */
+    public function enforceChapterRestrictions($query, $action = 'view')
+    {
+        if ($this->isAdmin) return $query;
+        $this->currentAction = $action;
+        return $this->chapterRestrictionQuery($query);
+    }
+
+    /**
+     * The base query for restricting chapters.
+     * @param $query
+     * @return mixed
+     */
+    private function chapterRestrictionQuery($query)
+    {
+        return $query->where(function ($parentWhereQuery) {
+
+            $parentWhereQuery
+                // Book & chapter unrestricted
+                ->where(function ($query) {
+                    $query->where('restricted', '=', false)->whereExists(function ($query) {
+                        $query->select('*')->from('books')
+                            ->whereRaw('books.id=chapters.book_id')
+                            ->where('restricted', '=', false);
+                    });
+                })
+                // Chapter unrestricted & book has accepted restrictions
+                ->orWhere(function ($query) {
+                    $query->where('restricted', '=', false)
+                        ->whereExists(function ($query) {
+                            $query->select('*')->from('books')
+                                ->whereRaw('books.id=chapters.book_id')
+                                ->whereExists(function ($query) {
+                                    $this->checkRestrictionsQuery($query, 'books', 'Book');
+                                });
+                        });
+                })
+                // Chapter has accepted permissions
+                ->orWhereExists(function ($query) {
+                    $this->checkRestrictionsQuery($query, 'chapters', 'Chapter');
+                });
+        });
+    }
+
+    /**
+     * Add restrictions to a book query.
+     * @param $query
+     * @param string $action
+     * @return mixed
+     */
+    public function enforceBookRestrictions($query, $action = 'view')
+    {
+        if ($this->isAdmin) return $query;
+        $this->currentAction = $action;
+        return $this->bookRestrictionQuery($query);
+    }
+
+    /**
+     * The base query for restricting books.
+     * @param $query
+     * @return mixed
+     */
+    private function bookRestrictionQuery($query)
+    {
+        return $query->where(function ($parentWhereQuery) {
+            $parentWhereQuery
+                ->where('restricted', '=', false)
+                ->orWhereExists(function ($query) {
+                    $this->checkRestrictionsQuery($query, 'books', 'Book');
+                });
+        });
+    }
+
+    /**
+     * Filter items that have entities set a a polymorphic relation.
+     * @param $query
+     * @param string $tableName
+     * @param string $entityIdColumn
+     * @param string $entityTypeColumn
+     * @return mixed
+     */
+    public function filterRestrictedEntityRelations($query, $tableName, $entityIdColumn, $entityTypeColumn)
+    {
+        if ($this->isAdmin) return $query;
+        $this->currentAction = 'view';
+        $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
+        return $query->where(function($query) use ($tableDetails) {
+            $query->where(function ($query) use (&$tableDetails) {
+                $query->where($tableDetails['entityTypeColumn'], '=', 'BookStack\Page')
+                    ->whereExists(function ($query) use (&$tableDetails) {
+                        $query->select('*')->from('pages')->whereRaw('pages.id='.$tableDetails['tableName'].'.'.$tableDetails['entityIdColumn'])
+                            ->where(function ($query) {
+                                $this->pageRestrictionQuery($query);
+                            });
+                    });
+            })->orWhere(function ($query) use (&$tableDetails) {
+                $query->where($tableDetails['entityTypeColumn'], '=', 'BookStack\Book')->whereExists(function ($query) use (&$tableDetails) {
+                    $query->select('*')->from('books')->whereRaw('books.id='.$tableDetails['tableName'].'.'.$tableDetails['entityIdColumn'])
+                        ->where(function ($query) {
+                            $this->bookRestrictionQuery($query);
+                        });
+                });
+            })->orWhere(function ($query) use (&$tableDetails) {
+                $query->where($tableDetails['entityTypeColumn'], '=', 'BookStack\Chapter')->whereExists(function ($query) use (&$tableDetails) {
+                    $query->select('*')->from('chapters')->whereRaw('chapters.id='.$tableDetails['tableName'].'.'.$tableDetails['entityIdColumn'])
+                        ->where(function ($query) {
+                            $this->chapterRestrictionQuery($query);
+                        });
+                });
+            });
+        });
+    }
+
+    /**
+     * The query to check the restrictions on an entity.
+     * @param $query
+     * @param $tableName
+     * @param $modelName
+     */
+    private function checkRestrictionsQuery($query, $tableName, $modelName)
+    {
+        $query->select('*')->from('restrictions')
+            ->whereRaw('restrictions.restrictable_id=' . $tableName . '.id')
+            ->where('restrictions.restrictable_type', '=', 'BookStack\\' . $modelName)
+            ->where('restrictions.action', '=', $this->currentAction)
+            ->whereIn('restrictions.role_id', $this->userRoles);
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/Services/ViewService.php b/app/Services/ViewService.php
index 5b800d939..75ffd21dc 100644
--- a/app/Services/ViewService.php
+++ b/app/Services/ViewService.php
@@ -9,15 +9,18 @@ class ViewService
 
     protected $view;
     protected $user;
+    protected $restrictionService;
 
     /**
      * ViewService constructor.
-     * @param $view
+     * @param View $view
+     * @param RestrictionService $restrictionService
      */
-    public function __construct(View $view)
+    public function __construct(View $view, RestrictionService $restrictionService)
     {
         $this->view = $view;
         $this->user = auth()->user();
+        $this->restrictionService = $restrictionService;
     }
 
     /**
@@ -27,7 +30,7 @@ class ViewService
      */
     public function add(Entity $entity)
     {
-        if($this->user === null) return 0;
+        if ($this->user === null) return 0;
         $view = $entity->views()->where('user_id', '=', $this->user->id)->first();
         // Add view if model exists
         if ($view) {
@@ -47,18 +50,19 @@ class ViewService
 
     /**
      * Get the entities with the most views.
-     * @param int        $count
-     * @param int        $page
+     * @param int $count
+     * @param int $page
      * @param bool|false $filterModel
      */
     public function getPopular($count = 10, $page = 0, $filterModel = false)
     {
         $skipCount = $count * $page;
-        $query = $this->view->select('id', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count'))
+        $query = $this->restrictionService->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type')
+            ->select('id', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count'))
             ->groupBy('viewable_id', 'viewable_type')
             ->orderBy('view_count', 'desc');
 
-        if($filterModel) $query->where('viewable_type', '=', get_class($filterModel));
+        if ($filterModel) $query->where('viewable_type', '=', get_class($filterModel));
 
         $views = $query->with('viewable')->skip($skipCount)->take($count)->get();
         $viewedEntities = $views->map(function ($item) {
@@ -69,22 +73,24 @@ class ViewService
 
     /**
      * Get all recently viewed entities for the current user.
-     * @param int         $count
-     * @param int         $page
+     * @param int $count
+     * @param int $page
      * @param Entity|bool $filterModel
      * @return mixed
      */
     public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false)
     {
-        if($this->user === null) return collect();
+        if ($this->user === null) return collect();
         $skipCount = $count * $page;
-        $query = $this->view->where('user_id', '=', auth()->user()->id);
+        $query = $this->restrictionService
+            ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type');
 
-        if ($filterModel) $query->where('viewable_type', '=', get_class($filterModel));
+        if ($filterModel) $query = $query->where('viewable_type', '=', get_class($filterModel));
+        $query = $query->where('user_id', '=', auth()->user()->id);
 
         $views = $query->with('viewable')->orderBy('updated_at', 'desc')->skip($skipCount)->take($count)->get();
         $viewedEntities = $views->map(function ($item) {
-            return $item->viewable()->getResults();
+            return $item->viewable;
         });
         return $viewedEntities;
     }
diff --git a/resources/views/partials/activity-item.blade.php b/resources/views/partials/activity-item.blade.php
index f94fad5e1..00ca574dd 100644
--- a/resources/views/partials/activity-item.blade.php
+++ b/resources/views/partials/activity-item.blade.php
@@ -17,7 +17,7 @@
     {{ $activity->getText() }}
 
     @if($activity->entity())
-        <a href="{{ $activity->entity()->getUrl() }}">{{ $activity->entity()->name }}</a>
+        <a href="{{ $activity->entity->getUrl() }}">{{ $activity->entity->name }}</a>
     @endif
 
     @if($activity->extra) "{{$activity->extra}}" @endif