1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-09 10:22:51 +03:00

Added restriction tests and fixed any bugs in the process

Also updated many styles within areas affected by the new permission and roles system.
This commit is contained in:
Dan Brown
2016-03-05 18:09:21 +00:00
parent 268db6b1d0
commit 8e6248f57f
26 changed files with 680 additions and 32 deletions

View File

@@ -56,7 +56,8 @@ class Handler extends ExceptionHandler
// Which will include the basic message to point the user roughly to the cause.
if (($e instanceof PrettyException || $e->getPrevious() instanceof PrettyException) && !config('app.debug')) {
$message = ($e instanceof PrettyException) ? $e->getMessage() : $e->getPrevious()->getMessage();
return response()->view('errors/500', ['message' => $message], 500);
$code = ($e->getCode() === 0) ? 500 : $e->getCode();
return response()->view('errors/' . $code, ['message' => $message], $code);
}
return parent::render($request, $e);

View File

@@ -0,0 +1,14 @@
<?php namespace BookStack\Exceptions;
class NotFoundException extends PrettyException {
/**
* NotFoundException constructor.
* @param string $message
*/
public function __construct($message = 'Item not found')
{
parent::__construct($message, 404);
}
}

View File

@@ -80,7 +80,14 @@ class ChapterController extends Controller
$sidebarTree = $this->bookRepo->getChildren($book);
Views::add($chapter);
$this->setPageTitle($chapter->getShortName());
return view('chapters/show', ['book' => $book, 'chapter' => $chapter, 'current' => $chapter, 'sidebarTree' => $sidebarTree]);
$pages = $this->chapterRepo->getChildren($chapter);
return view('chapters/show', [
'book' => $book,
'chapter' => $chapter,
'current' => $chapter,
'sidebarTree' => $sidebarTree,
'pages' => $pages
]);
}
/**

View File

@@ -1,6 +1,7 @@
<?php namespace BookStack\Http\Controllers;
use Activity;
use BookStack\Exceptions\NotFoundException;
use BookStack\Repos\UserRepo;
use BookStack\Services\ExportService;
use Illuminate\Http\Request;
@@ -94,7 +95,7 @@ class PageController extends Controller
try {
$page = $this->pageRepo->getBySlug($pageSlug, $book->id);
} catch (NotFoundHttpException $e) {
} catch (NotFoundException $e) {
$page = $this->pageRepo->findPageUsingOldSlug($pageSlug, $bookSlug);
if ($page === null) abort(404);
return redirect($page->getUrl());

View File

@@ -1,6 +1,7 @@
<?php namespace BookStack\Repos;
use Activity;
use BookStack\Exceptions\NotFoundException;
use BookStack\Services\RestrictionService;
use Illuminate\Support\Str;
use BookStack\Book;
@@ -111,11 +112,12 @@ class BookRepo
* Get a book by slug
* @param $slug
* @return mixed
* @throws NotFoundException
*/
public function getBySlug($slug)
{
$book = $this->bookQuery()->where('slug', '=', $slug)->first();
if ($book === null) abort(404);
if ($book === null) throw new NotFoundException('Book not found');
return $book;
}
@@ -153,6 +155,7 @@ class BookRepo
$this->chapterRepo->destroy($chapter);
}
$book->views()->delete();
$book->restrictions()->delete();
$book->delete();
}
@@ -210,11 +213,13 @@ class BookRepo
public function getChildren(Book $book)
{
$pageQuery = $book->pages()->where('chapter_id', '=', 0);
$this->restrictionService->enforcePageRestrictions($pageQuery, 'view');
$pageQuery = $this->restrictionService->enforcePageRestrictions($pageQuery, 'view');
$pages = $pageQuery->get();
$chapterQuery = $book->chapters()->with('pages');
$this->restrictionService->enforceChapterRestrictions($chapterQuery, 'view');
$chapterQuery = $book->chapters()->with(['pages' => function($query) {
$this->restrictionService->enforcePageRestrictions($query, 'view');
}]);
$chapterQuery = $this->restrictionService->enforceChapterRestrictions($chapterQuery, 'view');
$chapters = $chapterQuery->get();
$children = $pages->merge($chapters);
$bookSlug = $book->slug;

View File

@@ -2,6 +2,7 @@
use Activity;
use BookStack\Exceptions\NotFoundException;
use BookStack\Services\RestrictionService;
use Illuminate\Support\Str;
use BookStack\Chapter;
@@ -66,14 +67,24 @@ class ChapterRepo
* @param $slug
* @param $bookId
* @return mixed
* @throws NotFoundException
*/
public function getBySlug($slug, $bookId)
{
$chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
if ($chapter === null) abort(404);
if ($chapter === null) throw new NotFoundException('Chapter not found');
return $chapter;
}
/**
* Get the child items for a chapter
* @param Chapter $chapter
*/
public function getChildren(Chapter $chapter)
{
return $this->restrictionService->enforcePageRestrictions($chapter->pages())->get();
}
/**
* Create a new chapter from request input.
* @param $input
@@ -98,6 +109,7 @@ class ChapterRepo
}
Activity::removeEntity($chapter);
$chapter->views()->delete();
$chapter->restrictions()->delete();
$chapter->delete();
}

View File

@@ -4,6 +4,7 @@
use Activity;
use BookStack\Book;
use BookStack\Chapter;
use BookStack\Exceptions\NotFoundException;
use BookStack\Services\RestrictionService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@@ -56,11 +57,12 @@ class PageRepo
* @param $slug
* @param $bookId
* @return mixed
* @throws NotFoundException
*/
public function getBySlug($slug, $bookId)
{
$page = $this->pageQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
if ($page === null) throw new NotFoundHttpException('Page not found');
if ($page === null) throw new NotFoundException('Page not found');
return $page;
}
@@ -373,6 +375,7 @@ class PageRepo
Activity::removeEntity($page);
$page->views()->delete();
$page->revisions()->delete();
$page->restrictions()->delete();
$page->delete();
}

View File

@@ -15,10 +15,16 @@ class RestrictionService
public function __construct()
{
$user = auth()->user();
$this->userRoles = $user ? auth()->user()->roles->pluck('id') : false;
$this->userRoles = $user ? auth()->user()->roles->pluck('id') : [];
$this->isAdmin = $user ? auth()->user()->hasRole('admin') : false;
}
/**
* Checks if an entity has a restriction set upon it.
* @param Entity $entity
* @param $action
* @return bool
*/
public function checkIfEntityRestricted(Entity $entity, $action)
{
if ($this->isAdmin) return true;
@@ -93,12 +99,28 @@ class RestrictionService
});
});
})
// Page unrestricted, Has an unrestricted chapter & book has accepted restrictions
->orWhere(function ($query) {
$query->where('restricted', '=', false)
->whereExists(function ($query) {
$query->select('*')->from('chapters')
->whereRaw('chapters.id=pages.chapter_id')->where('restricted', '=', false);
})
->whereExists(function ($query) {
$query->select('*')->from('books')
->whereRaw('books.id=pages.book_id')
->whereExists(function ($query) {
$this->checkRestrictionsQuery($query, 'books', 'Book');
});
});
})
// Page unrestricted, Has a chapter with accepted permissions
->orWhere(function ($query) {
$query->where('restricted', '=', false)
->whereExists(function ($query) {
$query->select('*')->from('chapters')
->whereRaw('chapters.id=pages.chapter_id')
->where('restricted', '=', true)
->whereExists(function ($query) {
$this->checkRestrictionsQuery($query, 'chapters', 'Chapter');
});
@@ -183,8 +205,10 @@ class RestrictionService
return $query->where(function ($parentWhereQuery) {
$parentWhereQuery
->where('restricted', '=', false)
->orWhereExists(function ($query) {
$this->checkRestrictionsQuery($query, 'books', 'Book');
->orWhere(function ($query) {
$query->where('restricted', '=', true)->whereExists(function ($query) {
$this->checkRestrictionsQuery($query, 'books', 'Book');
});
});
});
}

View File

@@ -1,10 +1,10 @@
<?php
if (! function_exists('versioned_asset')) {
if (!function_exists('versioned_asset')) {
/**
* Get the path to a versioned file.
*
* @param string $file
* @param string $file
* @return string
*
* @throws \InvalidArgumentException
@@ -39,6 +39,7 @@ if (! function_exists('versioned_asset')) {
*/
function userCan($permission, \BookStack\Ownable $ownable = null)
{
if (!auth()->check()) return false;
if ($ownable === null) {
return auth()->user() && auth()->user()->can($permission);
}
@@ -47,9 +48,9 @@ function userCan($permission, \BookStack\Ownable $ownable = null)
$permissionBaseName = strtolower($permission) . '-';
$hasPermission = false;
if (auth()->user()->can($permissionBaseName . 'all')) $hasPermission = true;
if (auth()->user()->can($permissionBaseName . 'own') && $ownable->createdBy->id === auth()->user()->id) $hasPermission = true;
if (auth()->user()->can($permissionBaseName . 'own') && $ownable->createdBy && $ownable->createdBy->id === auth()->user()->id) $hasPermission = true;
if(!$ownable instanceof \BookStack\Entity) return $hasPermission;
if (!$ownable instanceof \BookStack\Entity) return $hasPermission;
// Check restrictions on the entitiy
$restrictionService = app('BookStack\Services\RestrictionService');