From ce7683e276b122d622afeeec8fc13d33e98dbd97 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Fri, 21 Jun 2024 11:37:02 +0200 Subject: [PATCH 01/10] IBX-8426: Fixed duplicate relations --- src/lib/Repository/ContentService.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/Repository/ContentService.php b/src/lib/Repository/ContentService.php index a2388e97da..66903e8f1b 100644 --- a/src/lib/Repository/ContentService.php +++ b/src/lib/Repository/ContentService.php @@ -1421,7 +1421,7 @@ protected function internalUpdateContent( )->id, ] ); - $existingRelations = $this->internalLoadRelations($versionInfo); + $existingRelations = $this->internalLoadRelations($versionInfo, false); $this->repository->beginTransaction(); try { @@ -2009,13 +2009,13 @@ public function loadRelations(APIVersionInfo $versionInfo): iterable } /** - * Loads all outgoing relations for the given version without checking the permissions. + * Loads all outgoing relations for the given version without checking the permissions on $versionInfo. * * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException * * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation[] */ - protected function internalLoadRelations(APIVersionInfo $versionInfo): array + protected function internalLoadRelations(APIVersionInfo $versionInfo, bool $checkDestinationPermission = true): array { $contentInfo = $versionInfo->getContentInfo(); $spiRelations = $this->persistenceHandler->contentHandler()->loadRelations( @@ -2027,7 +2027,7 @@ protected function internalLoadRelations(APIVersionInfo $versionInfo): array $relations = []; foreach ($spiRelations as $spiRelation) { $destinationContentInfo = $this->internalLoadContentInfoById($spiRelation->destinationContentId); - if (!$this->permissionResolver->canUser('content', 'read', $destinationContentInfo)) { + if ($checkDestinationPermission && !$this->permissionResolver->canUser('content', 'read', $destinationContentInfo)) { continue; } From 5227bc9e73bb89ee8c7e38c26a209f932fb6d9b8 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Sat, 29 Jun 2024 10:27:53 +0200 Subject: [PATCH 02/10] Integration test --- .../ContentService/UpdateContentTest.php | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/integration/Core/Repository/ContentService/UpdateContentTest.php diff --git a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php new file mode 100644 index 0000000000..80d9608aa4 --- /dev/null +++ b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php @@ -0,0 +1,98 @@ +generateId('user', 14); + $repository = $this->getRepository(); + $contentTypeService = $repository->getContentTypeService(); + $sectionService = $repository->getSectionService(); + $contentService = $repository->getContentService(); + $userService = $repository->getUserService(); + $permissionResolver = $repository->getPermissionResolver(); + + /* BEGIN: Use Case */ + // 1. Add relation field to 'folder' ContentType + $folderType = $contentTypeService->loadContentTypeByIdentifier('folder'); + $folderTypeDraft = $contentTypeService->createContentTypeDraft($folderType); + + $titleFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('relations', 'ezobjectrelationlist'); + $titleFieldCreateStruct->names = ['eng-GB' => 'Relations']; + $titleFieldCreateStruct->descriptions = ['eng-GB' => 'Relations']; + $titleFieldCreateStruct->fieldGroup = 'content'; + $titleFieldCreateStruct->position = 10; + $titleFieldCreateStruct->isTranslatable = false; + $titleFieldCreateStruct->isRequired = false; + $titleFieldCreateStruct->isSearchable = false; + $contentTypeService->addFieldDefinition($folderTypeDraft, $titleFieldCreateStruct); + $contentTypeService->publishContentTypeDraft($folderTypeDraft); + + // 2. Add Section 'private' + $sectionCreateStruct = $sectionService->newSectionCreateStruct(); + $sectionCreateStruct->identifier = 'private'; + $sectionCreateStruct->name = 'Private Section'; + $privateSection = $sectionService->createSection($sectionCreateStruct); + + // 3. Add 'Private Folder' + $folderPrivate = $this->createFolder(['eng-GB' => 'Private Folder'], 2); + $sectionService->assignSection($folderPrivate->getContentInfo(), $privateSection); + + // 4. Add folder with relation to 'Private Folder' + $folder = $this->createFolder(['eng-GB' => 'Folder with private relation'], 2); + $folderDraft = $contentService->createContentDraft($folder->getContentInfo()); + $folderUpdateStruct = $contentService->newContentUpdateStruct(); + $relationListTarget = [$folderPrivate->id]; + $folderUpdateStruct->setField('relations', $relationListTarget); + $folder = $contentService->updateContent($folderDraft->getVersionInfo(), $folderUpdateStruct); + $contentService->publishVersion($folder->getVersionInfo()); + + // 5. Create User that has no access to content in $privateSection + $editorRole = $repository->getRoleService()->loadRole(3); + foreach ($repository->getRoleService()->getRoleAssignments($editorRole) as $role) { + if ($role->getRoleLimitation()->limitationValues == ['/1/2/']) { + $repository->getRoleService()->removeRoleAssignment($role); + } + } + $editorUserGroup = $userService->loadUserGroup(13); + $repository->getRoleService()->assignRoleToUserGroup( + $editorRole, + $editorUserGroup, + new SectionLimitation(['limitationValues' => [1]]) + ); + $editor = $this->createUser('test.editor', 'Editor', 'Test'); + + // 6. Create & publish new $folder version as $editor + $permissionResolver->setCurrentUserReference($editor); + $folderDraft = $contentService->createContentDraft($folder->getContentInfo()); + $folderUpdateStruct = $contentService->newContentUpdateStruct(); + $folder = $contentService->updateContent($folderDraft->getVersionInfo(), $folderUpdateStruct); + $contentService->publishVersion($folder->getVersionInfo()); + + // 7. Read relations & check if count($relations) is unchanged + $permissionResolver->setCurrentUserReference($userService->loadUser($administratorUserId)); + $relations = $contentService->loadRelations($folder->getVersionInfo()); + self::assertEquals(1, count($relations)); + } +} From 569435834851eb14e8cf3f5249cdb17c78fff675 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Sat, 29 Jun 2024 10:46:40 +0200 Subject: [PATCH 03/10] fix errors from phpstan --- .../Core/Repository/ContentService/UpdateContentTest.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php index 80d9608aa4..ddb72de375 100644 --- a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php +++ b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php @@ -70,12 +70,13 @@ public function testUpdateContentHavingPrivateRelation(): void // 5. Create User that has no access to content in $privateSection $editorRole = $repository->getRoleService()->loadRole(3); + // remove existing role assignments foreach ($repository->getRoleService()->getRoleAssignments($editorRole) as $role) { - if ($role->getRoleLimitation()->limitationValues == ['/1/2/']) { - $repository->getRoleService()->removeRoleAssignment($role); - } + $repository->getRoleService()->removeRoleAssignment($role); } + $editorUserGroup = $userService->loadUserGroup(13); + // grant access to standard section $repository->getRoleService()->assignRoleToUserGroup( $editorRole, $editorUserGroup, @@ -93,6 +94,6 @@ public function testUpdateContentHavingPrivateRelation(): void // 7. Read relations & check if count($relations) is unchanged $permissionResolver->setCurrentUserReference($userService->loadUser($administratorUserId)); $relations = $contentService->loadRelations($folder->getVersionInfo()); - self::assertEquals(1, count($relations)); + self::assertEquals(1, count((array)$relations)); } } From f6bf7a863c43e37dbc14216fd12f3b17fdaf3bed Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Sat, 29 Jun 2024 10:54:49 +0200 Subject: [PATCH 04/10] minor change --- .../ContentService/UpdateContentTest.php | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php index ddb72de375..b865a3e09d 100644 --- a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php +++ b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php @@ -31,22 +31,16 @@ public function testUpdateContentHavingPrivateRelation(): void $sectionService = $repository->getSectionService(); $contentService = $repository->getContentService(); $userService = $repository->getUserService(); + $roleService = $repository->getRoleService(); $permissionResolver = $repository->getPermissionResolver(); - /* BEGIN: Use Case */ // 1. Add relation field to 'folder' ContentType $folderType = $contentTypeService->loadContentTypeByIdentifier('folder'); $folderTypeDraft = $contentTypeService->createContentTypeDraft($folderType); - $titleFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('relations', 'ezobjectrelationlist'); - $titleFieldCreateStruct->names = ['eng-GB' => 'Relations']; - $titleFieldCreateStruct->descriptions = ['eng-GB' => 'Relations']; - $titleFieldCreateStruct->fieldGroup = 'content'; - $titleFieldCreateStruct->position = 10; - $titleFieldCreateStruct->isTranslatable = false; - $titleFieldCreateStruct->isRequired = false; - $titleFieldCreateStruct->isSearchable = false; - $contentTypeService->addFieldDefinition($folderTypeDraft, $titleFieldCreateStruct); + $relationsFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('relations', 'ezobjectrelationlist'); + $relationsFieldCreateStruct->names = ['eng-GB' => 'Relations']; + $contentTypeService->addFieldDefinition($folderTypeDraft, $relationsFieldCreateStruct); $contentTypeService->publishContentTypeDraft($folderTypeDraft); // 2. Add Section 'private' @@ -69,15 +63,15 @@ public function testUpdateContentHavingPrivateRelation(): void $contentService->publishVersion($folder->getVersionInfo()); // 5. Create User that has no access to content in $privateSection - $editorRole = $repository->getRoleService()->loadRole(3); + $editorRole = $roleService->loadRole(3); // remove existing role assignments - foreach ($repository->getRoleService()->getRoleAssignments($editorRole) as $role) { - $repository->getRoleService()->removeRoleAssignment($role); + foreach ($roleService->getRoleAssignments($editorRole) as $role) { + $roleService->removeRoleAssignment($role); } $editorUserGroup = $userService->loadUserGroup(13); // grant access to standard section - $repository->getRoleService()->assignRoleToUserGroup( + $roleService->assignRoleToUserGroup( $editorRole, $editorUserGroup, new SectionLimitation(['limitationValues' => [1]]) From 993cc19be8bf3f9731a0d00a2293b0199ca3ff03 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter <34274688+reithor@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:36:28 +0200 Subject: [PATCH 05/10] Apply suggestions from code review Co-authored-by: Andrew Longosz --- src/lib/Repository/ContentService.php | 2 +- .../ContentService/UpdateContentTest.php | 160 ++++++++++++------ 2 files changed, 112 insertions(+), 50 deletions(-) diff --git a/src/lib/Repository/ContentService.php b/src/lib/Repository/ContentService.php index 66903e8f1b..34156a3f7c 100644 --- a/src/lib/Repository/ContentService.php +++ b/src/lib/Repository/ContentService.php @@ -1421,7 +1421,7 @@ protected function internalUpdateContent( )->id, ] ); - $existingRelations = $this->internalLoadRelations($versionInfo, false); + $existingRelations = $this->repository->sudo(fn (): array => $this->internalLoadRelations($versionInfo)); $this->repository->beginTransaction(); try { diff --git a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php index b865a3e09d..9b49f23d7f 100644 --- a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php +++ b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php @@ -8,86 +8,148 @@ 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\Tests\Integration\Core\Repository\BaseTest; +use Ibexa\Contracts\Core\Repository\Values\User\User; +use Ibexa\Tests\Integration\Core\RepositoryTestCase; /** * @covers \Ibexa\Contracts\Core\Repository\ContentService */ -final class UpdateContentTest extends BaseTest +final class UpdateContentTest extends RepositoryTestCase { /** - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentTypeFieldDefinitionValidationException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception */ public function testUpdateContentHavingPrivateRelation(): void { - $administratorUserId = $this->generateId('user', 14); - $repository = $this->getRepository(); - $contentTypeService = $repository->getContentTypeService(); - $sectionService = $repository->getSectionService(); - $contentService = $repository->getContentService(); - $userService = $repository->getUserService(); - $roleService = $repository->getRoleService(); - $permissionResolver = $repository->getPermissionResolver(); - - // 1. Add relation field to 'folder' ContentType + $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()); + self::assertCount(1, (array)$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 = $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(); - // 2. Add Section 'private' $sectionCreateStruct = $sectionService->newSectionCreateStruct(); $sectionCreateStruct->identifier = 'private'; $sectionCreateStruct->name = 'Private Section'; - $privateSection = $sectionService->createSection($sectionCreateStruct); - // 3. Add 'Private Folder' - $folderPrivate = $this->createFolder(['eng-GB' => 'Private Folder'], 2); - $sectionService->assignSection($folderPrivate->getContentInfo(), $privateSection); + return $sectionService->createSection($sectionCreateStruct); + } + + /** + * @param int[] $relationListTarget + * + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception + */ + private function createFolderWithRelations(array $relationListTarget): Content + { + $contentService = self::getContentService(); - // 4. Add folder with relation to 'Private Folder' $folder = $this->createFolder(['eng-GB' => 'Folder with private relation'], 2); $folderDraft = $contentService->createContentDraft($folder->getContentInfo()); $folderUpdateStruct = $contentService->newContentUpdateStruct(); - $relationListTarget = [$folderPrivate->id]; $folderUpdateStruct->setField('relations', $relationListTarget); + $folder = $contentService->updateContent($folderDraft->getVersionInfo(), $folderUpdateStruct); - $contentService->publishVersion($folder->getVersionInfo()); - - // 5. Create User that has no access to content in $privateSection - $editorRole = $roleService->loadRole(3); - // remove existing role assignments - foreach ($roleService->getRoleAssignments($editorRole) as $role) { - $roleService->removeRoleAssignment($role); - } - - $editorUserGroup = $userService->loadUserGroup(13); - // grant access to standard section - $roleService->assignRoleToUserGroup( - $editorRole, - $editorUserGroup, - new SectionLimitation(['limitationValues' => [1]]) + + 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]]) ); - $editor = $this->createUser('test.editor', 'Editor', 'Test'); + } - // 6. Create & publish new $folder version as $editor - $permissionResolver->setCurrentUserReference($editor); - $folderDraft = $contentService->createContentDraft($folder->getContentInfo()); + /** + * @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); - $contentService->publishVersion($folder->getVersionInfo()); - // 7. Read relations & check if count($relations) is unchanged - $permissionResolver->setCurrentUserReference($userService->loadUser($administratorUserId)); - $relations = $contentService->loadRelations($folder->getVersionInfo()); - self::assertEquals(1, count((array)$relations)); + return $contentService->publishVersion($folder->getVersionInfo()); } } From 7737be37b83d282e936840fb8d83e8c4fce5aaa2 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Wed, 3 Jul 2024 12:42:44 +0200 Subject: [PATCH 06/10] added createUser to RepositoryTestCase --- tests/integration/Core/RepositoryTestCase.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/integration/Core/RepositoryTestCase.php b/tests/integration/Core/RepositoryTestCase.php index 6a4955b112..4eaa7a4bda 100644 --- a/tests/integration/Core/RepositoryTestCase.php +++ b/tests/integration/Core/RepositoryTestCase.php @@ -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; @@ -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 { @@ -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 + */ + 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 $names * From 1ec290dc1af7cf0a8bbd2163aa8b8b3cf9418bd5 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Wed, 3 Jul 2024 13:22:43 +0200 Subject: [PATCH 07/10] fixed unit test: ContentTest --- tests/lib/Repository/Service/Mock/ContentTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/lib/Repository/Service/Mock/ContentTest.php b/tests/lib/Repository/Service/Mock/ContentTest.php index 5f10cdb39d..b6d49d0d9e 100644 --- a/tests/lib/Repository/Service/Mock/ContentTest.php +++ b/tests/lib/Repository/Service/Mock/ContentTest.php @@ -3317,7 +3317,7 @@ protected function assertForTestUpdateContentNonRedundantFieldSet( ->expects($this->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(); @@ -3470,10 +3470,7 @@ static function (SPIValue $value) use ($emptyValue) { )->will($this->returnValue([])); $existingRelations = ['RELATIONS!!!']; - $mockedService - ->method('internalLoadRelations') - ->with($content->versionInfo) - ->will($this->returnValue($existingRelations)); + $repositoryMock->method('sudo')->willReturn($existingRelations); $relationProcessorMock->expects($this->any()) ->method('processFieldRelations') ->with( From 0f8fe40524bbfcea8f56f11dc3f4f049e4041f03 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Wed, 3 Jul 2024 14:01:28 +0200 Subject: [PATCH 08/10] undo changes in internalLoadRelations --- src/lib/Repository/ContentService.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/Repository/ContentService.php b/src/lib/Repository/ContentService.php index 34156a3f7c..4aee3f990a 100644 --- a/src/lib/Repository/ContentService.php +++ b/src/lib/Repository/ContentService.php @@ -2009,13 +2009,13 @@ public function loadRelations(APIVersionInfo $versionInfo): iterable } /** - * Loads all outgoing relations for the given version without checking the permissions on $versionInfo. + * Loads all outgoing relations for the given version without checking the permissions. * * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException * * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation[] */ - protected function internalLoadRelations(APIVersionInfo $versionInfo, bool $checkDestinationPermission = true): array + protected function internalLoadRelations(APIVersionInfo $versionInfo): array { $contentInfo = $versionInfo->getContentInfo(); $spiRelations = $this->persistenceHandler->contentHandler()->loadRelations( @@ -2027,7 +2027,7 @@ protected function internalLoadRelations(APIVersionInfo $versionInfo, bool $chec $relations = []; foreach ($spiRelations as $spiRelation) { $destinationContentInfo = $this->internalLoadContentInfoById($spiRelation->destinationContentId); - if ($checkDestinationPermission && !$this->permissionResolver->canUser('content', 'read', $destinationContentInfo)) { + if (!$this->permissionResolver->canUser('content', 'read', $destinationContentInfo)) { continue; } From 960a6714735a29de7cd4cf2ad4361aaba1fe0859 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter <34274688+reithor@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:43:47 +0200 Subject: [PATCH 09/10] Update tests/integration/Core/RepositoryTestCase.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Paweł Niedzielski --- tests/integration/Core/RepositoryTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/Core/RepositoryTestCase.php b/tests/integration/Core/RepositoryTestCase.php index 4eaa7a4bda..97de4dc0d1 100644 --- a/tests/integration/Core/RepositoryTestCase.php +++ b/tests/integration/Core/RepositoryTestCase.php @@ -51,7 +51,7 @@ public function createFolder(array $names, int $parentLocationId = self::CONTENT * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException */ - protected function createUser(string $login, string $firstName, string $lastName, UserGroup $userGroup = null): User + final protected function createUser(string $login, string $firstName, string $lastName, UserGroup $userGroup = null): User { $userService = self::getUserService(); From 5cf57342d684c7d9fb93299ed03ea78a2298c4d4 Mon Sep 17 00:00:00 2001 From: Thorsten Reiter Date: Wed, 3 Jul 2024 17:09:54 +0200 Subject: [PATCH 10/10] apply suggestion from code review --- .../Core/Repository/ContentService/UpdateContentTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php index 9b49f23d7f..0dd3f900f6 100644 --- a/tests/integration/Core/Repository/ContentService/UpdateContentTest.php +++ b/tests/integration/Core/Repository/ContentService/UpdateContentTest.php @@ -48,7 +48,10 @@ public function testUpdateContentHavingPrivateRelation(): void // Read relations & check if count($relations) is unchanged self::setAdministratorUser(); $relations = $contentService->loadRelations($folder->getVersionInfo()); - self::assertCount(1, (array)$relations); + if ($relations instanceof \Traversable) { + $relations = iterator_to_array($relations); + } + self::assertCount(1, $relations); } /**