return true;
}
+ // The chain order here is very important due to the fact we walk up the chain
+ // in the loop below. Earlier items in the chain have higher priority.
$chain = [$entity];
if ($entity instanceof Page && $entity->chapter_id) {
$chain[] = $entity->chapter;
}
foreach ($chain as $currentEntity) {
- if (is_null($currentEntity->restricted)) {
- throw new InvalidArgumentException('Entity restricted field used but has not been loaded');
+ $allowedByRoleId = $currentEntity->permissions()
+ ->whereIn('role_id', [0, ...$userRoleIds])
+ ->pluck($action, 'role_id');
+
+ // Continue up the chain if no applicable entity permission overrides.
+ if (empty($allowedByRoleId)) {
+ continue;
}
- if ($currentEntity->restricted) {
- return $currentEntity->permissions()
- ->whereIn('role_id', $userRoleIds)
- ->where($action, '=', true)
- ->count() > 0;
+ // If we have user-role-specific permissions set, allow if any of those
+ // role permissions allow access.
+ $hasDefault = $allowedByRoleId->has(0);
+ if (!$hasDefault || $allowedByRoleId->count() > 1) {
+ return $allowedByRoleId->search(function (bool $allowed, int $roleId) {
+ return $roleId !== 0 && $allowed;
+ }) !== false;
}
+
+ // Otherwise, return the default "Other roles" fallback value.
+ return $allowedByRoleId->get(0);
}
return null;
return;
}
- $shelves = Bookshelf::query()->get(['id', 'restricted']);
+ $shelves = Bookshelf::query()->get(['id']);
}
if ($shelfSlug) {
- $shelves = Bookshelf::query()->where('slug', '=', $shelfSlug)->get(['id', 'restricted']);
+ $shelves = Bookshelf::query()->where('slug', '=', $shelfSlug)->get(['id']);
if ($shelves->count() === 0) {
$this->info('No shelves found with the given slug.');
}
public $searchFactor = 1.2;
protected $fillable = ['name', 'description'];
- protected $hidden = ['restricted', 'pivot', 'image_id', 'deleted_at'];
+ protected $hidden = ['pivot', 'image_id', 'deleted_at'];
/**
* Get the url for this book.
protected $fillable = ['name', 'description', 'image_id'];
- protected $hidden = ['restricted', 'image_id', 'deleted_at'];
+ protected $hidden = ['image_id', 'deleted_at'];
/**
* Get the books in this shelf.
public $searchFactor = 1.2;
protected $fillable = ['name', 'description', 'priority'];
- protected $hidden = ['restricted', 'pivot', 'deleted_at'];
+ protected $hidden = ['pivot', 'deleted_at'];
/**
* Get the pages that this chapter contains.
* @property Carbon $deleted_at
* @property int $created_by
* @property int $updated_by
- * @property bool $restricted
* @property Collection $tags
*
* @method static Entity|Builder visible()
public $textField = 'text';
- protected $hidden = ['html', 'markdown', 'text', 'restricted', 'pivot', 'deleted_at'];
+ protected $hidden = ['html', 'markdown', 'text', 'pivot', 'deleted_at'];
protected $casts = [
'draft' => 'boolean',
class PageRevision extends Model implements Loggable
{
protected $fillable = ['name', 'text', 'summary'];
- protected $hidden = ['html', 'markdown', 'restricted', 'text'];
+ protected $hidden = ['html', 'markdown', 'text'];
/**
* Get the user that created the page revision.
*/
public function copyEntityPermissions(Entity $sourceEntity, Entity $targetEntity): void
{
- $targetEntity->restricted = $sourceEntity->restricted;
$permissions = $sourceEntity->permissions()->get(['role_id', 'view', 'create', 'update', 'delete'])->toArray();
$targetEntity->permissions()->delete();
$targetEntity->permissions()->createMany($permissions);
foreach ($book->chapters as $index => $chapter) {
$newBook = $this->transformChapterToBook($chapter);
$shelfBookSyncData[$newBook->id] = ['order' => $index];
- if (!$newBook->restricted) {
+ if (!$newBook->hasPermissions()) {
$this->cloner->copyEntityPermissions($shelf, $newBook);
}
}
*/
public function updateBookPermissionsFromShelf(Bookshelf $shelf, $checkUserPermissions = true): int
{
- // TODO - Fix for new format
$shelfPermissions = $shelf->permissions()->get(['role_id', 'view', 'create', 'update', 'delete'])->toArray();
- $shelfBooks = $shelf->books()->get(['id', 'restricted', 'owned_by']);
+ $shelfBooks = $shelf->books()->get(['id', 'owned_by']);
$updatedBookCount = 0;
/** @var Book $book */
continue;
}
$book->permissions()->delete();
- $book->restricted = $shelf->restricted;
$book->permissions()->createMany($shelfPermissions);
- $book->save();
$book->rebuildPermissions();
$updatedBookCount++;
}
$modelInstance = $model->newQuery()
->where('id', '=', $modelInfo['id'])
- ->first(['id', 'name', 'restricted', 'owned_by']);
+ ->first(['id', 'name', 'owned_by']);
$inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
if (is_null($modelInstance) || $inaccessibleEntity) {
],
]]);
- $page->restricted = true;
- $page->save();
- $this->entities->regenPermissions($page);
+ $this->entities->setPermissions($page, [], []);
$resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id');
$resp->assertJsonMissing(['data' => [
$shelf = $this->entities->shelf();
$child = $shelf->books()->first();
$editorRole = $this->getEditor()->roles()->first();
- $this->assertFalse(boolval($child->restricted), 'Child book should not be restricted by default');
+ $this->assertFalse(boolval($child->hasPermissions()), 'Child book should not be restricted by default');
$this->assertTrue($child->permissions()->count() === 0, 'Child book should have no permissions by default');
$this->entities->setPermissions($shelf, ['view', 'update'], [$editorRole]);
]);
$child = $shelf->books()->first();
- $this->assertTrue(boolval($child->restricted), 'Child book should now be restricted');
+ $this->assertTrue(boolval($child->hasPermissions()), 'Child book should now be restricted');
$this->assertTrue($child->permissions()->count() === 2, 'Child book should have copied permissions');
$this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'view', 'role_id' => $editorRole->id]);
$this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'update', 'role_id' => $editorRole->id]);
Bookshelf::query()->where('id', '!=', $shelf->id)->delete();
$child = $shelf->books()->first();
$editorRole = $this->getEditor()->roles()->first();
- $this->assertFalse(boolval($child->restricted), 'Child book should not be restricted by default');
+ $this->assertFalse(boolval($child->hasPermissions()), 'Child book should not be restricted by default');
$this->assertTrue($child->permissions()->count() === 0, 'Child book should have no permissions by default');
$this->entities->setPermissions($shelf, ['view', 'update'], [$editorRole]);
->expectsQuestion('Permission settings for all shelves will be cascaded. Books assigned to multiple shelves will receive only the permissions of it\'s last processed shelf. Are you sure you want to proceed?', 'y');
$child = $shelf->books()->first();
- $this->assertTrue(boolval($child->restricted), 'Child book should now be restricted');
+ $this->assertTrue(boolval($child->hasPermissions()), 'Child book should now be restricted');
$this->assertTrue($child->permissions()->count() === 2, 'Child book should have copied permissions');
$this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'view', 'role_id' => $editorRole->id]);
$this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'update', 'role_id' => $editorRole->id]);
$child = $shelf->books()->first();
$editorRole = $this->getEditor()->roles()->first();
- $this->assertFalse(boolval($child->restricted), 'Child book should not be restricted by default');
+ $this->assertFalse(boolval($child->hasPermissions()), 'Child book should not be restricted by default');
$this->assertTrue($child->permissions()->count() === 0, 'Child book should have no permissions by default');
$this->entities->setPermissions($shelf, ['view', 'update'], [$editorRole]);
$child = $shelf->books()->first();
$resp->assertRedirect($shelf->getUrl());
- $this->assertTrue(boolval($child->restricted), 'Child book should now be restricted');
+ $this->assertTrue(boolval($child->hasPermissions()), 'Child book should now be restricted');
$this->assertTrue($child->permissions()->count() === 2, 'Child book should have copied permissions');
$this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'view', 'role_id' => $editorRole->id]);
$this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'update', 'role_id' => $editorRole->id]);
// Hide child content
/** @var BookChild $page */
foreach ($book->getDirectChildren() as $child) {
- $child->restricted = true;
- $child->save();
- $this->entities->regenPermissions($child);
+ $this->entities->setPermissions($child, [], []);
}
$this->asEditor()->post($book->getUrl('/copy'), ['name' => 'My copy book']);
// Hide pages to all non-admin roles
/** @var Page $page */
foreach ($chapter->pages as $page) {
- $page->restricted = true;
- $page->save();
- $this->entities->regenPermissions($page);
+ $this->entities->setPermissions($page, [], []);
}
$this->asEditor()->post($chapter->getUrl('/copy'), [
// Restricted filter
$this->get('/search?term=' . urlencode('danzorbhsing {is_restricted}'))->assertDontSee($page->name);
- $page->restricted = true;
- $page->save();
+ $this->entities->setPermissions($page, [], []);
$this->get('/search?term=' . urlencode('danzorbhsing {is_restricted}'))->assertSee($page->name);
// Date filters
$this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
// Set restricted permission the page
- $page->restricted = true;
- $page->save();
- $page->rebuildPermissions();
+ $this->entities->setPermissions($page, [], []);
$this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']);
$this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson([]);
$resp = $this->get('/tags?name=SuperCategory');
$resp->assertSee('GreatTestContent');
- $page->restricted = true;
- $this->entities->regenPermissions($page);
+ $this->entities->setPermissions($page, [], []);
$resp = $this->asEditor()->get('/tags');
$resp->assertDontSee('SuperCategory');
*/
public function setPermissions(Entity $entity, array $actions = [], array $roles = []): void
{
- $entity->restricted = true;
$entity->permissions()->delete();
$permissions = [];
}
$entity->permissions()->createMany($permissions);
- $entity->save();
$entity->load('permissions');
$this->regenPermissions($entity);
}
->assertSee($title);
$this->put($modelInstance->getUrl('/permissions'), [
- 'restricted' => 'true',
'restrictions' => [
$roleId => [
$permission => 'true',
$this->uploadFile($fileName, $page->id);
$attachment = Attachment::orderBy('id', 'desc')->take(1)->first();
- $page->restricted = true;
- $page->permissions()->delete();
- $page->save();
- $page->rebuildPermissions();
- $page->load('jointPermissions');
+ $this->entities->setPermissions($page, [], []);
$this->actingAs($viewer);
$attachmentGet = $this->get($attachment->getUrl());