Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion app/Auth/Permissions/PermissionApplicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ public function checkOwnableUserAccess(Model $ownable, string $permission): bool
$ownRolePermission = $user->can($fullPermission . '-own');
$nonJointPermissions = ['restrictions', 'image', 'attachment', 'comment'];
$ownerField = ($ownable instanceof Entity) ? 'owned_by' : 'created_by';
$isOwner = $user->id === $ownable->getAttribute($ownerField);
$ownableFieldVal = $ownable->getAttribute($ownerField);

if (is_null($ownableFieldVal)) {
throw new InvalidArgumentException("{$ownerField} field used but has not been loaded");
}

$isOwner = $user->id === $ownableFieldVal;
$hasRolePermission = $allRolePermission || ($isOwner && $ownRolePermission);

// Handle non entity specific jointPermissions
Expand Down Expand Up @@ -68,6 +74,11 @@ protected function hasEntityPermission(Entity $entity, array $userRoleIds, strin
}

foreach ($chain as $currentEntity) {

if (is_null($currentEntity->restricted)) {
throw new InvalidArgumentException("Entity restricted field used but has not been loaded");
}

if ($currentEntity->restricted) {
return $currentEntity->permissions()
->whereIn('role_id', $userRoleIds)
Expand Down
1 change: 1 addition & 0 deletions app/Entities/Repos/BaseRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function create(Entity $entity, array $input)
$this->tagRepo->saveTagsToEntity($entity, $input['tags']);
}

$entity->refresh();
$entity->rebuildPermissions();
$entity->indexForSearch();
}
Expand Down
2 changes: 1 addition & 1 deletion app/Entities/Repos/BookshelfRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ protected function updateBooks(Bookshelf $shelf, array $bookIds)
public function copyDownPermissions(Bookshelf $shelf, $checkUserPermissions = true): int
{
$shelfPermissions = $shelf->permissions()->get(['role_id', 'action'])->toArray();
$shelfBooks = $shelf->books()->get(['id', 'restricted']);
$shelfBooks = $shelf->books()->get(['id', 'restricted', 'owned_by']);
$updatedBookCount = 0;

/** @var Book $book */
Expand Down
2 changes: 1 addition & 1 deletion app/Entities/Tools/SearchRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInst
$entityQuery = $entityModelInstance->newQuery()->scopes('visible');

if ($entityModelInstance instanceof Page) {
$entityQuery->select($entityModelInstance::$listAttributes);
$entityQuery->select(array_merge($entityModelInstance::$listAttributes, ['restricted', 'owned_by']));
} else {
$entityQuery->select(['*']);
}
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/FavouriteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ protected function getValidatedModelFromRequest(Request $request): Entity

$modelInstance = $model->newQuery()
->where('id', '=', $modelInfo['id'])
->first(['id', 'name']);
->first(['id', 'name', 'restricted', 'owned_by']);

$inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
if (is_null($modelInstance) || $inaccessibleEntity) {
Expand Down
28 changes: 26 additions & 2 deletions tests/FavouriteTest.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php
<?php namespace Tests;

use BookStack\Actions\Favourite;
use BookStack\Auth\User;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
use Tests\TestCase;

class FavouriteTest extends TestCase
{
Expand Down Expand Up @@ -58,6 +58,30 @@ public function test_page_remove_favourite_flow()
]);
}

public function test_favourite_flow_with_own_permissions()
{
/** @var Book $book */
$book = Book::query()->first();
$user = User::factory()->create();
$book->owned_by = $user->id;
$book->save();

$this->giveUserPermissions($user, ['book-view-own']);

$this->actingAs($user)->get($book->getUrl());
$resp = $this->post('/favourites/add', [
'type' => get_class($book),
'id' => $book->id,
]);
$resp->assertRedirect($book->getUrl());

$this->assertDatabaseHas('favourites', [
'user_id' => $user->id,
'favouritable_type' => $book->getMorphClass(),
'favouritable_id' => $book->id,
]);
}

public function test_book_chapter_shelf_pages_contain_favourite_button()
{
$entities = [
Expand Down