Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EZP-32308: Fixed evaluating permissions on non prepared targets #3083

Merged
merged 5 commits into from
Feb 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace eZ\Publish\API\Repository\Tests\Limitation\PermissionResolver;

use eZ\Publish\API\Repository\Values\User\Limitation\LocationLimitation;
use eZ\Publish\SPI\Limitation\Target\Version;

class LocationLimitationIntegrationTest extends BaseLimitationIntegrationTest
{
private const LOCATION_ID = 2;

public function providerForCanUserEditOrPublishContent(): array
{
$limitationRoot = new LocationLimitation();
$limitationRoot->limitationValues = [self::LOCATION_ID];

return [
[[$limitationRoot], true],
];
}

/**
* @dataProvider providerForCanUserEditOrPublishContent
*
* @param array $limitations
* @param bool $expectedResult
*
* @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
public function testCanUserEditContent(array $limitations, bool $expectedResult): void
{
$repository = $this->getRepository();
$locationService = $repository->getLocationService();

$location = $locationService->loadLocation(2);

$this->loginAsEditorUserWithLimitations('content', 'edit', $limitations);

$this->assertCanUser(
$expectedResult,
'content',
'edit',
$limitations,
$location->contentInfo,
[$location]
);

$this->assertCanUser(
$expectedResult,
'content',
'edit',
$limitations,
$location->contentInfo,
[$location, new Version(['allLanguageCodesList' => 'eng-GB'])]
);
}
}
68 changes: 68 additions & 0 deletions eZ/Publish/API/Repository/Tests/PermissionResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
namespace eZ\Publish\API\Repository\Tests;

use eZ\Publish\SPI\Limitation\Target\Builder\VersionBuilder;
use function array_filter;
use eZ\Publish\API\Repository\Repository;
use eZ\Publish\API\Repository\Values\Content\ContentCreateStruct;
Expand Down Expand Up @@ -1238,6 +1239,73 @@ public function testLookupLimitationsWithRoleLimitationsHasNoAccess(): void
);
}

public function testLookupLimitationsWithMixedTargets(): void
{
$repository = $this->getRepository();
$userService = $repository->getUserService();
$permissionResolver = $repository->getPermissionResolver();
$roleService = $repository->getRoleService();
$locationService = $repository->getLocationService();

$location = $locationService->loadLocation(2);
$module = 'content';
$function = 'edit';

$role = $this->createRoleWithPolicies(
'role_' . __FUNCTION__,
[
[
'module' => $module,
'function' => $function,
'limitations' => [
new Limitation\LocationLimitation(['limitationValues' => [$location->id]]),
],
],
[
'module' => $module,
'function' => $function,
'limitations' => [
new Limitation\LanguageLimitation(['limitationValues' => ['eng-GB']]),
],
],
]
);
$user = $this->createUser('user', 'John', 'Doe', $userService->loadUserGroup(4));
$roleService->assignRoleToUser($role, $user);
$permissionResolver->setCurrentUserReference($user);

$expected = new LookupLimitationResult(
true,
[],
[
new LookupPolicyLimitations(
$role->getPolicies()[0],
[]
),
new LookupPolicyLimitations(
$role->getPolicies()[1],
[
new Limitation\LanguageLimitation(['limitationValues' => ['eng-GB']]),
]
),
]
);

self::assertEquals(
$expected,
$permissionResolver->lookupLimitations(
$module,
$function,
$location->contentInfo,
[
(new VersionBuilder())->translateToAnyLanguageOf(['eng-GB'])->build(),
$location,
],
[Limitation::LANGUAGE]
)
);
}

/**
* @param \eZ\Publish\API\Repository\Repository $repository
* @param string $contentTypeIdentifier
Expand Down
17 changes: 10 additions & 7 deletions eZ/Publish/Core/Limitation/LocationLimitationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,22 @@ public function evaluate(APILimitationValue $value, APIUserReference $currentUse
$targets = $this->persistence->locationHandler()->loadParentLocationsForDraftContent($object->id);
}
}
/** @var \eZ\Publish\API\Repository\Values\Content\Location[]|\eZ\Publish\SPI\Persistence\Content\Location[] $targets */
$targets = array_filter($targets, function ($target) {
return $target instanceof Location || $target instanceof SPILocation;
});

foreach ($targets as $target) {
if (!$target instanceof Location && !$target instanceof SPILocation) {
throw new InvalidArgumentException('$targets', 'Must contain objects of type: Location');
}
if (empty($targets)) {
throw new InvalidArgumentException('$targets', 'Must contain at least one Location object');
}

// Single match is sufficient
foreach ($targets as $target) {
if (in_array($target->id, $value->limitationValues)) {
return true;
return self::ACCESS_GRANTED;
}
}

return false;
return self::ACCESS_DENIED;
}

/**
Expand Down
14 changes: 12 additions & 2 deletions eZ/Publish/Core/Repository/Permission/PermissionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,12 @@ private function isGrantedByLimitation(
?array $targets
): bool {
$type = $this->limitationService->getLimitationType($limitation->getIdentifier());
$accessVote = $type->evaluate($limitation, $currentUserReference, $object, $targets);
$accessVote = $type->evaluate(
$limitation,
$currentUserReference,
$object,
$this->prepareTargetsForType($targets, $type)
);

return $accessVote === LimitationType::ACCESS_GRANTED;
}
Expand All @@ -366,7 +371,12 @@ private function isDeniedByRoleLimitation(
}

$type = $this->limitationService->getLimitationType($limitation->getIdentifier());
$accessVote = $type->evaluate($limitation, $currentUserReference, $object, $targets);
$accessVote = $type->evaluate(
$limitation,
$currentUserReference,
$object,
$this->prepareTargetsForType($targets, $type)
);

return $accessVote === LimitationType::ACCESS_DENIED;
}
Expand Down