Dan Brown

Added in restriction queries for most lists

...@@ -19,11 +19,7 @@ class Activity extends Model ...@@ -19,11 +19,7 @@ class Activity extends Model
19 */ 19 */
20 public function entity() 20 public function entity()
21 { 21 {
22 - if ($this->entity_id) { 22 + return $this->morphTo('entity');
23 - return $this->morphTo('entity')->first();
24 - } else {
25 - return false;
26 - }
27 } 23 }
28 24
29 /** 25 /**
......
...@@ -28,11 +28,17 @@ class CustomFacadeProvider extends ServiceProvider ...@@ -28,11 +28,17 @@ class CustomFacadeProvider extends ServiceProvider
28 public function register() 28 public function register()
29 { 29 {
30 $this->app->bind('activity', function() { 30 $this->app->bind('activity', function() {
31 - return new ActivityService($this->app->make('BookStack\Activity')); 31 + return new ActivityService(
32 + $this->app->make('BookStack\Activity'),
33 + $this->app->make('BookStack\Services\RestrictionService')
34 + );
32 }); 35 });
33 36
34 $this->app->bind('views', function() { 37 $this->app->bind('views', function() {
35 - return new ViewService($this->app->make('BookStack\View')); 38 + return new ViewService(
39 + $this->app->make('BookStack\View'),
40 + $this->app->make('BookStack\Services\RestrictionService')
41 + );
36 }); 42 });
37 43
38 $this->app->bind('setting', function() { 44 $this->app->bind('setting', function() {
...@@ -41,6 +47,7 @@ class CustomFacadeProvider extends ServiceProvider ...@@ -41,6 +47,7 @@ class CustomFacadeProvider extends ServiceProvider
41 $this->app->make('Illuminate\Contracts\Cache\Repository') 47 $this->app->make('Illuminate\Contracts\Cache\Repository')
42 ); 48 );
43 }); 49 });
50 +
44 $this->app->bind('images', function() { 51 $this->app->bind('images', function() {
45 return new ImageService( 52 return new ImageService(
46 $this->app->make('Intervention\Image\ImageManager'), 53 $this->app->make('Intervention\Image\ImageManager'),
......
1 <?php namespace BookStack\Repos; 1 <?php namespace BookStack\Repos;
2 2
3 use Activity; 3 use Activity;
4 +use BookStack\Services\RestrictionService;
4 use Illuminate\Support\Str; 5 use Illuminate\Support\Str;
5 use BookStack\Book; 6 use BookStack\Book;
6 use Views; 7 use Views;
...@@ -11,18 +12,31 @@ class BookRepo ...@@ -11,18 +12,31 @@ class BookRepo
11 protected $book; 12 protected $book;
12 protected $pageRepo; 13 protected $pageRepo;
13 protected $chapterRepo; 14 protected $chapterRepo;
15 + protected $restrictionService;
14 16
15 /** 17 /**
16 * BookRepo constructor. 18 * BookRepo constructor.
17 * @param Book $book 19 * @param Book $book
18 * @param PageRepo $pageRepo 20 * @param PageRepo $pageRepo
19 * @param ChapterRepo $chapterRepo 21 * @param ChapterRepo $chapterRepo
22 + * @param RestrictionService $restrictionService
20 */ 23 */
21 - public function __construct(Book $book, PageRepo $pageRepo, ChapterRepo $chapterRepo) 24 + public function __construct(Book $book, PageRepo $pageRepo, ChapterRepo $chapterRepo, RestrictionService $restrictionService)
22 { 25 {
23 $this->book = $book; 26 $this->book = $book;
24 $this->pageRepo = $pageRepo; 27 $this->pageRepo = $pageRepo;
25 $this->chapterRepo = $chapterRepo; 28 $this->chapterRepo = $chapterRepo;
29 + $this->restrictionService = $restrictionService;
30 + }
31 +
32 + /**
33 + * Base query for getting books.
34 + * Takes into account any restrictions.
35 + * @return mixed
36 + */
37 + private function bookQuery()
38 + {
39 + return $this->restrictionService->enforceBookRestrictions($this->book, 'view');
26 } 40 }
27 41
28 /** 42 /**
...@@ -32,7 +46,7 @@ class BookRepo ...@@ -32,7 +46,7 @@ class BookRepo
32 */ 46 */
33 public function getById($id) 47 public function getById($id)
34 { 48 {
35 - return $this->book->findOrFail($id); 49 + return $this->bookQuery()->findOrFail($id);
36 } 50 }
37 51
38 /** 52 /**
...@@ -42,7 +56,7 @@ class BookRepo ...@@ -42,7 +56,7 @@ class BookRepo
42 */ 56 */
43 public function getAll($count = 10) 57 public function getAll($count = 10)
44 { 58 {
45 - $bookQuery = $this->book->orderBy('name', 'asc'); 59 + $bookQuery = $this->bookQuery()->orderBy('name', 'asc');
46 if (!$count) return $bookQuery->get(); 60 if (!$count) return $bookQuery->get();
47 return $bookQuery->take($count)->get(); 61 return $bookQuery->take($count)->get();
48 } 62 }
...@@ -54,7 +68,8 @@ class BookRepo ...@@ -54,7 +68,8 @@ class BookRepo
54 */ 68 */
55 public function getAllPaginated($count = 10) 69 public function getAllPaginated($count = 10)
56 { 70 {
57 - return $this->book->orderBy('name', 'asc')->paginate($count); 71 + return $this->bookQuery()
72 + ->orderBy('name', 'asc')->paginate($count);
58 } 73 }
59 74
60 75
...@@ -65,7 +80,7 @@ class BookRepo ...@@ -65,7 +80,7 @@ class BookRepo
65 */ 80 */
66 public function getLatest($count = 10) 81 public function getLatest($count = 10)
67 { 82 {
68 - return $this->book->orderBy('created_at', 'desc')->take($count)->get(); 83 + return $this->bookQuery()->orderBy('created_at', 'desc')->take($count)->get();
69 } 84 }
70 85
71 /** 86 /**
...@@ -76,6 +91,7 @@ class BookRepo ...@@ -76,6 +91,7 @@ class BookRepo
76 */ 91 */
77 public function getRecentlyViewed($count = 10, $page = 0) 92 public function getRecentlyViewed($count = 10, $page = 0)
78 { 93 {
94 + // TODO restrict
79 return Views::getUserRecentlyViewed($count, $page, $this->book); 95 return Views::getUserRecentlyViewed($count, $page, $this->book);
80 } 96 }
81 97
...@@ -87,6 +103,7 @@ class BookRepo ...@@ -87,6 +103,7 @@ class BookRepo
87 */ 103 */
88 public function getPopular($count = 10, $page = 0) 104 public function getPopular($count = 10, $page = 0)
89 { 105 {
106 + // TODO - Restrict
90 return Views::getPopular($count, $page, $this->book); 107 return Views::getPopular($count, $page, $this->book);
91 } 108 }
92 109
...@@ -97,7 +114,7 @@ class BookRepo ...@@ -97,7 +114,7 @@ class BookRepo
97 */ 114 */
98 public function getBySlug($slug) 115 public function getBySlug($slug)
99 { 116 {
100 - $book = $this->book->where('slug', '=', $slug)->first(); 117 + $book = $this->bookQuery()->where('slug', '=', $slug)->first();
101 if ($book === null) abort(404); 118 if ($book === null) abort(404);
102 return $book; 119 return $book;
103 } 120 }
...@@ -109,7 +126,7 @@ class BookRepo ...@@ -109,7 +126,7 @@ class BookRepo
109 */ 126 */
110 public function exists($id) 127 public function exists($id)
111 { 128 {
112 - return $this->book->where('id', '=', $id)->exists(); 129 + return $this->bookQuery()->where('id', '=', $id)->exists();
113 } 130 }
114 131
115 /** 132 /**
...@@ -119,17 +136,7 @@ class BookRepo ...@@ -119,17 +136,7 @@ class BookRepo
119 */ 136 */
120 public function newFromInput($input) 137 public function newFromInput($input)
121 { 138 {
122 - return $this->book->fill($input); 139 + return $this->bookQuery()->fill($input);
123 - }
124 -
125 - /**
126 - * Count the amount of books that have a specific slug.
127 - * @param $slug
128 - * @return mixed
129 - */
130 - public function countBySlug($slug)
131 - {
132 - return $this->book->where('slug', '=', $slug)->count();
133 } 140 }
134 141
135 /** 142 /**
...@@ -202,8 +209,13 @@ class BookRepo ...@@ -202,8 +209,13 @@ class BookRepo
202 */ 209 */
203 public function getChildren(Book $book) 210 public function getChildren(Book $book)
204 { 211 {
205 - $pages = $book->pages()->where('chapter_id', '=', 0)->get(); 212 + $pageQuery = $book->pages()->where('chapter_id', '=', 0);
206 - $chapters = $book->chapters()->with('pages')->get(); 213 + $this->restrictionService->enforcePageRestrictions($pageQuery, 'view');
214 + $pages = $pageQuery->get();
215 +
216 + $chapterQuery = $book->chapters()->with('pages');
217 + $this->restrictionService->enforceChapterRestrictions($chapterQuery, 'view');
218 + $chapters = $chapterQuery->get();
207 $children = $pages->merge($chapters); 219 $children = $pages->merge($chapters);
208 $bookSlug = $book->slug; 220 $bookSlug = $book->slug;
209 $children->each(function ($child) use ($bookSlug) { 221 $children->each(function ($child) use ($bookSlug) {
...@@ -227,7 +239,7 @@ class BookRepo ...@@ -227,7 +239,7 @@ class BookRepo
227 public function getBySearch($term, $count = 20, $paginationAppends = []) 239 public function getBySearch($term, $count = 20, $paginationAppends = [])
228 { 240 {
229 $terms = explode(' ', $term); 241 $terms = explode(' ', $term);
230 - $books = $this->book->fullTextSearchQuery(['name', 'description'], $terms) 242 + $books = $this->restrictionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms))
231 ->paginate($count)->appends($paginationAppends); 243 ->paginate($count)->appends($paginationAppends);
232 $words = join('|', explode(' ', preg_quote(trim($term), '/'))); 244 $words = join('|', explode(' ', preg_quote(trim($term), '/')));
233 foreach ($books as $book) { 245 foreach ($books as $book) {
...@@ -249,11 +261,11 @@ class BookRepo ...@@ -249,11 +261,11 @@ class BookRepo
249 $book->restricted = $request->has('restricted') && $request->get('restricted') === 'true'; 261 $book->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
250 $book->restrictions()->delete(); 262 $book->restrictions()->delete();
251 if ($request->has('restrictions')) { 263 if ($request->has('restrictions')) {
252 - foreach($request->get('restrictions') as $roleId => $restrictions) { 264 + foreach ($request->get('restrictions') as $roleId => $restrictions) {
253 foreach ($restrictions as $action => $value) { 265 foreach ($restrictions as $action => $value) {
254 $book->restrictions()->create([ 266 $book->restrictions()->create([
255 'role_id' => $roleId, 267 'role_id' => $roleId,
256 - 'action' => strtolower($action) 268 + 'action' => strtolower($action)
257 ]); 269 ]);
258 } 270 }
259 } 271 }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
2 2
3 3
4 use Activity; 4 use Activity;
5 +use BookStack\Services\RestrictionService;
5 use Illuminate\Support\Str; 6 use Illuminate\Support\Str;
6 use BookStack\Chapter; 7 use BookStack\Chapter;
7 8
...@@ -9,14 +10,26 @@ class ChapterRepo ...@@ -9,14 +10,26 @@ class ChapterRepo
9 { 10 {
10 11
11 protected $chapter; 12 protected $chapter;
13 + protected $restrictionService;
12 14
13 /** 15 /**
14 * ChapterRepo constructor. 16 * ChapterRepo constructor.
15 - * @param $chapter 17 + * @param Chapter $chapter
18 + * @param RestrictionService $restrictionService
16 */ 19 */
17 - public function __construct(Chapter $chapter) 20 + public function __construct(Chapter $chapter, RestrictionService $restrictionService)
18 { 21 {
19 $this->chapter = $chapter; 22 $this->chapter = $chapter;
23 + $this->restrictionService = $restrictionService;
24 + }
25 +
26 + /**
27 + * Base query for getting chapters, Takes restrictions into account.
28 + * @return mixed
29 + */
30 + private function chapterQuery()
31 + {
32 + return $this->restrictionService->enforceChapterRestrictions($this->chapter, 'view');
20 } 33 }
21 34
22 /** 35 /**
...@@ -26,7 +39,7 @@ class ChapterRepo ...@@ -26,7 +39,7 @@ class ChapterRepo
26 */ 39 */
27 public function idExists($id) 40 public function idExists($id)
28 { 41 {
29 - return $this->chapter->where('id', '=', $id)->count() > 0; 42 + return $this->chapterQuery()->where('id', '=', $id)->count() > 0;
30 } 43 }
31 44
32 /** 45 /**
...@@ -36,7 +49,7 @@ class ChapterRepo ...@@ -36,7 +49,7 @@ class ChapterRepo
36 */ 49 */
37 public function getById($id) 50 public function getById($id)
38 { 51 {
39 - return $this->chapter->findOrFail($id); 52 + return $this->chapterQuery()->findOrFail($id);
40 } 53 }
41 54
42 /** 55 /**
...@@ -45,7 +58,7 @@ class ChapterRepo ...@@ -45,7 +58,7 @@ class ChapterRepo
45 */ 58 */
46 public function getAll() 59 public function getAll()
47 { 60 {
48 - return $this->chapter->all(); 61 + return $this->chapterQuery()->all();
49 } 62 }
50 63
51 /** 64 /**
...@@ -56,7 +69,7 @@ class ChapterRepo ...@@ -56,7 +69,7 @@ class ChapterRepo
56 */ 69 */
57 public function getBySlug($slug, $bookId) 70 public function getBySlug($slug, $bookId)
58 { 71 {
59 - $chapter = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first(); 72 + $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
60 if ($chapter === null) abort(404); 73 if ($chapter === null) abort(404);
61 return $chapter; 74 return $chapter;
62 } 75 }
...@@ -132,7 +145,7 @@ class ChapterRepo ...@@ -132,7 +145,7 @@ class ChapterRepo
132 public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = []) 145 public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
133 { 146 {
134 $terms = explode(' ', $term); 147 $terms = explode(' ', $term);
135 - $chapters = $this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms) 148 + $chapters = $this->restrictionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms))
136 ->paginate($count)->appends($paginationAppends); 149 ->paginate($count)->appends($paginationAppends);
137 $words = join('|', explode(' ', preg_quote(trim($term), '/'))); 150 $words = join('|', explode(' ', preg_quote(trim($term), '/')));
138 foreach ($chapters as $chapter) { 151 foreach ($chapters as $chapter) {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
4 use BookStack\Book; 4 use BookStack\Book;
5 use BookStack\Chapter; 5 use BookStack\Chapter;
6 use BookStack\Page; 6 use BookStack\Page;
7 +use BookStack\Services\RestrictionService;
7 8
8 class EntityRepo 9 class EntityRepo
9 { 10 {
...@@ -11,18 +12,21 @@ class EntityRepo ...@@ -11,18 +12,21 @@ class EntityRepo
11 public $book; 12 public $book;
12 public $chapter; 13 public $chapter;
13 public $page; 14 public $page;
15 + private $restrictionService;
14 16
15 /** 17 /**
16 * EntityService constructor. 18 * EntityService constructor.
17 - * @param $book 19 + * @param Book $book
18 - * @param $chapter 20 + * @param Chapter $chapter
19 - * @param $page 21 + * @param Page $page
22 + * @param RestrictionService $restrictionService
20 */ 23 */
21 - public function __construct(Book $book, Chapter $chapter, Page $page) 24 + public function __construct(Book $book, Chapter $chapter, Page $page, RestrictionService $restrictionService)
22 { 25 {
23 $this->book = $book; 26 $this->book = $book;
24 $this->chapter = $chapter; 27 $this->chapter = $chapter;
25 $this->page = $page; 28 $this->page = $page;
29 + $this->restrictionService = $restrictionService;
26 } 30 }
27 31
28 /** 32 /**
...@@ -32,7 +36,8 @@ class EntityRepo ...@@ -32,7 +36,8 @@ class EntityRepo
32 */ 36 */
33 public function getRecentlyCreatedBooks($count = 20, $page = 0) 37 public function getRecentlyCreatedBooks($count = 20, $page = 0)
34 { 38 {
35 - return $this->book->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get(); 39 + return $this->restrictionService->enforceBookRestrictions($this->book)
40 + ->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get();
36 } 41 }
37 42
38 /** 43 /**
...@@ -43,7 +48,8 @@ class EntityRepo ...@@ -43,7 +48,8 @@ class EntityRepo
43 */ 48 */
44 public function getRecentlyUpdatedBooks($count = 20, $page = 0) 49 public function getRecentlyUpdatedBooks($count = 20, $page = 0)
45 { 50 {
46 - return $this->book->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get(); 51 + return $this->restrictionService->enforceBookRestrictions($this->book)
52 + ->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get();
47 } 53 }
48 54
49 /** 55 /**
...@@ -53,7 +59,8 @@ class EntityRepo ...@@ -53,7 +59,8 @@ class EntityRepo
53 */ 59 */
54 public function getRecentlyCreatedPages($count = 20, $page = 0) 60 public function getRecentlyCreatedPages($count = 20, $page = 0)
55 { 61 {
56 - return $this->page->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get(); 62 + return $this->restrictionService->enforcePageRestrictions($this->page)
63 + ->orderBy('created_at', 'desc')->skip($page*$count)->take($count)->get();
57 } 64 }
58 65
59 /** 66 /**
...@@ -64,7 +71,8 @@ class EntityRepo ...@@ -64,7 +71,8 @@ class EntityRepo
64 */ 71 */
65 public function getRecentlyUpdatedPages($count = 20, $page = 0) 72 public function getRecentlyUpdatedPages($count = 20, $page = 0)
66 { 73 {
67 - return $this->page->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get(); 74 + return $this->restrictionService->enforcePageRestrictions($this->page)
75 + ->orderBy('updated_at', 'desc')->skip($page*$count)->take($count)->get();
68 } 76 }
69 77
70 78
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
4 use Activity; 4 use Activity;
5 use BookStack\Book; 5 use BookStack\Book;
6 use BookStack\Chapter; 6 use BookStack\Chapter;
7 +use BookStack\Services\RestrictionService;
7 use Illuminate\Http\Request; 8 use Illuminate\Http\Request;
8 use Illuminate\Support\Facades\Auth; 9 use Illuminate\Support\Facades\Auth;
9 use Illuminate\Support\Facades\Log; 10 use Illuminate\Support\Facades\Log;
...@@ -16,26 +17,28 @@ class PageRepo ...@@ -16,26 +17,28 @@ class PageRepo
16 { 17 {
17 protected $page; 18 protected $page;
18 protected $pageRevision; 19 protected $pageRevision;
20 + protected $restrictionService;
19 21
20 /** 22 /**
21 * PageRepo constructor. 23 * PageRepo constructor.
22 - * @param Page $page 24 + * @param Page $page
23 * @param PageRevision $pageRevision 25 * @param PageRevision $pageRevision
26 + * @param RestrictionService $restrictionService
24 */ 27 */
25 - public function __construct(Page $page, PageRevision $pageRevision) 28 + public function __construct(Page $page, PageRevision $pageRevision, RestrictionService $restrictionService)
26 { 29 {
27 $this->page = $page; 30 $this->page = $page;
28 $this->pageRevision = $pageRevision; 31 $this->pageRevision = $pageRevision;
32 + $this->restrictionService = $restrictionService;
29 } 33 }
30 34
31 /** 35 /**
32 - * Check if a page id exists. 36 + * Base query for getting pages, Takes restrictions into account.
33 - * @param $id 37 + * @return mixed
34 - * @return bool
35 */ 38 */
36 - public function idExists($id) 39 + private function pageQuery()
37 { 40 {
38 - return $this->page->where('page_id', '=', $id)->count() > 0; 41 + return $this->restrictionService->enforcePageRestrictions($this->page, 'view');
39 } 42 }
40 43
41 /** 44 /**
...@@ -45,16 +48,7 @@ class PageRepo ...@@ -45,16 +48,7 @@ class PageRepo
45 */ 48 */
46 public function getById($id) 49 public function getById($id)
47 { 50 {
48 - return $this->page->findOrFail($id); 51 + return $this->pageQuery()->findOrFail($id);
49 - }
50 -
51 - /**
52 - * Get all pages.
53 - * @return \Illuminate\Database\Eloquent\Collection|static[]
54 - */
55 - public function getAll()
56 - {
57 - return $this->page->all();
58 } 52 }
59 53
60 /** 54 /**
...@@ -65,7 +59,7 @@ class PageRepo ...@@ -65,7 +59,7 @@ class PageRepo
65 */ 59 */
66 public function getBySlug($slug, $bookId) 60 public function getBySlug($slug, $bookId)
67 { 61 {
68 - $page = $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first(); 62 + $page = $this->pageQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
69 if ($page === null) throw new NotFoundHttpException('Page not found'); 63 if ($page === null) throw new NotFoundHttpException('Page not found');
70 return $page; 64 return $page;
71 } 65 }
...@@ -81,6 +75,9 @@ class PageRepo ...@@ -81,6 +75,9 @@ class PageRepo
81 public function findPageUsingOldSlug($pageSlug, $bookSlug) 75 public function findPageUsingOldSlug($pageSlug, $bookSlug)
82 { 76 {
83 $revision = $this->pageRevision->where('slug', '=', $pageSlug) 77 $revision = $this->pageRevision->where('slug', '=', $pageSlug)
78 + ->whereHas('page', function($query) {
79 + $this->restrictionService->enforcePageRestrictions($query);
80 + })
84 ->where('book_slug', '=', $bookSlug)->orderBy('created_at', 'desc') 81 ->where('book_slug', '=', $bookSlug)->orderBy('created_at', 'desc')
85 ->with('page')->first(); 82 ->with('page')->first();
86 return $revision !== null ? $revision->page : null; 83 return $revision !== null ? $revision->page : null;
...@@ -97,16 +94,6 @@ class PageRepo ...@@ -97,16 +94,6 @@ class PageRepo
97 return $page; 94 return $page;
98 } 95 }
99 96
100 - /**
101 - * Count the pages with a particular slug within a book.
102 - * @param $slug
103 - * @param $bookId
104 - * @return mixed
105 - */
106 - public function countBySlug($slug, $bookId)
107 - {
108 - return $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->count();
109 - }
110 97
111 /** 98 /**
112 * Save a new page into the system. 99 * Save a new page into the system.
...@@ -202,7 +189,7 @@ class PageRepo ...@@ -202,7 +189,7 @@ class PageRepo
202 public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = []) 189 public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
203 { 190 {
204 $terms = explode(' ', $term); 191 $terms = explode(' ', $term);
205 - $pages = $this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms) 192 + $pages = $this->restrictionService->enforcePageRestrictions($this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms))
206 ->paginate($count)->appends($paginationAppends); 193 ->paginate($count)->appends($paginationAppends);
207 194
208 // Add highlights to page text. 195 // Add highlights to page text.
...@@ -240,7 +227,7 @@ class PageRepo ...@@ -240,7 +227,7 @@ class PageRepo
240 */ 227 */
241 public function searchForImage($imageString) 228 public function searchForImage($imageString)
242 { 229 {
243 - $pages = $this->page->where('html', 'like', '%' . $imageString . '%')->get(); 230 + $pages = $this->pageQuery()->where('html', 'like', '%' . $imageString . '%')->get();
244 foreach ($pages as $page) { 231 foreach ($pages as $page) {
245 $page->url = $page->getUrl(); 232 $page->url = $page->getUrl();
246 $page->html = ''; 233 $page->html = '';
...@@ -395,7 +382,7 @@ class PageRepo ...@@ -395,7 +382,7 @@ class PageRepo
395 */ 382 */
396 public function getRecentlyCreatedPaginated($count = 20) 383 public function getRecentlyCreatedPaginated($count = 20)
397 { 384 {
398 - return $this->page->orderBy('created_at', 'desc')->paginate($count); 385 + return $this->pageQuery()->orderBy('created_at', 'desc')->paginate($count);
399 } 386 }
400 387
401 /** 388 /**
...@@ -404,7 +391,7 @@ class PageRepo ...@@ -404,7 +391,7 @@ class PageRepo
404 */ 391 */
405 public function getRecentlyUpdatedPaginated($count = 20) 392 public function getRecentlyUpdatedPaginated($count = 20)
406 { 393 {
407 - return $this->page->orderBy('updated_at', 'desc')->paginate($count); 394 + return $this->pageQuery()->orderBy('updated_at', 'desc')->paginate($count);
408 } 395 }
409 396
410 /** 397 /**
......
...@@ -9,14 +9,17 @@ class ActivityService ...@@ -9,14 +9,17 @@ class ActivityService
9 { 9 {
10 protected $activity; 10 protected $activity;
11 protected $user; 11 protected $user;
12 + protected $restrictionService;
12 13
13 /** 14 /**
14 * ActivityService constructor. 15 * ActivityService constructor.
15 - * @param $activity 16 + * @param Activity $activity
17 + * @param RestrictionService $restrictionService
16 */ 18 */
17 - public function __construct(Activity $activity) 19 + public function __construct(Activity $activity, RestrictionService $restrictionService)
18 { 20 {
19 $this->activity = $activity; 21 $this->activity = $activity;
22 + $this->restrictionService = $restrictionService;
20 $this->user = auth()->user(); 23 $this->user = auth()->user();
21 } 24 }
22 25
...@@ -86,8 +89,10 @@ class ActivityService ...@@ -86,8 +89,10 @@ class ActivityService
86 */ 89 */
87 public function latest($count = 20, $page = 0) 90 public function latest($count = 20, $page = 0)
88 { 91 {
89 - $activityList = $this->activity->orderBy('created_at', 'desc') 92 + $activityList = $this->restrictionService
90 - ->skip($count * $page)->take($count)->get(); 93 + ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type')
94 + ->orderBy('created_at', 'desc')->skip($count * $page)->take($count)->get();
95 +
91 return $this->filterSimilar($activityList); 96 return $this->filterSimilar($activityList);
92 } 97 }
93 98
......
1 +<?php namespace BookStack\Services;
2 +
3 +class RestrictionService
4 +{
5 +
6 + protected $userRoles;
7 + protected $isAdmin;
8 + protected $currentAction;
9 +
10 + /**
11 + * RestrictionService constructor.
12 + */
13 + public function __construct()
14 + {
15 + $this->userRoles = auth()->user()->roles->pluck('id');
16 + $this->isAdmin = auth()->user()->hasRole('admin');
17 + }
18 +
19 + /**
20 + * Add restrictions for a page query
21 + * @param $query
22 + * @param string $action
23 + * @return mixed
24 + */
25 + public function enforcePageRestrictions($query, $action = 'view')
26 + {
27 + if ($this->isAdmin) return $query;
28 + $this->currentAction = $action;
29 + return $this->pageRestrictionQuery($query);
30 + }
31 +
32 + /**
33 + * The base query for restricting pages.
34 + * @param $query
35 + * @return mixed
36 + */
37 + private function pageRestrictionQuery($query)
38 + {
39 + return $query->where(function ($parentWhereQuery) {
40 +
41 + $parentWhereQuery
42 + // (Book & chapter & page) or (Book & page & NO CHAPTER) unrestricted
43 + ->where(function ($query) {
44 + $query->where(function ($query) {
45 + $query->whereExists(function ($query) {
46 + $query->select('*')->from('chapters')
47 + ->whereRaw('chapters.id=pages.chapter_id')
48 + ->where('restricted', '=', false);
49 + })->whereExists(function ($query) {
50 + $query->select('*')->from('books')
51 + ->whereRaw('books.id=pages.book_id')
52 + ->where('restricted', '=', false);
53 + })->where('restricted', '=', false);
54 + })->orWhere(function ($query) {
55 + $query->where('restricted', '=', false)->where('chapter_id', '=', 0)
56 + ->whereExists(function ($query) {
57 + $query->select('*')->from('books')
58 + ->whereRaw('books.id=pages.book_id')
59 + ->where('restricted', '=', false);
60 + });
61 + });
62 + })
63 + // Page unrestricted, Has no chapter & book has accepted restrictions
64 + ->orWhere(function ($query) {
65 + $query->where('restricted', '=', false)
66 + ->whereExists(function ($query) {
67 + $query->select('*')->from('chapters')
68 + ->whereRaw('chapters.id=pages.chapter_id');
69 + }, 'and', true)
70 + ->whereExists(function ($query) {
71 + $query->select('*')->from('books')
72 + ->whereRaw('books.id=pages.book_id')
73 + ->whereExists(function ($query) {
74 + $this->checkRestrictionsQuery($query, 'books', 'Book');
75 + });
76 + });
77 + })
78 + // Page unrestricted, Has a chapter with accepted permissions
79 + ->orWhere(function ($query) {
80 + $query->where('restricted', '=', false)
81 + ->whereExists(function ($query) {
82 + $query->select('*')->from('chapters')
83 + ->whereRaw('chapters.id=pages.chapter_id')
84 + ->whereExists(function ($query) {
85 + $this->checkRestrictionsQuery($query, 'chapters', 'Chapter');
86 + });
87 + });
88 + })
89 + // Page has accepted permissions
90 + ->orWhereExists(function ($query) {
91 + $this->checkRestrictionsQuery($query, 'pages', 'Page');
92 + });
93 + });
94 + }
95 +
96 + /**
97 + * Add on permission restrictions to a chapter query.
98 + * @param $query
99 + * @param string $action
100 + * @return mixed
101 + */
102 + public function enforceChapterRestrictions($query, $action = 'view')
103 + {
104 + if ($this->isAdmin) return $query;
105 + $this->currentAction = $action;
106 + return $this->chapterRestrictionQuery($query);
107 + }
108 +
109 + /**
110 + * The base query for restricting chapters.
111 + * @param $query
112 + * @return mixed
113 + */
114 + private function chapterRestrictionQuery($query)
115 + {
116 + return $query->where(function ($parentWhereQuery) {
117 +
118 + $parentWhereQuery
119 + // Book & chapter unrestricted
120 + ->where(function ($query) {
121 + $query->where('restricted', '=', false)->whereExists(function ($query) {
122 + $query->select('*')->from('books')
123 + ->whereRaw('books.id=chapters.book_id')
124 + ->where('restricted', '=', false);
125 + });
126 + })
127 + // Chapter unrestricted & book has accepted restrictions
128 + ->orWhere(function ($query) {
129 + $query->where('restricted', '=', false)
130 + ->whereExists(function ($query) {
131 + $query->select('*')->from('books')
132 + ->whereRaw('books.id=chapters.book_id')
133 + ->whereExists(function ($query) {
134 + $this->checkRestrictionsQuery($query, 'books', 'Book');
135 + });
136 + });
137 + })
138 + // Chapter has accepted permissions
139 + ->orWhereExists(function ($query) {
140 + $this->checkRestrictionsQuery($query, 'chapters', 'Chapter');
141 + });
142 + });
143 + }
144 +
145 + /**
146 + * Add restrictions to a book query.
147 + * @param $query
148 + * @param string $action
149 + * @return mixed
150 + */
151 + public function enforceBookRestrictions($query, $action = 'view')
152 + {
153 + if ($this->isAdmin) return $query;
154 + $this->currentAction = $action;
155 + return $this->bookRestrictionQuery($query);
156 + }
157 +
158 + /**
159 + * The base query for restricting books.
160 + * @param $query
161 + * @return mixed
162 + */
163 + private function bookRestrictionQuery($query)
164 + {
165 + return $query->where(function ($parentWhereQuery) {
166 + $parentWhereQuery
167 + ->where('restricted', '=', false)
168 + ->orWhereExists(function ($query) {
169 + $this->checkRestrictionsQuery($query, 'books', 'Book');
170 + });
171 + });
172 + }
173 +
174 + /**
175 + * Filter items that have entities set a a polymorphic relation.
176 + * @param $query
177 + * @param string $tableName
178 + * @param string $entityIdColumn
179 + * @param string $entityTypeColumn
180 + * @return mixed
181 + */
182 + public function filterRestrictedEntityRelations($query, $tableName, $entityIdColumn, $entityTypeColumn)
183 + {
184 + if ($this->isAdmin) return $query;
185 + $this->currentAction = 'view';
186 + $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
187 + return $query->where(function($query) use ($tableDetails) {
188 + $query->where(function ($query) use (&$tableDetails) {
189 + $query->where($tableDetails['entityTypeColumn'], '=', 'BookStack\Page')
190 + ->whereExists(function ($query) use (&$tableDetails) {
191 + $query->select('*')->from('pages')->whereRaw('pages.id='.$tableDetails['tableName'].'.'.$tableDetails['entityIdColumn'])
192 + ->where(function ($query) {
193 + $this->pageRestrictionQuery($query);
194 + });
195 + });
196 + })->orWhere(function ($query) use (&$tableDetails) {
197 + $query->where($tableDetails['entityTypeColumn'], '=', 'BookStack\Book')->whereExists(function ($query) use (&$tableDetails) {
198 + $query->select('*')->from('books')->whereRaw('books.id='.$tableDetails['tableName'].'.'.$tableDetails['entityIdColumn'])
199 + ->where(function ($query) {
200 + $this->bookRestrictionQuery($query);
201 + });
202 + });
203 + })->orWhere(function ($query) use (&$tableDetails) {
204 + $query->where($tableDetails['entityTypeColumn'], '=', 'BookStack\Chapter')->whereExists(function ($query) use (&$tableDetails) {
205 + $query->select('*')->from('chapters')->whereRaw('chapters.id='.$tableDetails['tableName'].'.'.$tableDetails['entityIdColumn'])
206 + ->where(function ($query) {
207 + $this->chapterRestrictionQuery($query);
208 + });
209 + });
210 + });
211 + });
212 + }
213 +
214 + /**
215 + * The query to check the restrictions on an entity.
216 + * @param $query
217 + * @param $tableName
218 + * @param $modelName
219 + */
220 + private function checkRestrictionsQuery($query, $tableName, $modelName)
221 + {
222 + $query->select('*')->from('restrictions')
223 + ->whereRaw('restrictions.restrictable_id=' . $tableName . '.id')
224 + ->where('restrictions.restrictable_type', '=', 'BookStack\\' . $modelName)
225 + ->where('restrictions.action', '=', $this->currentAction)
226 + ->whereIn('restrictions.role_id', $this->userRoles);
227 + }
228 +
229 +
230 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -9,15 +9,18 @@ class ViewService ...@@ -9,15 +9,18 @@ class ViewService
9 9
10 protected $view; 10 protected $view;
11 protected $user; 11 protected $user;
12 + protected $restrictionService;
12 13
13 /** 14 /**
14 * ViewService constructor. 15 * ViewService constructor.
15 - * @param $view 16 + * @param View $view
17 + * @param RestrictionService $restrictionService
16 */ 18 */
17 - public function __construct(View $view) 19 + public function __construct(View $view, RestrictionService $restrictionService)
18 { 20 {
19 $this->view = $view; 21 $this->view = $view;
20 $this->user = auth()->user(); 22 $this->user = auth()->user();
23 + $this->restrictionService = $restrictionService;
21 } 24 }
22 25
23 /** 26 /**
...@@ -27,7 +30,7 @@ class ViewService ...@@ -27,7 +30,7 @@ class ViewService
27 */ 30 */
28 public function add(Entity $entity) 31 public function add(Entity $entity)
29 { 32 {
30 - if($this->user === null) return 0; 33 + if ($this->user === null) return 0;
31 $view = $entity->views()->where('user_id', '=', $this->user->id)->first(); 34 $view = $entity->views()->where('user_id', '=', $this->user->id)->first();
32 // Add view if model exists 35 // Add view if model exists
33 if ($view) { 36 if ($view) {
...@@ -47,18 +50,19 @@ class ViewService ...@@ -47,18 +50,19 @@ class ViewService
47 50
48 /** 51 /**
49 * Get the entities with the most views. 52 * Get the entities with the most views.
50 - * @param int $count 53 + * @param int $count
51 - * @param int $page 54 + * @param int $page
52 * @param bool|false $filterModel 55 * @param bool|false $filterModel
53 */ 56 */
54 public function getPopular($count = 10, $page = 0, $filterModel = false) 57 public function getPopular($count = 10, $page = 0, $filterModel = false)
55 { 58 {
56 $skipCount = $count * $page; 59 $skipCount = $count * $page;
57 - $query = $this->view->select('id', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count')) 60 + $query = $this->restrictionService->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type')
61 + ->select('id', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count'))
58 ->groupBy('viewable_id', 'viewable_type') 62 ->groupBy('viewable_id', 'viewable_type')
59 ->orderBy('view_count', 'desc'); 63 ->orderBy('view_count', 'desc');
60 64
61 - if($filterModel) $query->where('viewable_type', '=', get_class($filterModel)); 65 + if ($filterModel) $query->where('viewable_type', '=', get_class($filterModel));
62 66
63 $views = $query->with('viewable')->skip($skipCount)->take($count)->get(); 67 $views = $query->with('viewable')->skip($skipCount)->take($count)->get();
64 $viewedEntities = $views->map(function ($item) { 68 $viewedEntities = $views->map(function ($item) {
...@@ -69,22 +73,24 @@ class ViewService ...@@ -69,22 +73,24 @@ class ViewService
69 73
70 /** 74 /**
71 * Get all recently viewed entities for the current user. 75 * Get all recently viewed entities for the current user.
72 - * @param int $count 76 + * @param int $count
73 - * @param int $page 77 + * @param int $page
74 * @param Entity|bool $filterModel 78 * @param Entity|bool $filterModel
75 * @return mixed 79 * @return mixed
76 */ 80 */
77 public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false) 81 public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false)
78 { 82 {
79 - if($this->user === null) return collect(); 83 + if ($this->user === null) return collect();
80 $skipCount = $count * $page; 84 $skipCount = $count * $page;
81 - $query = $this->view->where('user_id', '=', auth()->user()->id); 85 + $query = $this->restrictionService
86 + ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type');
82 87
83 - if ($filterModel) $query->where('viewable_type', '=', get_class($filterModel)); 88 + if ($filterModel) $query = $query->where('viewable_type', '=', get_class($filterModel));
89 + $query = $query->where('user_id', '=', auth()->user()->id);
84 90
85 $views = $query->with('viewable')->orderBy('updated_at', 'desc')->skip($skipCount)->take($count)->get(); 91 $views = $query->with('viewable')->orderBy('updated_at', 'desc')->skip($skipCount)->take($count)->get();
86 $viewedEntities = $views->map(function ($item) { 92 $viewedEntities = $views->map(function ($item) {
87 - return $item->viewable()->getResults(); 93 + return $item->viewable;
88 }); 94 });
89 return $viewedEntities; 95 return $viewedEntities;
90 } 96 }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
17 {{ $activity->getText() }} 17 {{ $activity->getText() }}
18 18
19 @if($activity->entity()) 19 @if($activity->entity())
20 - <a href="{{ $activity->entity()->getUrl() }}">{{ $activity->entity()->name }}</a> 20 + <a href="{{ $activity->entity->getUrl() }}">{{ $activity->entity->name }}</a>
21 @endif 21 @endif
22 22
23 @if($activity->extra) "{{$activity->extra}}" @endif 23 @if($activity->extra) "{{$activity->extra}}" @endif
......