| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  | <?php namespace BookStack\Services; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  | use BookStack\Book; | 
					
						
							|  |  |  | use BookStack\Chapter; | 
					
						
							| 
									
										
										
										
											2016-03-01 04:31:21 +08:00
										 |  |  | use BookStack\Entity; | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  | use BookStack\JointPermission; | 
					
						
							| 
									
										
										
										
											2016-07-02 03:11:49 +08:00
										 |  |  | use BookStack\Ownable; | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  | use BookStack\Page; | 
					
						
							|  |  |  | use BookStack\Role; | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  | use BookStack\User; | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  | use Illuminate\Database\Eloquent\Collection; | 
					
						
							| 
									
										
										
										
											2016-03-01 04:31:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  | class PermissionService | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected $userRoles; | 
					
						
							|  |  |  |     protected $isAdmin; | 
					
						
							|  |  |  |     protected $currentAction; | 
					
						
							| 
									
										
										
										
											2016-03-13 20:04:08 +08:00
										 |  |  |     protected $currentUser; | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     public $book; | 
					
						
							|  |  |  |     public $chapter; | 
					
						
							|  |  |  |     public $page; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     protected $jointPermission; | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     protected $role; | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * PermissionService constructor. | 
					
						
							|  |  |  |      * @param JointPermission $jointPermission | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |      * @param Book $book | 
					
						
							|  |  |  |      * @param Chapter $chapter | 
					
						
							|  |  |  |      * @param Page $page | 
					
						
							|  |  |  |      * @param Role $role | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function __construct(JointPermission $jointPermission, Book $book, Chapter $chapter, Page $page, Role $role) | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-03-13 20:04:08 +08:00
										 |  |  |         $this->currentUser = auth()->user(); | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |         $userSet = $this->currentUser !== null; | 
					
						
							|  |  |  |         $this->userRoles = false; | 
					
						
							|  |  |  |         $this->isAdmin = $userSet ? $this->currentUser->hasRole('admin') : false; | 
					
						
							|  |  |  |         if (!$userSet) $this->currentUser = new User(); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->jointPermission = $jointPermission; | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |         $this->role = $role; | 
					
						
							|  |  |  |         $this->book = $book; | 
					
						
							|  |  |  |         $this->chapter = $chapter; | 
					
						
							|  |  |  |         $this->page = $page; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get the roles for the current user; | 
					
						
							|  |  |  |      * @return array|bool | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function getRoles() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($this->userRoles !== false) return $this->userRoles; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $roles = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (auth()->guest()) { | 
					
						
							|  |  |  |             $roles[] = $this->role->getSystemRole('public')->id; | 
					
						
							|  |  |  |             return $roles; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->currentUser->roles as $role) { | 
					
						
							|  |  |  |             $roles[] = $role->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $roles; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Re-generate all entity permission from scratch. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function buildJointPermissions() | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->jointPermission->truncate(); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Get all roles (Should be the most limited dimension)
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:16:06 +08:00
										 |  |  |         $roles = $this->role->with('permissions')->get(); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Chunk through all books
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->book->with('permissions')->chunk(500, function ($books) use ($roles) { | 
					
						
							|  |  |  |             $this->createManyJointPermissions($books, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Chunk through all chapters
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->chapter->with('book', 'permissions')->chunk(500, function ($chapters) use ($roles) { | 
					
						
							|  |  |  |             $this->createManyJointPermissions($chapters, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Chunk through all pages
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->page->with('book', 'chapter', 'permissions')->chunk(500, function ($pages) use ($roles) { | 
					
						
							|  |  |  |             $this->createManyJointPermissions($pages, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Create the entity jointPermissions for a particular entity. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Entity $entity | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function buildJointPermissionsForEntity(Entity $entity) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $roles = $this->role->with('jointPermissions')->get(); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         $entities = collect([$entity]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($entity->isA('book')) { | 
					
						
							|  |  |  |             $entities = $entities->merge($entity->chapters); | 
					
						
							|  |  |  |             $entities = $entities->merge($entity->pages); | 
					
						
							|  |  |  |         } elseif ($entity->isA('chapter')) { | 
					
						
							|  |  |  |             $entities = $entities->merge($entity->pages); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->deleteManyJointPermissionsForEntities($entities); | 
					
						
							|  |  |  |         $this->createManyJointPermissions($entities, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Build the entity jointPermissions for a particular role. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Role $role | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function buildJointPermissionForRole(Role $role) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $roles = collect([$role]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->deleteManyJointPermissionsForRoles($roles); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Chunk through all books
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->book->with('permissions')->chunk(500, function ($books) use ($roles) { | 
					
						
							|  |  |  |             $this->createManyJointPermissions($books, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Chunk through all chapters
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->chapter->with('book', 'permissions')->chunk(500, function ($books) use ($roles) { | 
					
						
							|  |  |  |             $this->createManyJointPermissions($books, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Chunk through all pages
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->page->with('book', 'chapter', 'permissions')->chunk(500, function ($books) use ($roles) { | 
					
						
							|  |  |  |             $this->createManyJointPermissions($books, $roles); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Delete the entity jointPermissions attached to a particular role. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Role $role | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function deleteJointPermissionsForRole(Role $role) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->deleteManyJointPermissionsForRoles([$role]); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Delete all of the entity jointPermissions for a list of entities. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Role[] $roles | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     protected function deleteManyJointPermissionsForRoles($roles) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         foreach ($roles as $role) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |             $role->jointPermissions()->delete(); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Delete the entity jointPermissions for a particular entity. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Entity $entity | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function deleteJointPermissionsForEntity(Entity $entity) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->deleteManyJointPermissionsForEntities([$entity]); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Delete all of the entity jointPermissions for a list of entities. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Entity[] $entities | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     protected function deleteManyJointPermissionsForEntities($entities) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         foreach ($entities as $entity) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |             $entity->jointPermissions()->delete(); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Create & Save entity jointPermissions for many entities and jointPermissions. | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |      * @param Collection $entities | 
					
						
							|  |  |  |      * @param Collection $roles | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     protected function createManyJointPermissions($entities, $roles) | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $jointPermissions = []; | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |         foreach ($entities as $entity) { | 
					
						
							|  |  |  |             foreach ($roles as $role) { | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                 foreach ($this->getActions($entity) as $action) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                     $jointPermissions[] = $this->createJointPermissionData($entity, $role, $action); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->jointPermission->insert($jointPermissions); | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the actions related to an entity. | 
					
						
							|  |  |  |      * @param $entity | 
					
						
							|  |  |  |      * @return array | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function getActions($entity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $baseActions = ['view', 'update', 'delete']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($entity->isA('chapter')) { | 
					
						
							|  |  |  |             $baseActions[] = 'page-create'; | 
					
						
							|  |  |  |         } else if ($entity->isA('book')) { | 
					
						
							|  |  |  |             $baseActions[] = 'page-create'; | 
					
						
							|  |  |  |             $baseActions[] = 'chapter-create'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          return $baseActions; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Create entity permission data for an entity and role | 
					
						
							|  |  |  |      * for a particular action. | 
					
						
							|  |  |  |      * @param Entity $entity | 
					
						
							|  |  |  |      * @param Role $role | 
					
						
							|  |  |  |      * @param $action | 
					
						
							|  |  |  |      * @return array | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     protected function createJointPermissionData(Entity $entity, Role $role, $action) | 
					
						
							| 
									
										
										
										
											2016-04-21 04:37:57 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |         $permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action; | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |         $roleHasPermission = $role->hasPermission($permissionPrefix . '-all'); | 
					
						
							|  |  |  |         $roleHasPermissionOwn = $role->hasPermission($permissionPrefix . '-own'); | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |         $explodedAction = explode('-', $action); | 
					
						
							|  |  |  |         $restrictionAction = end($explodedAction); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($entity->isA('book')) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!$entity->restricted) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                 $hasAccess = $entity->hasActiveRestriction($role->id, $restrictionAction); | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } elseif ($entity->isA('chapter')) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!$entity->restricted) { | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                 $hasExplicitAccessToBook = $entity->book->hasActiveRestriction($role->id, $restrictionAction); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |                 $hasPermissiveAccessToBook = !$entity->book->restricted; | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 return $this->createJointPermissionDataArray($entity, $role, $action, | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |                     ($hasExplicitAccessToBook || ($roleHasPermission && $hasPermissiveAccessToBook)), | 
					
						
							|  |  |  |                     ($hasExplicitAccessToBook || ($roleHasPermissionOwn && $hasPermissiveAccessToBook))); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                 $hasAccess = $entity->hasActiveRestriction($role->id, $restrictionAction); | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } elseif ($entity->isA('page')) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!$entity->restricted) { | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                 $hasExplicitAccessToBook = $entity->book->hasActiveRestriction($role->id, $restrictionAction); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |                 $hasPermissiveAccessToBook = !$entity->book->restricted; | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                 $hasExplicitAccessToChapter = $entity->chapter && $entity->chapter->hasActiveRestriction($role->id, $restrictionAction); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |                 $hasPermissiveAccessToChapter = $entity->chapter && !$entity->chapter->restricted; | 
					
						
							|  |  |  |                 $acknowledgeChapter = ($entity->chapter && $entity->chapter->restricted); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $hasExplicitAccessToParents = $acknowledgeChapter ? $hasExplicitAccessToChapter : $hasExplicitAccessToBook; | 
					
						
							|  |  |  |                 $hasPermissiveAccessToParents = $acknowledgeChapter ? $hasPermissiveAccessToChapter : $hasPermissiveAccessToBook; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 return $this->createJointPermissionDataArray($entity, $role, $action, | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |                     ($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)), | 
					
						
							|  |  |  |                     ($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents)) | 
					
						
							|  |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 $hasAccess = $entity->hasRestriction($role->id, $action); | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Create an array of data with the information of an entity jointPermissions. | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * Used to build data for bulk insertion. | 
					
						
							|  |  |  |      * @param Entity $entity | 
					
						
							|  |  |  |      * @param Role $role | 
					
						
							|  |  |  |      * @param $action | 
					
						
							|  |  |  |      * @param $permissionAll | 
					
						
							|  |  |  |      * @param $permissionOwn | 
					
						
							|  |  |  |      * @return array | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     protected function createJointPermissionDataArray(Entity $entity, Role $role, $action, $permissionAll, $permissionOwn) | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $entityClass = get_class($entity); | 
					
						
							|  |  |  |         return [ | 
					
						
							| 
									
										
										
										
											2016-05-01 00:16:06 +08:00
										 |  |  |             'role_id'            => $role->getRawAttribute('id'), | 
					
						
							|  |  |  |             'entity_id'          => $entity->getRawAttribute('id'), | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             'entity_type'        => $entityClass, | 
					
						
							|  |  |  |             'action'             => $action, | 
					
						
							|  |  |  |             'has_permission'     => $permissionAll, | 
					
						
							|  |  |  |             'has_permission_own' => $permissionOwn, | 
					
						
							| 
									
										
										
										
											2016-05-01 00:16:06 +08:00
										 |  |  |             'created_by'         => $entity->getRawAttribute('created_by') | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |         ]; | 
					
						
							| 
									
										
										
										
											2016-03-01 04:31:21 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Checks if an entity has a restriction set upon it. | 
					
						
							| 
									
										
										
										
											2016-07-02 03:11:49 +08:00
										 |  |  |      * @param Ownable $ownable | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param $permission | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-07-02 03:11:49 +08:00
										 |  |  |     public function checkOwnableUserAccess(Ownable $ownable, $permission) | 
					
						
							| 
									
										
										
										
											2016-03-01 04:31:21 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         if ($this->isAdmin) return true; | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         $explodedPermission = explode('-', $permission); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-02 03:11:49 +08:00
										 |  |  |         $baseQuery = $ownable->where('id', '=', $ownable->id); | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |         $action = end($explodedPermission); | 
					
						
							|  |  |  |         $this->currentAction = $action; | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $nonJointPermissions = ['restrictions']; | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         // Handle non entity specific jointPermissions
 | 
					
						
							|  |  |  |         if (in_array($explodedPermission[0], $nonJointPermissions)) { | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |             $allPermission = $this->currentUser && $this->currentUser->can($permission . '-all'); | 
					
						
							|  |  |  |             $ownPermission = $this->currentUser && $this->currentUser->can($permission . '-own'); | 
					
						
							|  |  |  |             $this->currentAction = 'view'; | 
					
						
							| 
									
										
										
										
											2016-07-02 03:11:49 +08:00
										 |  |  |             $isOwner = $this->currentUser && $this->currentUser->id === $ownable->created_by; | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |             return ($allPermission || ($isOwner && $ownPermission)); | 
					
						
							| 
									
										
										
										
											2016-03-01 04:31:21 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         // Handle abnormal create jointPermissions
 | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |         if ($action === 'create') { | 
					
						
							|  |  |  |             $this->currentAction = $permission; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         return $this->entityRestrictionQuery($baseQuery)->count() > 0; | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 03:15:44 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Check if an entity has restrictions set on itself or its | 
					
						
							|  |  |  |      * parent tree. | 
					
						
							|  |  |  |      * @param Entity $entity | 
					
						
							|  |  |  |      * @param $action | 
					
						
							|  |  |  |      * @return bool|mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function checkIfRestrictionsSet(Entity $entity, $action) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->currentAction = $action; | 
					
						
							|  |  |  |         if ($entity->isA('page')) { | 
					
						
							|  |  |  |             return $entity->restricted || ($entity->chapter && $entity->chapter->restricted) || $entity->book->restricted; | 
					
						
							|  |  |  |         } elseif ($entity->isA('chapter')) { | 
					
						
							|  |  |  |             return $entity->restricted || $entity->book->restricted; | 
					
						
							|  |  |  |         } elseif ($entity->isA('book')) { | 
					
						
							|  |  |  |             return $entity->restricted; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |      * The general query filter to remove all entities | 
					
						
							|  |  |  |      * that the current user does not have access to. | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |      * @param $query | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |     protected function entityRestrictionQuery($query) | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |         return $query->where(function ($parentQuery) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |             $parentQuery->whereHas('jointPermissions', function ($permissionQuery) { | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |                 $permissionQuery->whereIn('role_id', $this->getRoles()) | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                     ->where('action', '=', $this->currentAction) | 
					
						
							|  |  |  |                     ->where(function ($query) { | 
					
						
							|  |  |  |                         $query->where('has_permission', '=', true) | 
					
						
							|  |  |  |                             ->orWhere(function ($query) { | 
					
						
							|  |  |  |                                 $query->where('has_permission_own', '=', true) | 
					
						
							|  |  |  |                                     ->where('created_by', '=', $this->currentUser->id); | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |                             }); | 
					
						
							|  |  |  |                     }); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Add restrictions for a page query | 
					
						
							|  |  |  |      * @param $query | 
					
						
							|  |  |  |      * @param string $action | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function enforcePageRestrictions($query, $action = 'view') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Prevent drafts being visible to others.
 | 
					
						
							|  |  |  |         $query = $query->where(function ($query) { | 
					
						
							|  |  |  |             $query->where('draft', '=', false); | 
					
						
							|  |  |  |             if ($this->currentUser) { | 
					
						
							|  |  |  |                 $query->orWhere(function ($query) { | 
					
						
							|  |  |  |                     $query->where('draft', '=', true)->where('created_by', '=', $this->currentUser->id); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |         return $this->enforceEntityRestrictions($query, $action); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Add on permission restrictions to a chapter query. | 
					
						
							|  |  |  |      * @param $query | 
					
						
							|  |  |  |      * @param string $action | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function enforceChapterRestrictions($query, $action = 'view') | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |         return $this->enforceEntityRestrictions($query, $action); | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Add restrictions to a book query. | 
					
						
							|  |  |  |      * @param $query | 
					
						
							|  |  |  |      * @param string $action | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function enforceBookRestrictions($query, $action = 'view') | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-07 03:44:07 +08:00
										 |  |  |         return $this->enforceEntityRestrictions($query, $action); | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Add restrictions for a generic entity | 
					
						
							|  |  |  |      * @param $query | 
					
						
							|  |  |  |      * @param string $action | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function enforceEntityRestrictions($query, $action = 'view') | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         if ($this->isAdmin) return $query; | 
					
						
							|  |  |  |         $this->currentAction = $action; | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |         return $this->entityRestrictionQuery($query); | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * 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]; | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 04:31:21 +08:00
										 |  |  |         return $query->where(function ($query) use ($tableDetails) { | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |             $query->whereExists(function ($permissionQuery) use (&$tableDetails) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                 $permissionQuery->select('id')->from('joint_permissions') | 
					
						
							|  |  |  |                     ->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn']) | 
					
						
							|  |  |  |                     ->whereRaw('joint_permissions.entity_type=' . $tableDetails['tableName'] . '.' . $tableDetails['entityTypeColumn']) | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                     ->where('action', '=', $this->currentAction) | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |                     ->whereIn('role_id', $this->getRoles()) | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                     ->where(function ($query) { | 
					
						
							|  |  |  |                         $query->where('has_permission', '=', true)->orWhere(function ($query) { | 
					
						
							|  |  |  |                             $query->where('has_permission_own', '=', true) | 
					
						
							|  |  |  |                                 ->where('created_by', '=', $this->currentUser->id); | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |                         }); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                     }); | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |             }); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-13 21:30:47 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Filters pages that are a direct relation to another item. | 
					
						
							|  |  |  |      * @param $query | 
					
						
							|  |  |  |      * @param $tableName | 
					
						
							|  |  |  |      * @param $entityIdColumn | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function filterRelatedPages($query, $tableName, $entityIdColumn) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($this->isAdmin) return $query; | 
					
						
							|  |  |  |         $this->currentAction = 'view'; | 
					
						
							|  |  |  |         $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn]; | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $query->where(function ($query) use ($tableDetails) { | 
					
						
							| 
									
										
										
										
											2016-03-13 21:30:47 +08:00
										 |  |  |             $query->where(function ($query) use (&$tableDetails) { | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                 $query->whereExists(function ($permissionQuery) use (&$tableDetails) { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |                     $permissionQuery->select('id')->from('joint_permissions') | 
					
						
							|  |  |  |                         ->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn']) | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                         ->where('entity_type', '=', 'Bookstack\\Page') | 
					
						
							|  |  |  |                         ->where('action', '=', $this->currentAction) | 
					
						
							| 
									
										
										
										
											2016-05-02 02:36:53 +08:00
										 |  |  |                         ->whereIn('role_id', $this->getRoles()) | 
					
						
							| 
									
										
										
										
											2016-03-13 21:30:47 +08:00
										 |  |  |                         ->where(function ($query) { | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                             $query->where('has_permission', '=', true)->orWhere(function ($query) { | 
					
						
							|  |  |  |                                 $query->where('has_permission_own', '=', true) | 
					
						
							| 
									
										
										
										
											2016-04-27 04:48:17 +08:00
										 |  |  |                                     ->where('created_by', '=', $this->currentUser->id); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                             }); | 
					
						
							| 
									
										
										
										
											2016-03-13 21:30:47 +08:00
										 |  |  |                         }); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |                 }); | 
					
						
							|  |  |  |             })->orWhere($tableDetails['entityIdColumn'], '=', 0); | 
					
						
							| 
									
										
										
										
											2016-03-13 21:30:47 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  | } |