$action = $permission;
}
+ // TODO - Use a non-query based check
$hasAccess = $this->entityRestrictionQuery($baseQuery, $action)->count() > 0;
$this->clean();
/**
* Add restrictions for a generic entity.
*/
- public function enforceEntityRestrictions(Entity $entity, Builder $query, string $action = 'view'): Builder
+ public function enforceEntityRestrictions(Entity $entity, Builder $query): Builder
{
if ($entity instanceof Page) {
// Prevent drafts being visible to others.
$this->enforceDraftVisibilityOnQuery($query);
}
- return $this->entityRestrictionQuery($query, $action);
+ return $this->entityRestrictionQuery($query, 'view');
}
/**
}
/**
- * Get all permissions belonging to a the current user.
+ * Get all permissions belonging to the current user.
*/
protected function permissions(): Collection
{
class Popular extends EntityQuery
{
- public function run(int $count, int $page, array $filterModels = null, string $action = 'view')
+ public function run(int $count, int $page, array $filterModels = null)
{
$query = $this->permissionService()
- ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type', $action)
+ ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type', 'view')
->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count'))
->groupBy('viewable_id', 'viewable_type')
->orderBy('view_count', 'desc');
*
* @return array{total: int, count: int, has_more: bool, results: Entity[]}
*/
- public function searchEntities(SearchOptions $searchOpts, string $entityType = 'all', int $page = 1, int $count = 20, string $action = 'view'): array
+ public function searchEntities(SearchOptions $searchOpts, string $entityType = 'all', int $page = 1, int $count = 20): array
{
$entityTypes = array_keys($this->entityProvider->all());
$entityTypesToSearch = $entityTypes;
}
$entityModelInstance = $this->entityProvider->get($entityType);
- $searchQuery = $this->buildQuery($searchOpts, $entityModelInstance, $action);
+ $searchQuery = $this->buildQuery($searchOpts, $entityModelInstance);
$entityTotal = $searchQuery->count();
$searchResults = $this->getPageOfDataFromQuery($searchQuery, $entityModelInstance, $page, $count);
/**
* Create a search query for an entity.
*/
- protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance, string $action = 'view'): EloquentBuilder
+ protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance): EloquentBuilder
{
$entityQuery = $entityModelInstance->newQuery();
}
}
- return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery, $action);
+ return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery);
}
/**
class SearchController extends Controller
{
protected $searchRunner;
- protected $entityContextManager;
public function __construct(SearchRunner $searchRunner)
{
// Search for entities otherwise show most popular
if ($searchTerm !== false) {
$searchTerm .= ' {type:' . implode('|', $entityTypes) . '}';
- $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20, $permission)['results'];
+ $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20)['results'];
} else {
- $entities = (new Popular())->run(20, 0, $entityTypes, $permission);
+ $entities = (new Popular())->run(20, 0, $entityTypes);
}
- return view('search.parts.entity-ajax-list', ['entities' => $entities]);
+ return view('search.parts.entity-ajax-list', ['entities' => $entities, 'permission' => $permission]);
}
/**
}
}
+.entity-list-item.disabled {
+ pointer-events: none;
+ cursor: not-allowed;
+ opacity: 0.8;
+ user-select: none;
+ background: var(--bg-disabled);
+}
+
.entity-list-item-path-sep {
display: inline-block;
vertical-align: top;
--color-chapter: #af4d0d;
--color-book: #077b70;
--color-bookshelf: #a94747;
+
+ --bg-disabled: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='100%25' width='100%25'%3E%3Cdefs%3E%3Cpattern id='doodad' width='19' height='19' viewBox='0 0 40 40' patternUnits='userSpaceOnUse' patternTransform='rotate(143)'%3E%3Crect width='100%25' height='100%25' fill='rgba(42, 67, 101,0)'/%3E%3Cpath d='M-10 30h60v20h-60zM-10-10h60v20h-60' fill='rgba(26, 32, 44,0)'/%3E%3Cpath d='M-10 10h60v20h-60zM-10-30h60v20h-60z' fill='rgba(0, 0, 0,0.05)'/%3E%3C/pattern%3E%3C/defs%3E%3Crect fill='url(%23doodad)' height='200%25' width='200%25'/%3E%3C/svg%3E");
+}
+
+:root.dark-mode {
+ --bg-disabled: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='100%25' width='100%25'%3E%3Cdefs%3E%3Cpattern id='doodad' width='19' height='19' viewBox='0 0 40 40' patternUnits='userSpaceOnUse' patternTransform='rotate(143)'%3E%3Crect width='100%25' height='100%25' fill='rgba(42, 67, 101,0)'/%3E%3Cpath d='M-10 30h60v20h-60zM-10-10h60v20h-60' fill='rgba(26, 32, 44,0)'/%3E%3Cpath d='M-10 10h60v20h-60zM-10-30h60v20h-60z' fill='rgba(255, 255, 255,0.05)'/%3E%3C/pattern%3E%3C/defs%3E%3Crect fill='url(%23doodad)' height='200%25' width='200%25'/%3E%3C/svg%3E");
}
$positive: #0f7d15;
-@component('entities.list-item-basic', ['entity' => $entity])
+@component('entities.list-item-basic', ['entity' => $entity, 'classes' => (($locked ?? false) ? 'disabled ' : '') . ($classes ?? '') ])
<div class="entity-item-snippet">
+ @if($locked ?? false)
+ <div class="text-warn my-xxs bold">
+ @icon('lock')You don't have the required permissions to select this item.
+ </div>
+ @endif
+
@if($showPath ?? false)
@if($entity->relationLoaded('book') && $entity->book)
<span class="text-book">{{ $entity->book->getShortName(42) }}</span>
@if(count($entities) > 0)
@foreach($entities as $index => $entity)
- @include('entities.list-item', ['entity' => $entity, 'showPath' => true])
+ @include('entities.list-item', [
+ 'entity' => $entity,
+ 'showPath' => true,
+ 'locked' => $permission !== 'view' && !userCan($permission, $entity)
+ ])
+
@if($index !== count($entities) - 1)
<hr>
@endif
Route::get('/status', [StatusController::class, 'show']);
Route::get('/robots.txt', [HomeController::class, 'robots']);
+Route::get('/test', function() {
+ $book = \BookStack\Entities\Models\Book::query()->where('slug', '=', 'k5TrhXxaNb')->firstOrFail();
+ $builder= app()->make(\BookStack\Auth\Permissions\JointPermissionBuilder::class);
+ $builder->rebuildForEntity($book);
+ return 'finished';
+})->withoutMiddleware('web');
+
// Authenticated routes...
Route::middleware('auth')->group(function () {