mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-03-31 04:08:58 +08:00
Started removal of non-view permission queries
Updated ajax search and entity selector usage to display and handle items that the user does not have permission to interact with. Started logic changes to not allow permission type to be passed around, with views instead being the fixed sole permission.
This commit is contained in:
parent
2989852520
commit
4fb85a9a5c
@ -72,6 +72,7 @@ class PermissionApplicator
|
||||
$action = $permission;
|
||||
}
|
||||
|
||||
// TODO - Use a non-query based check
|
||||
$hasAccess = $this->entityRestrictionQuery($baseQuery, $action)->count() > 0;
|
||||
$this->clean();
|
||||
|
||||
@ -163,14 +164,14 @@ class PermissionApplicator
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,7 +163,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all permissions belonging to a the current user.
|
||||
* Get all permissions belonging to the current user.
|
||||
*/
|
||||
protected function permissions(): Collection
|
||||
{
|
||||
|
@ -7,10 +7,10 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
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');
|
||||
|
@ -54,7 +54,7 @@ class SearchRunner
|
||||
*
|
||||
* @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;
|
||||
@ -75,7 +75,7 @@ class SearchRunner
|
||||
}
|
||||
|
||||
$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);
|
||||
|
||||
@ -159,7 +159,7 @@ class SearchRunner
|
||||
/**
|
||||
* 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();
|
||||
|
||||
@ -193,7 +193,7 @@ class SearchRunner
|
||||
}
|
||||
}
|
||||
|
||||
return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery, $action);
|
||||
return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,6 @@ use Illuminate\Http\Request;
|
||||
class SearchController extends Controller
|
||||
{
|
||||
protected $searchRunner;
|
||||
protected $entityContextManager;
|
||||
|
||||
public function __construct(SearchRunner $searchRunner)
|
||||
{
|
||||
@ -79,12 +78,12 @@ class SearchController extends Controller
|
||||
// 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]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -443,6 +443,14 @@ ul.pagination {
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
|
@ -45,6 +45,12 @@ $fs-s: 12px;
|
||||
--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;
|
||||
|
@ -1,7 +1,13 @@
|
||||
@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>
|
||||
|
@ -2,7 +2,12 @@
|
||||
@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
|
||||
|
@ -38,6 +38,13 @@ use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
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 () {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user