diff --git a/dev/docs/permission-scenario-testing.md b/dev/docs/permission-scenario-testing.md index b45ffd87f..5797ee362 100644 --- a/dev/docs/permission-scenario-testing.md +++ b/dev/docs/permission-scenario-testing.md @@ -6,6 +6,64 @@ Test cases are written ability abstract, since all abilities should act the same ## Cases +TODO - User permissions +TODO - Role & entity-role interplay +TODO - entity-user permissions +TODO - entity-user & entity-role interplay + +### Content Role Permissions + +These are tests related to item/entity permissions that are set only at a role level. + +#### test_01_allow + +- Role A has role all-page permission. +- User has Role A. + +User granted page permission. + +#### test_02_deny + +- Role A has no page permission. +- User has Role A. + +User denied page permission. + +#### test_10_allow_on_own_with_own + +- Role A has role own-page permission. +- User has Role A. +- User is owner of page. + +User granted page permission. + +#### test_11_deny_on_other_with_own + +- Role A has role own-page permission. +- User has Role A. +- User is not owner of page. + +User denied page permission. + +#### test_20_multiple_role_conflicting_all + +- Role A has role all-page permission. +- Role B has no page permission. +- User has Role A & B. + +User granted page permission. + +#### test_21_multiple_role_conflicting_own + +- Role A has role own-page permission. +- Role B has no page permission. +- User has Role A & B. +- User is owner of page. + +User granted page permission. + +--- + ### Entity Role Permissions These are tests related to entity-level role-specific permission overrides. @@ -16,7 +74,7 @@ These are tests related to entity-level role-specific permission overrides. - Role A has entity allow page permission. - User has Role A. -User should have page permission. +User granted page permission. #### test_02_explicit_deny @@ -33,7 +91,7 @@ User denied page permission. - Role B has entity deny page permission. - User has both Role A & B. -User should have page permission. +User granted page permission. Explicit grant overrides entity deny at same level. #### test_20_inherit_allow @@ -41,16 +99,16 @@ Explicit grant overrides entity deny at same level. - Page permissions have inherit enabled. - Chapter permissions has inherit disabled. - Role A has entity allow chapter permission. -- User has both Role A. +- User has Role A. -User should have page permission. +User granted page permission. #### test_21_inherit_deny - Page permissions have inherit enabled. - Chapter permissions has inherit disabled. - Role A has entity deny chapter permission. -- User has both Role A. +- User has Role A. User denied page permission. @@ -62,7 +120,7 @@ User denied page permission. - Role B has entity allow chapter permission. - User has both Role A & B. -User should have page permission. +User granted page permission. #### test_30_child_inherit_override_allow @@ -72,7 +130,7 @@ User should have page permission. - Role A has entity allow page permission. - User has Role A. -User should have page permission. +User granted page permission. #### test_31_child_inherit_override_deny diff --git a/tests/Helpers/PermissionsProvider.php b/tests/Helpers/PermissionsProvider.php index 1406cf4cf..bf14ac2da 100644 --- a/tests/Helpers/PermissionsProvider.php +++ b/tests/Helpers/PermissionsProvider.php @@ -56,6 +56,16 @@ class PermissionsProvider } } + /** + * Change the owner of the given entity to the given user. + */ + public function changeEntityOwner(Entity $entity, User $newOwner): void + { + $entity->owned_by = $newOwner->id; + $entity->save(); + $entity->rebuildPermissions(); + } + /** * Regenerate the permission for an entity. * Centralised to manage clearing of cached elements between requests. diff --git a/tests/Permissions/Scenarios/EntityRolePermissions.php b/tests/Permissions/Scenarios/EntityRolePermissions.php index 66bb64f22..908b07e8c 100644 --- a/tests/Permissions/Scenarios/EntityRolePermissions.php +++ b/tests/Permissions/Scenarios/EntityRolePermissions.php @@ -2,13 +2,7 @@ namespace Tests\Permissions\Scenarios; -use BookStack\Auth\User; -use BookStack\Entities\Models\Entity; -use Tests\TestCase; - -// Cases defined in dev/docs/permission-scenario-testing.md - -class EntityRolePermissions extends TestCase +class EntityRolePermissions extends PermissionScenarioTestCase { public function test_01_explicit_allow() { @@ -104,30 +98,4 @@ class EntityRolePermissions extends TestCase $this->assertNotVisibleToUser($page, $user); } - - protected function assertVisibleToUser(Entity $entity, User $user) - { - $this->actingAs($user); - $funcView = userCan($entity->getMorphClass() . '-view', $entity); - $queryView = $entity->newQuery()->scopes(['visible'])->find($entity->id) !== null; - - $id = $entity->getMorphClass() . ':' . $entity->id; - $msg = "Item [{$id}] should be visible but was not found via "; - $msg .= implode(' and ', array_filter([!$funcView ? 'userCan' : '', !$queryView ? 'query' : ''])); - - static::assertTrue($funcView && $queryView, $msg); - } - - protected function assertNotVisibleToUser(Entity $entity, User $user) - { - $this->actingAs($user); - $funcView = userCan($entity->getMorphClass() . '-view', $entity); - $queryView = $entity->newQuery()->scopes(['visible'])->find($entity->id) !== null; - - $id = $entity->getMorphClass() . ':' . $entity->id; - $msg = "Item [{$id}] should not be visible but was found via "; - $msg .= implode(' and ', array_filter([$funcView ? 'userCan' : '', $queryView ? 'query' : ''])); - - static::assertTrue(!$funcView && !$queryView, $msg); - } } diff --git a/tests/Permissions/Scenarios/PermissionScenarioTestCase.php b/tests/Permissions/Scenarios/PermissionScenarioTestCase.php new file mode 100644 index 000000000..5352f468a --- /dev/null +++ b/tests/Permissions/Scenarios/PermissionScenarioTestCase.php @@ -0,0 +1,38 @@ +actingAs($user); + $funcView = userCan($entity->getMorphClass() . '-view', $entity); + $queryView = $entity->newQuery()->scopes(['visible'])->find($entity->id) !== null; + + $id = $entity->getMorphClass() . ':' . $entity->id; + $msg = "Item [{$id}] should be visible but was not found via "; + $msg .= implode(' and ', array_filter([!$funcView ? 'userCan' : '', !$queryView ? 'query' : ''])); + + static::assertTrue($funcView && $queryView, $msg); + } + + protected function assertNotVisibleToUser(Entity $entity, User $user) + { + $this->actingAs($user); + $funcView = userCan($entity->getMorphClass() . '-view', $entity); + $queryView = $entity->newQuery()->scopes(['visible'])->find($entity->id) !== null; + + $id = $entity->getMorphClass() . ':' . $entity->id; + $msg = "Item [{$id}] should not be visible but was found via "; + $msg .= implode(' and ', array_filter([$funcView ? 'userCan' : '', $queryView ? 'query' : ''])); + + static::assertTrue(!$funcView && !$queryView, $msg); + } +} diff --git a/tests/Permissions/Scenarios/RoleContentPermissions.php b/tests/Permissions/Scenarios/RoleContentPermissions.php new file mode 100644 index 000000000..38e9ac9f7 --- /dev/null +++ b/tests/Permissions/Scenarios/RoleContentPermissions.php @@ -0,0 +1,59 @@ +users->newUserWithRole([], ['page-view-all']); + $page = $this->entities->page(); + + $this->assertVisibleToUser($page, $user); + } + + public function test_02_deny() + { + [$user] = $this->users->newUserWithRole([], []); + $page = $this->entities->page(); + + $this->assertNotVisibleToUser($page, $user); + } + + public function test_10_allow_on_own_with_own() + { + [$user] = $this->users->newUserWithRole([], ['page-view-own']); + $page = $this->entities->page(); + $this->permissions->changeEntityOwner($page, $user); + + $this->assertVisibleToUser($page, $user); + } + + public function test_11_deny_on_other_with_own() + { + [$user] = $this->users->newUserWithRole([], ['page-view-own']); + $page = $this->entities->page(); + $this->permissions->changeEntityOwner($page, $this->users->editor()); + + $this->assertNotVisibleToUser($page, $user); + } + + public function test_20_multiple_role_conflicting_all() + { + [$user] = $this->users->newUserWithRole([], ['page-view-all']); + $this->users->attachNewRole($user, []); + $page = $this->entities->page(); + + $this->assertVisibleToUser($page, $user); + } + + public function test_21_multiple_role_conflicting_own() + { + [$user] = $this->users->newUserWithRole([], ['page-view-own']); + $this->users->attachNewRole($user, []); + $page = $this->entities->page(); + $this->permissions->changeEntityOwner($page, $user); + + $this->assertVisibleToUser($page, $user); + } +}