X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/553954ad18bd684b7d83d1ee6f7d0bdbf7651acf..refs/pull/3616/head:/app/Entities/Tools/BookContents.php diff --git a/app/Entities/Tools/BookContents.php b/app/Entities/Tools/BookContents.php index bdbc4262d..6f11e8cbe 100644 --- a/app/Entities/Tools/BookContents.php +++ b/app/Entities/Tools/BookContents.php @@ -119,9 +119,10 @@ class BookContents // Sort our changes from our map to be chapters first // Since they need to be process to ensure book alignment for child page changes. $sortMapItems = $sortMap->all(); - usort($sortMapItems, function(BookSortMapItem $itemA, BookSortMapItem $itemB) { + usort($sortMapItems, function (BookSortMapItem $itemA, BookSortMapItem $itemB) { $aScore = $itemA->type === 'page' ? 2 : 1; $bScore = $itemB->type === 'page' ? 2 : 1; + return $aScore - $bScore; }); @@ -167,14 +168,14 @@ class BookContents return; } - $currentParentKey = 'book:' . $model->book_id; + $currentParentKey = 'book:' . $model->book_id; if ($model instanceof Page && $model->chapter_id) { - $currentParentKey = 'chapter:' . $model->chapter_id; + $currentParentKey = 'chapter:' . $model->chapter_id; } $currentParent = $modelMap[$currentParentKey] ?? null; /** @var Book $newBook */ - $newBook = $modelMap['book:' . $sortMapItem->parentBookId]; + $newBook = $modelMap['book:' . $sortMapItem->parentBookId] ?? null; /** @var ?Chapter $newChapter */ $newChapter = $sortMapItem->parentChapterId ? ($modelMap['chapter:' . $sortMapItem->parentChapterId] ?? null) : null; @@ -202,19 +203,27 @@ class BookContents /** * Check if the current user has permissions to apply the given sorting change. + * Is quite complex since items can gain a different parent change. Acts as a: + * - Update of old parent element (Change of content/order). + * - Update of sorted/moved element. + * - Deletion of element (Relative to parent upon move). + * - Creation of element within parent (Upon move to new parent). */ - protected function isSortChangePermissible(BookSortMapItem $sortMapItem, Entity $model, ?Entity $currentParent, ?Entity $newBook, ?Entity $newChapter): bool + protected function isSortChangePermissible(BookSortMapItem $sortMapItem, BookChild $model, ?Entity $currentParent, ?Entity $newBook, ?Entity $newChapter): bool { - // TODO - Move operations check for create permissions, Needs these also/instead? - // Stop if we can't see the current parent or new book. if (!$currentParent || !$newBook) { return false; } + $hasNewParent = $newBook->id !== $model->book_id || ($model instanceof Page && $model->chapter_id !== ($sortMapItem->parentChapterId ?? 0)); if ($model instanceof Chapter) { $hasPermission = userCan('book-update', $currentParent) - && userCan('book-update', $newBook); + && userCan('book-update', $newBook) + && userCan('chapter-update', $model) + && (!$hasNewParent || userCan('chapter-create', $newBook)) + && (!$hasNewParent || userCan('chapter-delete', $model)); + if (!$hasPermission) { return false; } @@ -232,11 +241,21 @@ class BookContents return false; } + $hasPageEditPermission = userCan('page-update', $model); $newParentInRightLocation = ($newParent instanceof Book || $newParent->book_id === $newBook->id); $newParentPermission = ($newParent instanceof Chapter) ? 'chapter-update' : 'book-update'; $hasNewParentPermission = userCan($newParentPermission, $newParent); - $hasPermission = $hasCurrentParentPermission && $newParentInRightLocation && $hasNewParentPermission; + $hasDeletePermissionIfMoving = (!$hasNewParent || userCan('page-delete', $model)); + $hasCreatePermissionIfMoving = (!$hasNewParent || userCan('page-create', $newParent)); + + $hasPermission = $hasCurrentParentPermission + && $newParentInRightLocation + && $hasNewParentPermission + && $hasPageEditPermission + && $hasDeletePermissionIfMoving + && $hasCreatePermissionIfMoving; + if (!$hasPermission) { return false; } @@ -247,6 +266,7 @@ class BookContents /** * Load models from the database into the given sort map. + * * @return array */ protected function loadModelsFromSortMap(BookSortMap $sortMap): array @@ -254,8 +274,8 @@ class BookContents $modelMap = []; $ids = [ 'chapter' => [], - 'page' => [], - 'book' => [], + 'page' => [], + 'book' => [], ]; foreach ($sortMap->all() as $sortMapItem) {