Skip to content

Commit

Permalink
Merge branch '4.6' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
reithor committed Jul 15, 2024
2 parents ace51ec + bdab9ea commit 40698b3
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/lib/Repository/ContentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1423,7 +1423,7 @@ protected function internalUpdateContent(
)->id,
]
);
$existingRelations = $this->internalLoadRelations($versionInfo);
$existingRelations = $this->repository->sudo(fn (): array => $this->internalLoadRelations($versionInfo));

$this->repository->beginTransaction();
try {
Expand Down
158 changes: 158 additions & 0 deletions tests/integration/Core/Repository/ContentService/UpdateContentTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<?php

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

namespace Ibexa\Tests\Integration\Core\Repository\ContentService;

use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo;
use Ibexa\Contracts\Core\Repository\Values\Content\Section;
use Ibexa\Contracts\Core\Repository\Values\User\Limitation\SectionLimitation;
use Ibexa\Contracts\Core\Repository\Values\User\User;
use Ibexa\Tests\Integration\Core\RepositoryTestCase;

/**
* @covers \Ibexa\Contracts\Core\Repository\ContentService
*/
final class UpdateContentTest extends RepositoryTestCase
{
/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception
*/
public function testUpdateContentHavingPrivateRelation(): void
{
$sectionService = self::getSectionService();
$contentService = self::getContentService();
$permissionResolver = self::getPermissionResolver();

$this->addRelationFieldToFolderContentType();

$privateSection = $this->createPrivateSection();

$folderPrivate = $this->createFolder(['eng-GB' => 'Private Folder'], 2);
$sectionService->assignSection($folderPrivate->getContentInfo(), $privateSection);

// Create folder with relation to 'Private Folder'
$folder = $this->createFolderWithRelations([$folderPrivate->getId()]);

$userWithRoleLimitation = $this->createUserWithNoAccessToPrivateSection();

// Create & publish new $folder version as $editor
$permissionResolver->setCurrentUserReference($userWithRoleLimitation);
$folder = $this->publishVersionWithoutChanges($folder->getContentInfo());

// Read relations & check if count($relations) is unchanged
self::setAdministratorUser();
$relations = $contentService->loadRelations($folder->getVersionInfo());
if ($relations instanceof \Traversable) {
$relations = iterator_to_array($relations);
}
self::assertCount(1, $relations);
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception
*/
private function addRelationFieldToFolderContentType(): void
{
$contentTypeService = self::getContentTypeService();
$folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
$folderTypeDraft = $contentTypeService->createContentTypeDraft($folderType);

$relationsFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct(
'relations',
'ezobjectrelationlist'
);
$relationsFieldCreateStruct->names = ['eng-GB' => 'Relations'];
$contentTypeService->addFieldDefinition($folderTypeDraft, $relationsFieldCreateStruct);
$contentTypeService->publishContentTypeDraft($folderTypeDraft);
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
*/
private function createPrivateSection(): Section
{
$sectionService = self::getSectionService();

$sectionCreateStruct = $sectionService->newSectionCreateStruct();
$sectionCreateStruct->identifier = 'private';
$sectionCreateStruct->name = 'Private Section';

return $sectionService->createSection($sectionCreateStruct);
}

/**
* @param int[] $relationListTarget
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception
*/
private function createFolderWithRelations(array $relationListTarget): Content
{
$contentService = self::getContentService();

$folder = $this->createFolder(['eng-GB' => 'Folder with private relation'], 2);
$folderDraft = $contentService->createContentDraft($folder->getContentInfo());
$folderUpdateStruct = $contentService->newContentUpdateStruct();
$folderUpdateStruct->setField('relations', $relationListTarget);

$folder = $contentService->updateContent($folderDraft->getVersionInfo(), $folderUpdateStruct);

return $contentService->publishVersion($folder->getVersionInfo());
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\LimitationValidationException
*/
private function assignToUserRoleWithStandardSectionLimitation(User $user): void
{
$sectionService = self::getSectionService();
$roleService = self::getRoleService();

$roleCreateStruct = $roleService->newRoleCreateStruct('limited_access');
$roleCreateStruct->addPolicy($roleService->newPolicyCreateStruct('*', '*'));
$role = $roleService->createRole($roleCreateStruct);
$roleService->publishRoleDraft($role);

// limit access to standard section only on the role assignment level
$standardSection = $sectionService->loadSectionByIdentifier('standard');
$roleService->assignRoleToUser(
$role,
$user,
new SectionLimitation(['limitationValues' => [$standardSection->id]])
);
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception
*/
private function createUserWithNoAccessToPrivateSection(): User
{
$user = $this->createUser('test.editor', 'Editor', 'Test');
$this->assignToUserRoleWithStandardSectionLimitation($user);

return $user;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception
*/
private function publishVersionWithoutChanges(ContentInfo $contentInfo): Content
{
$contentService = self::getContentService();

$folderDraft = $contentService->createContentDraft($contentInfo);
$folderUpdateStruct = $contentService->newContentUpdateStruct();
$folder = $contentService->updateContent($folderDraft->getVersionInfo(), $folderUpdateStruct);

return $contentService->publishVersion($folder->getVersionInfo());
}
}
34 changes: 34 additions & 0 deletions tests/integration/Core/RepositoryTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
namespace Ibexa\Tests\Integration\Core;

use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use Ibexa\Contracts\Core\Repository\Values\User\User;
use Ibexa\Contracts\Core\Repository\Values\User\UserGroup;
use Ibexa\Contracts\Core\Test\IbexaKernelTestCase;
use InvalidArgumentException;

Expand All @@ -17,6 +19,7 @@ abstract class RepositoryTestCase extends IbexaKernelTestCase
public const CONTENT_TREE_ROOT_ID = 2;

private const CONTENT_TYPE_FOLDER_IDENTIFIER = 'folder';
private const MAIN_USER_GROUP_REMOTE_ID = 'f5c88a2209584891056f987fd965b0ba';

protected function setUp(): void
{
Expand All @@ -41,6 +44,37 @@ public function createFolder(array $names, int $parentLocationId = self::CONTENT
return $contentService->publishVersion($draft->getVersionInfo());
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
final protected function createUser(string $login, string $firstName, string $lastName, UserGroup $userGroup = null): User
{
$userService = self::getUserService();

if (null === $userGroup) {
$userGroup = $userService->loadUserGroupByRemoteId(self::MAIN_USER_GROUP_REMOTE_ID);
}

$userCreateStruct = $userService->newUserCreateStruct(
$login,
"$login@mail.invalid",
'secret',
'eng-US'
);
$userCreateStruct->enabled = true;

// Set some fields required by the user ContentType
$userCreateStruct->setField('first_name', $firstName);
$userCreateStruct->setField('last_name', $lastName);

// Create a new user instance.
return $userService->createUser($userCreateStruct, [$userGroup]);
}

/**
* @param array<string, string> $names
*
Expand Down
9 changes: 3 additions & 6 deletions tests/lib/Repository/Service/Mock/ContentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3331,7 +3331,7 @@ protected function assertForTestUpdateContentNonRedundantFieldSet(
->expects(self::once())
->method('getCurrentUserReference')
->willReturn(new UserReference(169));
$mockedService = $this->getPartlyMockedContentService(['internalLoadContentById', 'internalLoadRelations'], $permissionResolverMock);
$mockedService = $this->getPartlyMockedContentService(['internalLoadContentById'], $permissionResolverMock);
$permissionResolverMock = $this->getPermissionResolverMock();
/** @var \PHPUnit\Framework\MockObject\MockObject $contentHandlerMock */
$contentHandlerMock = $this->getPersistenceMock()->contentHandler();
Expand Down Expand Up @@ -3484,11 +3484,8 @@ static function (SPIValue $value) use ($emptyValue) {
)->will(self::returnValue([]));

$existingRelations = ['RELATIONS!!!'];
$mockedService
->method('internalLoadRelations')
->with($content->versionInfo)
->will(self::returnValue($existingRelations));
$relationProcessorMock->expects(self::any())
$repositoryMock->method('sudo')->willReturn($existingRelations);
$relationProcessorMock->expects($this->any())
->method('processFieldRelations')
->with(
self::isType('array'),
Expand Down

0 comments on commit 40698b3

Please sign in to comment.