mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-10-25 06:37:36 +03:00
As per PR #5800 * DB: Planned out new entity table format via migrations * DB: Created entity migration logic Made some other tweaks/fixes while testing. * DB: Added change of entity relation columns to suit new entities table * DB: Got most view queries working for new structure * Entities: Started logic change to new structure Updated base entity class, and worked through BaseRepo. Need to go through other repos next. Removed a couple of redundant interfaces as part of this since we can move the logic onto the shared ContainerData model as needed. * Entities: Been through repos to update for new format * Entities: Updated repos to act on refreshed clones Changes to core entity models are now done on clones to ensure clean state before save, and those clones are returned back if changes are needed after that action. * Entities: Updated model classes & relations for changes * Entities: Changed from *Data to a common "contents" system Added smart loading from builder instances which should hydrate with "contents()" loaded via join, while keeping the core model original. * Entities: Moved entity description/covers to own non-model classes Added back some interfaces. * Entities: Removed use of contents system for data access * Entities: Got most queries back to working order * Entities: Reverted back to data from contents, fixed various issues * Entities: Started addressing issues from tests * Entities: Addressed further tests/issues * Entities: Been through tests to get all passing in dev Fixed issues and needed test changes along the way. * Entities: Addressed phpstan errors * Entities: Reviewed TODO notes * Entities: Ensured book/shelf relation data removed on destroy * Entities: Been through API responses & adjusted field visibility * Entities: Added type index to massively improve query speed
715 lines
26 KiB
PHP
715 lines
26 KiB
PHP
<?php
|
|
|
|
namespace Tests\Permissions;
|
|
|
|
use BookStack\Entities\Models\Book;
|
|
use BookStack\Entities\Models\Bookshelf;
|
|
use BookStack\Entities\Models\Chapter;
|
|
use BookStack\Entities\Models\Entity;
|
|
use BookStack\Entities\Models\Page;
|
|
use BookStack\Permissions\Permission;
|
|
use BookStack\Users\Models\Role;
|
|
use BookStack\Users\Models\User;
|
|
use Exception;
|
|
use Illuminate\Support\Str;
|
|
use Tests\TestCase;
|
|
|
|
class EntityPermissionsTest extends TestCase
|
|
{
|
|
protected User $user;
|
|
protected User $viewer;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->user = $this->users->editor();
|
|
$this->viewer = $this->users->viewer();
|
|
}
|
|
|
|
protected function setRestrictionsForTestRoles(Entity $entity, array $actions = []): void
|
|
{
|
|
$roles = [
|
|
$this->user->roles->first(),
|
|
$this->viewer->roles->first(),
|
|
];
|
|
$this->permissions->setEntityPermissions($entity, $actions, $roles);
|
|
}
|
|
|
|
public function test_bookshelf_view_restriction()
|
|
{
|
|
$shelf = $this->entities->shelf();
|
|
|
|
$this->actingAs($this->user)
|
|
->get($shelf->getUrl())
|
|
->assertStatus(200);
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, []);
|
|
|
|
$this->followingRedirects()->get($shelf->getUrl())
|
|
->assertSee('Shelf not found');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view']);
|
|
|
|
$this->get($shelf->getUrl())
|
|
->assertSee($shelf->name);
|
|
}
|
|
|
|
public function test_bookshelf_update_restriction()
|
|
{
|
|
$shelf = $this->entities->shelf();
|
|
|
|
$this->actingAs($this->user)
|
|
->get($shelf->getUrl('/edit'))
|
|
->assertSee('Edit Shelf');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
|
|
|
|
$resp = $this->get($shelf->getUrl('/edit'))
|
|
->assertRedirect('/');
|
|
$this->followRedirects($resp)->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
|
|
|
|
$this->get($shelf->getUrl('/edit'))
|
|
->assertOk();
|
|
}
|
|
|
|
public function test_bookshelf_delete_restriction()
|
|
{
|
|
$shelf = $this->entities->shelf();
|
|
|
|
$this->actingAs($this->user)
|
|
->get($shelf->getUrl('/delete'))
|
|
->assertSee('Delete Shelf');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
|
|
|
|
$this->get($shelf->getUrl('/delete'))->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
|
|
|
|
$this->get($shelf->getUrl('/delete'))
|
|
->assertOk()
|
|
->assertSee('Delete Shelf');
|
|
}
|
|
|
|
public function test_book_view_restriction()
|
|
{
|
|
$book = $this->entities->book();
|
|
$bookPage = $book->pages->first();
|
|
$bookChapter = $book->chapters->first();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$this->actingAs($this->user)
|
|
->get($bookUrl)
|
|
->assertOk();
|
|
|
|
$this->setRestrictionsForTestRoles($book, []);
|
|
|
|
$this->followingRedirects()->get($bookUrl)
|
|
->assertSee('Book not found');
|
|
$this->followingRedirects()->get($bookPage->getUrl())
|
|
->assertSee('Page not found');
|
|
$this->followingRedirects()->get($bookChapter->getUrl())
|
|
->assertSee('Chapter not found');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view']);
|
|
|
|
$this->get($bookUrl)
|
|
->assertSee($book->name);
|
|
$this->get($bookPage->getUrl())
|
|
->assertSee($bookPage->name);
|
|
$this->get($bookChapter->getUrl())
|
|
->assertSee($bookChapter->name);
|
|
}
|
|
|
|
public function test_book_create_restriction()
|
|
{
|
|
$book = $this->entities->book();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$resp = $this->actingAs($this->viewer)->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
|
|
->assertElementNotContains('.actions', 'New Chapter');
|
|
$resp = $this->actingAs($this->user)->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementContains('.actions', 'New Page')
|
|
->assertElementContains('.actions', 'New Chapter');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'delete', 'update']);
|
|
|
|
$this->get($bookUrl . '/create-chapter')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->get($bookUrl . '/create-page')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$resp = $this->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
|
|
->assertElementNotContains('.actions', 'New Chapter');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'create']);
|
|
|
|
$resp = $this->post($book->getUrl('/create-chapter'), [
|
|
'name' => 'test chapter',
|
|
'description' => 'desc',
|
|
]);
|
|
$resp->assertRedirect($book->getUrl('/chapter/test-chapter'));
|
|
|
|
$this->get($book->getUrl('/create-page'));
|
|
/** @var Page $page */
|
|
$page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first();
|
|
$resp = $this->post($page->getUrl(), [
|
|
'name' => 'test page',
|
|
'html' => 'test content',
|
|
]);
|
|
$resp->assertRedirect($book->getUrl('/page/test-page'));
|
|
|
|
$resp = $this->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementContains('.actions', 'New Page')
|
|
->assertElementContains('.actions', 'New Chapter');
|
|
}
|
|
|
|
public function test_book_update_restriction()
|
|
{
|
|
$book = $this->entities->book();
|
|
$bookPage = $book->pages->first();
|
|
$bookChapter = $book->chapters->first();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$this->actingAs($this->user)
|
|
->get($bookUrl . '/edit')
|
|
->assertSee('Edit Book');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'delete']);
|
|
|
|
$this->get($bookUrl . '/edit')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookPage->getUrl() . '/edit')->assertRedirect($bookPage->getUrl());
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookChapter->getUrl() . '/edit')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'update']);
|
|
|
|
$this->get($bookUrl . '/edit')->assertOk();
|
|
$this->get($bookPage->getUrl() . '/edit')->assertOk();
|
|
$this->get($bookChapter->getUrl() . '/edit')->assertSee('Edit Chapter');
|
|
}
|
|
|
|
public function test_book_delete_restriction()
|
|
{
|
|
$book = $this->entities->book();
|
|
$bookPage = $book->pages->first();
|
|
$bookChapter = $book->chapters->first();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$this->actingAs($this->user)->get($bookUrl . '/delete')
|
|
->assertSee('Delete Book');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'update']);
|
|
|
|
$this->get($bookUrl . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookPage->getUrl() . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookChapter->getUrl() . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'delete']);
|
|
|
|
$this->get($bookUrl . '/delete')->assertOk()->assertSee('Delete Book');
|
|
$this->get($bookPage->getUrl('/delete'))->assertOk()->assertSee('Delete Page');
|
|
$this->get($bookChapter->getUrl('/delete'))->assertSee('Delete Chapter');
|
|
}
|
|
|
|
public function test_chapter_view_restriction()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$chapterPage = $chapter->pages->first();
|
|
|
|
$chapterUrl = $chapter->getUrl();
|
|
$this->actingAs($this->user)->get($chapterUrl)->assertOk();
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, []);
|
|
|
|
$this->followingRedirects()->get($chapterUrl)->assertSee('Chapter not found');
|
|
$this->followingRedirects()->get($chapterPage->getUrl())->assertSee('Page not found');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view']);
|
|
|
|
$this->get($chapterUrl)->assertSee($chapter->name);
|
|
$this->get($chapterPage->getUrl())->assertSee($chapterPage->name);
|
|
}
|
|
|
|
public function test_chapter_create_restriction()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
|
|
$chapterUrl = $chapter->getUrl();
|
|
$resp = $this->actingAs($this->user)->get($chapterUrl);
|
|
$this->withHtml($resp)->assertElementContains('.actions', 'New Page');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view', 'delete', 'update']);
|
|
|
|
$this->get($chapterUrl . '/create-page')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->withHtml($this->get($chapterUrl))->assertElementNotContains('.actions', 'New Page');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view', 'create']);
|
|
|
|
$this->get($chapter->getUrl('/create-page'));
|
|
/** @var Page $page */
|
|
$page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first();
|
|
$resp = $this->post($page->getUrl(), [
|
|
'name' => 'test page',
|
|
'html' => 'test content',
|
|
]);
|
|
$resp->assertRedirect($chapter->book->getUrl('/page/test-page'));
|
|
|
|
$this->withHtml($this->get($chapterUrl))->assertElementContains('.actions', 'New Page');
|
|
}
|
|
|
|
public function test_chapter_update_restriction()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$chapterPage = $chapter->pages->first();
|
|
|
|
$chapterUrl = $chapter->getUrl();
|
|
$this->actingAs($this->user)->get($chapterUrl . '/edit')
|
|
->assertSee('Edit Chapter');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view', 'delete']);
|
|
|
|
$this->get($chapterUrl . '/edit')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($chapterPage->getUrl() . '/edit')->assertRedirect($chapterPage->getUrl());
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view', 'update']);
|
|
|
|
$this->get($chapterUrl . '/edit')->assertOk()->assertSee('Edit Chapter');
|
|
$this->get($chapterPage->getUrl() . '/edit')->assertOk();
|
|
}
|
|
|
|
public function test_chapter_delete_restriction()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$chapterPage = $chapter->pages->first();
|
|
|
|
$chapterUrl = $chapter->getUrl();
|
|
$this->actingAs($this->user)
|
|
->get($chapterUrl . '/delete')
|
|
->assertSee('Delete Chapter');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view', 'update']);
|
|
|
|
$this->get($chapterUrl . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($chapterPage->getUrl() . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($chapter, ['view', 'delete']);
|
|
|
|
$this->get($chapterUrl . '/delete')->assertOk()->assertSee('Delete Chapter');
|
|
$this->get($chapterPage->getUrl() . '/delete')->assertOk()->assertSee('Delete Page');
|
|
}
|
|
|
|
public function test_page_view_restriction()
|
|
{
|
|
$page = $this->entities->page();
|
|
|
|
$pageUrl = $page->getUrl();
|
|
$this->actingAs($this->user)->get($pageUrl)->assertOk();
|
|
|
|
$this->setRestrictionsForTestRoles($page, ['update', 'delete']);
|
|
|
|
$this->get($pageUrl)->assertSee('Page not found');
|
|
|
|
$this->setRestrictionsForTestRoles($page, ['view']);
|
|
|
|
$this->get($pageUrl)->assertSee($page->name);
|
|
}
|
|
|
|
public function test_page_update_restriction()
|
|
{
|
|
$page = $this->entities->page();
|
|
|
|
$pageUrl = $page->getUrl();
|
|
$resp = $this->actingAs($this->user)
|
|
->get($pageUrl . '/edit');
|
|
$this->withHtml($resp)->assertElementExists('input[name="name"][value="' . $page->name . '"]');
|
|
|
|
$this->setRestrictionsForTestRoles($page, ['view', 'delete']);
|
|
|
|
$this->get($pageUrl . '/edit')->assertRedirect($pageUrl);
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($page, ['view', 'update']);
|
|
|
|
$resp = $this->get($pageUrl . '/edit')
|
|
->assertOk();
|
|
$this->withHtml($resp)->assertElementExists('input[name="name"][value="' . $page->name . '"]');
|
|
}
|
|
|
|
public function test_page_delete_restriction()
|
|
{
|
|
$page = $this->entities->page();
|
|
|
|
$pageUrl = $page->getUrl();
|
|
$this->actingAs($this->user)
|
|
->get($pageUrl . '/delete')
|
|
->assertSee('Delete Page');
|
|
|
|
$this->setRestrictionsForTestRoles($page, ['view', 'update']);
|
|
|
|
$this->get($pageUrl . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($page, ['view', 'delete']);
|
|
|
|
$this->get($pageUrl . '/delete')->assertOk()->assertSee('Delete Page');
|
|
}
|
|
|
|
protected function entityRestrictionFormTest(string $model, string $title, string $permission, string $roleId)
|
|
{
|
|
/** @var Entity $modelInstance */
|
|
$modelInstance = $model::query()->first();
|
|
$this->asAdmin()->get($modelInstance->getUrl('/permissions'))
|
|
->assertSee($title);
|
|
|
|
$this->put($modelInstance->getUrl('/permissions'), [
|
|
'permissions' => [
|
|
$roleId => [
|
|
$permission => 'true',
|
|
],
|
|
],
|
|
]);
|
|
|
|
$this->assertDatabaseHas('entity_permissions', [
|
|
'entity_id' => $modelInstance->id,
|
|
'entity_type' => $modelInstance->getMorphClass(),
|
|
'role_id' => $roleId,
|
|
$permission => true,
|
|
]);
|
|
}
|
|
|
|
public function test_bookshelf_restriction_form()
|
|
{
|
|
$this->entityRestrictionFormTest(Bookshelf::class, 'Shelf Permissions', 'view', '2');
|
|
}
|
|
|
|
public function test_book_restriction_form()
|
|
{
|
|
$this->entityRestrictionFormTest(Book::class, 'Book Permissions', 'view', '2');
|
|
}
|
|
|
|
public function test_chapter_restriction_form()
|
|
{
|
|
$this->entityRestrictionFormTest(Chapter::class, 'Chapter Permissions', 'update', '2');
|
|
}
|
|
|
|
public function test_page_restriction_form()
|
|
{
|
|
$this->entityRestrictionFormTest(Page::class, 'Page Permissions', 'delete', '2');
|
|
}
|
|
|
|
public function test_shelf_create_permission_visible_with_notice()
|
|
{
|
|
$shelf = $this->entities->shelf();
|
|
|
|
$resp = $this->asAdmin()->get($shelf->getUrl('/permissions'));
|
|
$html = $this->withHtml($resp);
|
|
$html->assertElementExists('input[name$="[create]"]');
|
|
$resp->assertSee('Shelf create permissions are only used for copying permissions to child books using the action below.');
|
|
}
|
|
|
|
public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$page = $chapter->pages->first();
|
|
$page2 = $chapter->pages[2];
|
|
|
|
$this->setRestrictionsForTestRoles($page, []);
|
|
|
|
$resp = $this->actingAs($this->user)->get($page2->getUrl());
|
|
$this->withHtml($resp)->assertElementNotContains('.sidebar-page-list', $page->name);
|
|
}
|
|
|
|
public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$page = $chapter->pages->first();
|
|
|
|
$this->setRestrictionsForTestRoles($page, []);
|
|
|
|
$resp = $this->actingAs($this->user)->get($chapter->getUrl());
|
|
$this->withHtml($resp)->assertElementNotContains('.sidebar-page-list', $page->name);
|
|
}
|
|
|
|
public function test_restricted_pages_not_visible_on_chapter_pages()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$page = $chapter->pages->first();
|
|
|
|
$this->setRestrictionsForTestRoles($page, []);
|
|
|
|
$this->actingAs($this->user)
|
|
->get($chapter->getUrl())
|
|
->assertDontSee($page->name);
|
|
}
|
|
|
|
public function test_restricted_chapter_pages_not_visible_on_book_page()
|
|
{
|
|
$chapter = $this->entities->chapter();
|
|
$this->actingAs($this->user)
|
|
->get($chapter->book->getUrl())
|
|
->assertSee($chapter->pages->first()->name);
|
|
|
|
foreach ($chapter->pages as $page) {
|
|
$this->setRestrictionsForTestRoles($page, []);
|
|
}
|
|
|
|
$this->actingAs($this->user)
|
|
->get($chapter->book->getUrl())
|
|
->assertDontSee($chapter->pages->first()->name);
|
|
}
|
|
|
|
public function test_bookshelf_update_restriction_override()
|
|
{
|
|
$shelf = $this->entities->shelf();
|
|
|
|
$this->actingAs($this->viewer)
|
|
->get($shelf->getUrl('/edit'))
|
|
->assertDontSee('Edit Book');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
|
|
|
|
$this->get($shelf->getUrl('/edit'))->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
|
|
|
|
$this->get($shelf->getUrl('/edit'))->assertOk();
|
|
}
|
|
|
|
public function test_bookshelf_delete_restriction_override()
|
|
{
|
|
$shelf = $this->entities->shelf();
|
|
|
|
$this->actingAs($this->viewer)
|
|
->get($shelf->getUrl('/delete'))
|
|
->assertDontSee('Delete Book');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
|
|
|
|
$this->get($shelf->getUrl('/delete'))->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
|
|
|
|
$this->get($shelf->getUrl('/delete'))->assertOk()->assertSee('Delete Shelf');
|
|
}
|
|
|
|
public function test_book_create_restriction_override()
|
|
{
|
|
$book = $this->entities->book();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$resp = $this->actingAs($this->viewer)->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
|
|
->assertElementNotContains('.actions', 'New Chapter');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'delete', 'update']);
|
|
|
|
$this->get($bookUrl . '/create-chapter')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookUrl . '/create-page')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$resp = $this->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
|
|
->assertElementNotContains('.actions', 'New Chapter');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'create']);
|
|
|
|
$resp = $this->post($book->getUrl('/create-chapter'), [
|
|
'name' => 'test chapter',
|
|
'description' => 'test desc',
|
|
]);
|
|
$resp->assertRedirect($book->getUrl('/chapter/test-chapter'));
|
|
|
|
$this->get($book->getUrl('/create-page'));
|
|
/** @var Page $page */
|
|
$page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first();
|
|
$resp = $this->post($page->getUrl(), [
|
|
'name' => 'test page',
|
|
'html' => 'test desc',
|
|
]);
|
|
$resp->assertRedirect($book->getUrl('/page/test-page'));
|
|
|
|
$resp = $this->get($bookUrl);
|
|
$this->withHtml($resp)->assertElementContains('.actions', 'New Page')
|
|
->assertElementContains('.actions', 'New Chapter');
|
|
}
|
|
|
|
public function test_book_update_restriction_override()
|
|
{
|
|
$book = $this->entities->book();
|
|
$bookPage = $book->pages->first();
|
|
$bookChapter = $book->chapters->first();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$this->actingAs($this->viewer)->get($bookUrl . '/edit')
|
|
->assertDontSee('Edit Book');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'delete']);
|
|
|
|
$this->get($bookUrl . '/edit')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookPage->getUrl() . '/edit')->assertRedirect($bookPage->getUrl());
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookChapter->getUrl() . '/edit')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'update']);
|
|
|
|
$this->get($bookUrl . '/edit')->assertOk();
|
|
$this->get($bookPage->getUrl() . '/edit')->assertOk();
|
|
$this->get($bookChapter->getUrl() . '/edit')->assertSee('Edit Chapter');
|
|
}
|
|
|
|
public function test_book_delete_restriction_override()
|
|
{
|
|
$book = $this->entities->book();
|
|
$bookPage = $book->pages->first();
|
|
$bookChapter = $book->chapters->first();
|
|
|
|
$bookUrl = $book->getUrl();
|
|
$this->actingAs($this->viewer)
|
|
->get($bookUrl . '/delete')
|
|
->assertDontSee('Delete Book');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'update']);
|
|
|
|
$this->get($bookUrl . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookPage->getUrl() . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
$this->get($bookChapter->getUrl() . '/delete')->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
$this->setRestrictionsForTestRoles($book, ['view', 'delete']);
|
|
|
|
$this->get($bookUrl . '/delete')->assertOk()->assertSee('Delete Book');
|
|
$this->get($bookPage->getUrl() . '/delete')->assertOk()->assertSee('Delete Page');
|
|
$this->get($bookChapter->getUrl() . '/delete')->assertSee('Delete Chapter');
|
|
}
|
|
|
|
public function test_page_visible_if_has_permissions_when_book_not_visible()
|
|
{
|
|
$book = $this->entities->book();
|
|
$bookChapter = $book->chapters->first();
|
|
$bookPage = $bookChapter->pages->first();
|
|
|
|
foreach ([$book, $bookChapter, $bookPage] as $entity) {
|
|
$entity->name = Str::random(24);
|
|
$entity->save();
|
|
}
|
|
|
|
$this->setRestrictionsForTestRoles($book, []);
|
|
$this->setRestrictionsForTestRoles($bookPage, ['view']);
|
|
|
|
$this->actingAs($this->viewer);
|
|
$resp = $this->get($bookPage->getUrl());
|
|
$resp->assertOk();
|
|
$resp->assertSee($bookPage->name);
|
|
$resp->assertDontSee(substr($book->name, 0, 15));
|
|
$resp->assertDontSee(substr($bookChapter->name, 0, 15));
|
|
}
|
|
|
|
public function test_book_sort_view_permission()
|
|
{
|
|
$firstBook = $this->entities->book();
|
|
$secondBook = $this->entities->book();
|
|
|
|
$this->setRestrictionsForTestRoles($firstBook, ['view', 'update']);
|
|
$this->setRestrictionsForTestRoles($secondBook, ['view']);
|
|
|
|
// Test sort page visibility
|
|
$this->actingAs($this->user)->get($secondBook->getUrl('/sort'))->assertRedirect('/');
|
|
$this->get('/')->assertSee('You do not have permission');
|
|
|
|
// Check sort page on first book
|
|
$this->actingAs($this->user)->get($firstBook->getUrl('/sort'));
|
|
}
|
|
|
|
public function test_can_create_page_if_chapter_has_permissions_when_book_not_visible()
|
|
{
|
|
$book = $this->entities->book();
|
|
$this->setRestrictionsForTestRoles($book, []);
|
|
$bookChapter = $book->chapters->first();
|
|
$this->setRestrictionsForTestRoles($bookChapter, ['view']);
|
|
|
|
$this->actingAs($this->user)->get($bookChapter->getUrl())
|
|
->assertDontSee('New Page');
|
|
|
|
$this->setRestrictionsForTestRoles($bookChapter, ['view', 'create']);
|
|
|
|
$this->get($bookChapter->getUrl('/create-page'));
|
|
/** @var Page $page */
|
|
$page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first();
|
|
$resp = $this->post($page->getUrl(), [
|
|
'name' => 'test page',
|
|
'html' => 'test content',
|
|
]);
|
|
$resp->assertRedirect($book->getUrl('/page/test-page'));
|
|
}
|
|
|
|
public function test_access_to_item_prevented_if_inheritance_active_but_permission_prevented_via_role()
|
|
{
|
|
$user = $this->users->viewer();
|
|
$viewerRole = $user->roles->first();
|
|
$chapter = $this->entities->chapter();
|
|
$book = $chapter->book;
|
|
|
|
$this->permissions->setEntityPermissions($book, ['update'], [$viewerRole], false);
|
|
$this->permissions->setEntityPermissions($chapter, [], [$viewerRole], true);
|
|
|
|
$this->assertFalse(userCan(Permission::ChapterUpdate, $chapter));
|
|
}
|
|
|
|
public function test_access_to_item_allowed_if_inheritance_active_and_permission_prevented_via_role_but_allowed_via_parent()
|
|
{
|
|
$user = $this->users->viewer();
|
|
$viewerRole = $user->roles->first();
|
|
$editorRole = Role::getRole('Editor');
|
|
$user->attachRole($editorRole);
|
|
$chapter = $this->entities->chapter();
|
|
$book = $chapter->book;
|
|
|
|
$this->permissions->setEntityPermissions($book, ['update'], [$editorRole], false);
|
|
$this->permissions->setEntityPermissions($chapter, [], [$viewerRole], true);
|
|
|
|
$this->actingAs($user);
|
|
$this->assertTrue(userCan(Permission::ChapterUpdate, $chapter));
|
|
}
|
|
|
|
public function test_book_permissions_can_be_generated_without_error_if_child_chapter_is_in_recycle_bin()
|
|
{
|
|
$book = $this->entities->bookHasChaptersAndPages();
|
|
/** @var Chapter $chapter */
|
|
$chapter = $book->chapters()->first();
|
|
|
|
$this->asAdmin()->delete($chapter->getUrl());
|
|
|
|
$error = null;
|
|
try {
|
|
$this->permissions->setEntityPermissions($book, ['view'], []);
|
|
} catch (Exception $e) {
|
|
$error = $e;
|
|
}
|
|
|
|
$this->assertNull($error);
|
|
}
|
|
}
|