Details
-
Bug
-
Resolution: Fixed
-
Medium
-
None
-
None
-
Yes
Description
Calling $locationService->loadLocationChildren($location) when you have content/read policy with stage limitation on multiple stages returns wrong result
- Create an objectstategroup "Group1" with state "State1"
- Create a second objectstategroup "Group2" with state "State2"
- Limit permission for anonymous to only read contents from "Group1:State1 and Group2:State2"
- Create a Content Object Parent1 with State1 and State2 assigned
- Create children Child1 and Child2, below Parent1, also with State1 and State2 assigned
- Try to fetch the object Parent1 with $locationService->loadLocationChildren($location). (see code below )
- See no children are listed
<?php /** * @copyright Copyright (C) Ibexa AS. All rights reserved. * @license For full copyright and license information view LICENSE file distributed with this source code. */ namespace App\Command; use eZ\Publish\API\Repository\LocationService; use eZ\Publish\API\Repository\PermissionResolver; use eZ\Publish\API\Repository\UserService; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class loadLocationCommand extends Command { private LocationService$locationService; private UserService $userService; private PermissionResolver $permissionResolver; public function __construct( PermissionResolver $permissionResolver, LocationService $locationService, UserService $userService ) { $this->locationService = $locationService; $this->userService = $userService; parent::__construct(); $this->permissionResolver = $permissionResolver; } protected function configure() { $this->setName('app:load-location') ->setDescription('Load a given location') ->addArgument( 'locationId', InputArgument::REQUIRED, 'Parent location ID' ) ->addOption( 'user', 'u', InputOption::VALUE_REQUIRED, 'Ibexa DXP username', 'admin') ->setHelp( <<<EOT The command <info>%command.name%</info> allows you to load a given location EOT ); } protected function execute(InputInterface $input, OutputInterface $output) { $this->permissionResolver->setCurrentUserReference( $this->userService->loadUserByLogin($input->getOption('user')) ); $locationId = $input->getArgument('locationId'); $location = $this->locationService->loadLocation($locationId); $output->writeln('Found content: ' . $location->getContent()->getName() ); $children = $this->locationService->loadLocationChildren($location); /** @var \eZ\Publish\API\Repository\Values\Content\Location $child */ foreach ($children as $child) { $output->writeln(' - ' . $child->getContent()->getName() ); } return Command::SUCCESS; } }
Run the command as Admin (works):
./bin/console app:load-location 36742 --user admin -v Found content: loadLocationChildren() not working with multiple objectstate permissions - Child1 - Child2
Run the command as user with limitation:
./bin/console app:load-location 36742 --user ObjectState1 -v Found content: loadLocationChildren() not working with multiple objectstate permissions
See error in in generated SQL when executing the command:
tail -f var/log/dev.log |grep ezcobj_state [2023-11-23T14:34:02.713003+00:00] doctrine.DEBUG: SELECT DISTINCT COUNT(DISTINCT location.node_id) FROM ezcontentobject_tree location INNER JOIN ezcontentobject content ON content.id = location.contentobject_id INNER JOIN ezcontentobject_version version ON (content.id = version.contentobject_id) AND (content.current_version = version.version) AND (version.status = :dcValue1) INNER JOIN ezcobj_state_link object_state_link ON content.id = object_state_link.contentobject_id INNER JOIN ezcontent_language language ON language.id & version.language_mask = language.id WHERE (location.parent_node_id IN (:dcValue2)) AND ((language.locale IN (:dcValue3)) OR (version.language_mask & 1 = 1)) AND ((content.section_id IN (:dcValue4)) AND ((object_state_link.contentobject_state_id IN (:dcValue5)) AND (object_state_link.contentobject_state_id IN (:dcValue6)))) {"dcValue1":1,"dcValue2":[36742],"dcValue3":["eng-GB"],"dcValue4":[6,3,1],"dcValue5":[4],"dcValue6":[5]} []
The "ezcobj_state_link" table is only joined once but limited to two different IDs at the same time.
Designs
Attachments
Issue Links
- relates to
-
IBX-8019 Performance regression due to IBX-7172
- InputQ