Addressed fallback override cases found during testing

Had misalignment between query and usercan, The nuance between fallback
and entity-role permissions was not taken into account by the query
system. Now added with new test cases to cover.
This commit is contained in:
Dan Brown 2023-01-24 20:42:20 +00:00
parent d1bd6d0e39
commit 8be36455ab
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
6 changed files with 192 additions and 9 deletions

View File

@ -25,22 +25,24 @@ class EntityPermissionEvaluator
$relevantPermissions = $this->getPermissionsMapByTypeId($typeIdChain, [...$userRoleIds, 0]); $relevantPermissions = $this->getPermissionsMapByTypeId($typeIdChain, [...$userRoleIds, 0]);
$permitsByType = $this->collapseAndCategorisePermissions($typeIdChain, $relevantPermissions); $permitsByType = $this->collapseAndCategorisePermissions($typeIdChain, $relevantPermissions);
return $this->evaluatePermitsByType($permitsByType); $status = $this->evaluatePermitsByType($permitsByType);
return is_null($status) ? null : $status === PermissionStatus::IMPLICIT_ALLOW || $status === PermissionStatus::EXPLICIT_ALLOW;
} }
/** /**
* @param array<string, array<string, int>> $permitsByType * @param array<string, array<string, int>> $permitsByType
*/ */
protected function evaluatePermitsByType(array $permitsByType): ?bool protected function evaluatePermitsByType(array $permitsByType): ?int
{ {
// Return grant or reject from role-level if exists // Return grant or reject from role-level if exists
if (count($permitsByType['role']) > 0) { if (count($permitsByType['role']) > 0) {
return boolval(max($permitsByType['role'])); return max($permitsByType['role']) ? PermissionStatus::EXPLICIT_ALLOW : PermissionStatus::EXPLICIT_DENY;
} }
// Return fallback permission if exists // Return fallback permission if exists
if (count($permitsByType['fallback']) > 0) { if (count($permitsByType['fallback']) > 0) {
return boolval($permitsByType['fallback'][0]); return $permitsByType['fallback'][0] ? PermissionStatus::IMPLICIT_ALLOW : PermissionStatus::IMPLICIT_DENY;
} }
return null; return null;

View File

@ -262,8 +262,7 @@ class JointPermissionBuilder
// Return evaluated entity permission status if it has an affect. // Return evaluated entity permission status if it has an affect.
$entityPermissionStatus = $permissionMap->evaluateEntityForRole($entity, $roleId); $entityPermissionStatus = $permissionMap->evaluateEntityForRole($entity, $roleId);
if ($entityPermissionStatus !== null) { if ($entityPermissionStatus !== null) {
$status = $entityPermissionStatus ? PermissionStatus::EXPLICIT_ALLOW : PermissionStatus::EXPLICIT_DENY; return $this->createJointPermissionDataArray($entity, $roleId, $entityPermissionStatus, false);
return $this->createJointPermissionDataArray($entity, $roleId, $status, $entityPermissionStatus);
} }
// Otherwise default to the role-level permissions // Otherwise default to the role-level permissions

View File

@ -16,7 +16,7 @@ class MassEntityPermissionEvaluator extends EntityPermissionEvaluator
parent::__construct($action); parent::__construct($action);
} }
public function evaluateEntityForRole(SimpleEntityData $entity, int $roleId): ?bool public function evaluateEntityForRole(SimpleEntityData $entity, int $roleId): ?int
{ {
$typeIdChain = $this->gatherEntityChainTypeIds($entity); $typeIdChain = $this->gatherEntityChainTypeIds($entity);
$relevantPermissions = $this->getPermissionMapByTypeIdForChainAndRole($typeIdChain, $roleId); $relevantPermissions = $this->getPermissionMapByTypeIdForChainAndRole($typeIdChain, $roleId);

View File

@ -229,7 +229,7 @@ User denied page permission.
User denied page permission. User denied page permission.
#### test_80_multi_role_inherited_deny_via_parent #### test_75_multi_role_inherited_deny_via_parent
- Page permissions have inherit enabled. - Page permissions have inherit enabled.
- Chapter permissions have inherit enabled. - Chapter permissions have inherit enabled.
@ -238,3 +238,83 @@ User denied page permission.
- User has Role A & B. - User has Role A & B.
User denied page permission. User denied page permission.
#### test_80_fallback_override_allow
- Page permissions have inherit disabled.
- Page fallback has entity deny permission.
- Role A has entity allow page permission.
- User has Role A.
User granted page permission.
#### test_81_fallback_override_deny
- Page permissions have inherit disabled.
- Page fallback has entity allow permission.
- Role A has entity deny page permission.
- User has Role A.
User denied page permission.
#### test_84_fallback_override_allow_multi_role
- Page permissions have inherit disabled.
- Page fallback has entity deny permission.
- Role A has entity allow page permission.
- Role B has no entity page permissions.
- User has Role A & B.
User granted page permission.
#### test_85_fallback_override_deny_multi_role
- Page permissions have inherit disabled.
- Page fallback has entity allow permission.
- Role A has entity deny page permission.
- Role B has no entity page permissions.
- User has Role A & B.
User denied page permission.
#### test_86_fallback_override_allow_inherit
- Chapter permissions have inherit disabled.
- Page permissions have inherit enabled.
- Chapter fallback has entity deny permission.
- Role A has entity allow chapter permission.
- User has Role A.
User granted page permission.
#### test_87_fallback_override_deny_inherit
- Chapter permissions have inherit disabled.
- Page permissions have inherit enabled.
- Chapter fallback has entity allow permission.
- Role A has entity deny chapter permission.
- User has Role A.
User denied page permission.
#### test_88_fallback_override_allow_multi_role_inherit
- Chapter permissions have inherit disabled.
- Page permissions have inherit enabled.
- Chapter fallback has entity deny permission.
- Role A has entity allow chapter permission.
- Role B has no entity chapter permissions.
- User has Role A & B.
User granted page permission.
#### test_89_fallback_override_deny_multi_role_inherit
- Chapter permissions have inherit disabled.
- Page permissions have inherit enabled.
- Chapter fallback has entity allow permission.
- Role A has entity deny chapter permission.
- Role B has no entity chapter permissions.
- User has Role A & B.
User denied page permission.

View File

@ -101,6 +101,13 @@ class PermissionsProvider
$this->addEntityPermissionEntries($entity, [$permissionData]); $this->addEntityPermissionEntries($entity, [$permissionData]);
} }
public function setFallbackPermissions(Entity $entity, array $actionList)
{
$entity->permissions()->where('role_id', '=', 0)->delete();
$permissionData = $this->actionListToEntityPermissionData($actionList, 0);
$this->addEntityPermissionEntries($entity, [$permissionData]);
}
/** /**
* Disable inherited permissions on the given entity. * Disable inherited permissions on the given entity.
* Effectively sets the "Other Users" UI permission option to not inherit, with no permissions. * Effectively sets the "Other Users" UI permission option to not inherit, with no permissions.

View File

@ -187,7 +187,7 @@ class EntityRolePermissionsTest extends PermissionScenarioTestCase
$this->assertNotVisibleToUser($page, $user); $this->assertNotVisibleToUser($page, $user);
} }
public function test_80_multi_role_inherited_deny_via_parent() public function test_75_multi_role_inherited_deny_via_parent()
{ {
[$user, $roleA] = $this->users->newUserWithRole([], ['page-view-all']); [$user, $roleA] = $this->users->newUserWithRole([], ['page-view-all']);
$roleB = $this->users->attachNewRole($user); $roleB = $this->users->attachNewRole($user);
@ -198,4 +198,99 @@ class EntityRolePermissionsTest extends PermissionScenarioTestCase
$this->assertNotVisibleToUser($page, $user); $this->assertNotVisibleToUser($page, $user);
} }
public function test_80_fallback_override_allow()
{
[$user, $roleA] = $this->users->newUserWithRole();
$page = $this->entities->page();
$this->permissions->setFallbackPermissions($page, []);
$this->permissions->addEntityPermission($page, ['view'], $roleA);
$this->assertVisibleToUser($page, $user);
}
public function test_81_fallback_override_deny()
{
[$user, $roleA] = $this->users->newUserWithRole();
$page = $this->entities->page();
$this->permissions->setFallbackPermissions($page, ['view']);
$this->permissions->addEntityPermission($page, [], $roleA);
$this->assertNotVisibleToUser($page, $user);
}
public function test_84_fallback_override_allow_multi_role()
{
[$user, $roleA] = $this->users->newUserWithRole();
$roleB = $this->users->attachNewRole($user);
$page = $this->entities->page();
$this->permissions->setFallbackPermissions($page, []);
$this->permissions->addEntityPermission($page, ['view'], $roleA);
$this->assertVisibleToUser($page, $user);
}
public function test_85_fallback_override_deny_multi_role()
{
[$user, $roleA] = $this->users->newUserWithRole();
$roleB = $this->users->attachNewRole($user);
$page = $this->entities->page();
$this->permissions->setFallbackPermissions($page, ['view']);
$this->permissions->addEntityPermission($page, [], $roleA);
$this->assertNotVisibleToUser($page, $user);
}
public function test_86_fallback_override_allow_inherit()
{
[$user, $roleA] = $this->users->newUserWithRole();
$page = $this->entities->page();
$chapter = $page->chapter;
$this->permissions->setFallbackPermissions($chapter, []);
$this->permissions->addEntityPermission($chapter, ['view'], $roleA);
$this->assertVisibleToUser($page, $user);
}
public function test_87_fallback_override_deny_inherit()
{
[$user, $roleA] = $this->users->newUserWithRole();
$page = $this->entities->page();
$chapter = $page->chapter;
$this->permissions->setFallbackPermissions($chapter, ['view']);
$this->permissions->addEntityPermission($chapter, [], $roleA);
$this->assertNotVisibleToUser($page, $user);
}
public function test_88_fallback_override_allow_multi_role_inherit()
{
[$user, $roleA] = $this->users->newUserWithRole();
$roleB = $this->users->attachNewRole($user);
$page = $this->entities->page();
$chapter = $page->chapter;
$this->permissions->setFallbackPermissions($chapter, []);
$this->permissions->addEntityPermission($chapter, ['view'], $roleA);
$this->assertVisibleToUser($page, $user);
}
public function test_89_fallback_override_deny_multi_role_inherit()
{
[$user, $roleA] = $this->users->newUserWithRole();
$roleB = $this->users->attachNewRole($user);
$page = $this->entities->page();
$chapter = $page->chapter;
$this->permissions->setFallbackPermissions($chapter, ['view']);
$this->permissions->addEntityPermission($chapter, [], $roleA);
$this->assertNotVisibleToUser($page, $user);
}
} }