diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index d2cb647b7..28247185f 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -69,7 +69,7 @@ class PageController extends Controller { $book = $this->bookRepo->getBySlug($bookSlug); $draft = $this->pageRepo->getById($pageId, true); - $this->checkOwnablePermission('page-create', $draft); + $this->checkOwnablePermission('page-create', $book); $this->setPageTitle('Edit Page Draft'); return view('pages/create', ['draft' => $draft, 'book' => $book]); diff --git a/app/Services/RestrictionService.php b/app/Services/RestrictionService.php index 0050401bf..d3394fcd7 100644 --- a/app/Services/RestrictionService.php +++ b/app/Services/RestrictionService.php @@ -6,6 +6,7 @@ use BookStack\Entity; use BookStack\EntityPermission; use BookStack\Page; use BookStack\Role; +use BookStack\User; use Illuminate\Database\Eloquent\Collection; class RestrictionService @@ -23,12 +24,6 @@ class RestrictionService protected $entityPermission; protected $role; - /** - * The actions that have permissions attached throughout the application. - * @var array - */ - protected $actions = ['view', 'create', 'update', 'delete']; - /** * RestrictionService constructor. * @param EntityPermission $entityPermission @@ -40,6 +35,7 @@ class RestrictionService public function __construct(EntityPermission $entityPermission, Book $book, Chapter $chapter, Page $page, Role $role) { $this->currentUser = auth()->user(); + if ($this->currentUser === null) $this->currentUser = new User(['id' => 0]); $this->userRoles = $this->currentUser ? $this->currentUser->roles->pluck('id') : []; $this->isAdmin = $this->currentUser ? $this->currentUser->hasRole('admin') : false; @@ -172,15 +168,34 @@ class RestrictionService $entityPermissions = []; foreach ($entities as $entity) { foreach ($roles as $role) { - foreach ($this->actions as $action) { + foreach ($this->getActions($entity) as $action) { $entityPermissions[] = $this->createEntityPermissionData($entity, $role, $action); } } } - \Log::info(collect($entityPermissions)->where('entity_id', 1)->where('entity_type', 'BookStack\\Page')->where('role_id', 2)->all()); $this->entityPermission->insert($entityPermissions); } + + /** + * 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; + } + /** * Create entity permission data for an entity and role * for a particular action. @@ -191,38 +206,40 @@ class RestrictionService */ protected function createEntityPermissionData(Entity $entity, Role $role, $action) { - $permissionPrefix = $entity->getType() . '-' . $action; + $permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action; $roleHasPermission = $role->hasPermission($permissionPrefix . '-all'); $roleHasPermissionOwn = $role->hasPermission($permissionPrefix . '-own'); + $explodedAction = explode('-', $action); + $restrictionAction = end($explodedAction); if ($entity->isA('book')) { if (!$entity->restricted) { return $this->createEntityPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn); } else { - $hasAccess = $entity->hasActiveRestriction($role->id, $action); + $hasAccess = $entity->hasActiveRestriction($role->id, $restrictionAction); return $this->createEntityPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); } } elseif ($entity->isA('chapter')) { if (!$entity->restricted) { - $hasExplicitAccessToBook = $entity->book->hasActiveRestriction($role->id, $action); + $hasExplicitAccessToBook = $entity->book->hasActiveRestriction($role->id, $restrictionAction); $hasPermissiveAccessToBook = !$entity->book->restricted; return $this->createEntityPermissionDataArray($entity, $role, $action, ($hasExplicitAccessToBook || ($roleHasPermission && $hasPermissiveAccessToBook)), ($hasExplicitAccessToBook || ($roleHasPermissionOwn && $hasPermissiveAccessToBook))); } else { - $hasAccess = $entity->hasActiveRestriction($role->id, $action); + $hasAccess = $entity->hasActiveRestriction($role->id, $restrictionAction); return $this->createEntityPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); } } elseif ($entity->isA('page')) { if (!$entity->restricted) { - $hasExplicitAccessToBook = $entity->book->hasActiveRestriction($role->id, $action); + $hasExplicitAccessToBook = $entity->book->hasActiveRestriction($role->id, $restrictionAction); $hasPermissiveAccessToBook = !$entity->book->restricted; - $hasExplicitAccessToChapter = $entity->chapter && $entity->chapter->hasActiveRestriction($role->id, $action); + $hasExplicitAccessToChapter = $entity->chapter && $entity->chapter->hasActiveRestriction($role->id, $restrictionAction); $hasPermissiveAccessToChapter = $entity->chapter && !$entity->chapter->restricted; $acknowledgeChapter = ($entity->chapter && $entity->chapter->restricted); @@ -277,6 +294,8 @@ class RestrictionService $explodedPermission = explode('-', $permission); $baseQuery = $entity->where('id', '=', $entity->id); + $action = end($explodedPermission); + $this->currentAction = $action; $nonEntityPermissions = ['restrictions']; @@ -289,8 +308,12 @@ class RestrictionService return ($allPermission || ($isOwner && $ownPermission)); } - $action = end($explodedPermission); - $this->currentAction = $action; + // Handle abnormal create permissions + if ($action === 'create') { + $this->currentAction = $permission; + } + + return $this->entityRestrictionQuery($baseQuery)->count() > 0; } @@ -441,7 +464,7 @@ class RestrictionService ->where(function ($query) { $query->where('has_permission', '=', true)->orWhere(function ($query) { $query->where('has_permission_own', '=', true) - ->where('created_by', '=', $this->currentUser ? $this->currentUser->id : 0); + ->where('created_by', '=', $this->currentUser->id); }); }); }); diff --git a/database/seeds/DummyContentSeeder.php b/database/seeds/DummyContentSeeder.php index 328971f26..f7ddd95c4 100644 --- a/database/seeds/DummyContentSeeder.php +++ b/database/seeds/DummyContentSeeder.php @@ -20,12 +20,15 @@ class DummyContentSeeder extends Seeder ->each(function($book) use ($user) { $chapters = factory(BookStack\Chapter::class, 5)->create(['created_by' => $user->id, 'updated_by' => $user->id]) ->each(function($chapter) use ($user, $book){ - $pages = factory(\BookStack\Page::class, 10)->make(['created_by' => $user->id, 'updated_by' => $user->id, 'book_id' => $book->id]); + $pages = factory(\BookStack\Page::class, 5)->make(['created_by' => $user->id, 'updated_by' => $user->id, 'book_id' => $book->id]); $chapter->pages()->saveMany($pages); }); $pages = factory(\BookStack\Page::class, 3)->make(['created_by' => $user->id, 'updated_by' => $user->id]); $book->chapters()->saveMany($chapters); $book->pages()->saveMany($pages); }); + + $restrictionService = app(\BookStack\Services\RestrictionService::class); + $restrictionService->buildEntityPermissions(); } }