Skip to content
Open
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
6 changes: 5 additions & 1 deletion src/lib/Limitation/OwnerLimitationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,12 @@ public function evaluate(APILimitationValue $value, APIUserReference $currentUse
);
}

$versionCreatorId = null;
if ($object instanceof Content) {
$versionCreatorId = $object->getVersionInfo()->creatorId;
$object = $object->getVersionInfo()->getContentInfo();
} elseif ($object instanceof VersionInfo) {
$versionCreatorId = $object->creatorId;
$object = $object->getContentInfo();
} elseif (!$object instanceof ContentInfo && !$object instanceof ContentCreateStruct) {
throw new InvalidArgumentException(
Expand All @@ -141,9 +144,10 @@ public function evaluate(APILimitationValue $value, APIUserReference $currentUse
* @var $object ContentInfo
*/
$isOwner = $object->ownerId === $userId;
$isVersionCreator = $versionCreatorId !== null && $versionCreatorId === $userId;
$isSelf = $object instanceof ContentInfo && $object->id === $userId;

return $isOwner || $isSelf;
return $isOwner || $isVersionCreator || $isSelf;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,107 @@
);
/* END: Use Case */
}

/**
* @covers \Ibexa\Core\Limitation\OwnerLimitationType::evaluate
*/
public function testOwnerLimitationAllowsVersionRemoveForOwnDraftOfContentOwnedByAnotherUser(): void
{
$repository = $this->getRepository();
$permissionResolver = $repository->getPermissionResolver();
$contentService = $repository->getContentService();

/* BEGIN: Use Case */
// Content is created (and owned) by the currently logged in admin user
$content = $this->createWikiPage();

$user = $this->createUserWithVersionRemoveOwnerLimitation();

$permissionResolver->setCurrentUserReference($user);

// $user creates their own draft of content that is still owned by the admin user
$draft = $contentService->createContentDraft($content->contentInfo);

// This must succeed, because $user is the creator of this particular version,
// even though they do not own the Content itself
$contentService->deleteVersion($draft->getVersionInfo());
/* END: Use Case */

$this->expectNotToPerformAssertions();
}

/**
* @covers \Ibexa\Core\Limitation\OwnerLimitationType::evaluate
*/
public function testOwnerLimitationForbidsVersionRemoveForDraftCreatedByAnotherUser(): void
{
$this->expectException(UnauthorizedException::class);

$repository = $this->getRepository();
$permissionResolver = $repository->getPermissionResolver();
$contentService = $repository->getContentService();

/* BEGIN: Use Case */
// Content and its draft are created (and owned) by the currently logged in admin user
$content = $this->createWikiPage();
$draft = $contentService->createContentDraft($content->contentInfo);

$user = $this->createUserWithVersionRemoveOwnerLimitation();

$permissionResolver->setCurrentUserReference($user);

// This call fails with an UnauthorizedException, because $user neither owns
// the Content nor created this particular draft/version
$contentService->deleteVersion($draft->getVersionInfo());
/* END: Use Case */
}

/**
* Creates a user assigned to the Editor role, restricted so that the
* content:versionremove policy only applies to versions the user created themselves.
*/
private function createUserWithVersionRemoveOwnerLimitation(): \Ibexa\Contracts\Core\Repository\Values\User\User
{
$repository = $this->getRepository();
$roleService = $repository->getRoleService();

$user = $this->createUserVersion1();

$role = $roleService->loadRoleByIdentifier('Editor');
$roleDraft = $roleService->createRoleDraft($role);
// Search for the new policy instance
$versionRemovePolicy = null;
/** @var \Ibexa\Contracts\Core\Repository\Values\User\PolicyDraft $policy */
foreach ($roleDraft->getPolicies() as $policy) {
if ('content' != $policy->module || 'versionremove' != $policy->function) {
continue;
}
$versionRemovePolicy = $policy;
break;
}

if (null === $versionRemovePolicy) {
throw new \ErrorException('No content:versionremove policy found.');

Check warning on line 225 in tests/integration/Core/Repository/Values/User/Limitation/OwnerLimitationTest.php

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define and throw a dedicated exception instead of using a generic one.

See more on https://sonarcloud.io/project/issues?id=ibexa_core&issues=AaB781LjsoCHNhz6CSPJ&open=AaB781LjsoCHNhz6CSPJ&pullRequest=813
}

// Only allow version removal for versions the current user created themselves
$policyUpdate = $roleService->newPolicyUpdateStruct();
$policyUpdate->addLimitation(
new OwnerLimitation(
['limitationValues' => [1]]
)
);
$roleService->updatePolicyByRoleDraft(
$roleDraft,
$versionRemovePolicy,
$policyUpdate
);
$roleService->publishRoleDraft($roleDraft);

$roleService->assignRoleToUser($role, $user);

return $user;
}
}

class_alias(OwnerLimitationTest::class, 'eZ\Publish\API\Repository\Tests\Values\User\Limitation\OwnerLimitationTest');
Loading