diff --git a/src/bundle/Controller/SectionController.php b/src/bundle/Controller/SectionController.php index d10824b510..01274f50b6 100644 --- a/src/bundle/Controller/SectionController.php +++ b/src/bundle/Controller/SectionController.php @@ -15,9 +15,11 @@ use eZ\Publish\API\Repository\Values\Content\Query; use eZ\Publish\API\Repository\Values\Content\Query\SortClause; use eZ\Publish\API\Repository\Values\Content\Section; +use eZ\Publish\API\Repository\Values\User\Limitation\NewSectionLimitation; use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute; use eZ\Publish\Core\Pagination\Pagerfanta\ContentSearchAdapter; use eZ\Publish\API\Repository\SearchService; +use eZ\Publish\API\Repository\PermissionResolver; use EzSystems\EzPlatformAdminUi\Form\Data\Section\SectionContentAssignData; use EzSystems\EzPlatformAdminUi\Form\Data\Section\SectionCreateData; use EzSystems\EzPlatformAdminUi\Form\Data\Section\SectionDeleteData; @@ -29,6 +31,7 @@ use EzSystems\EzPlatformAdminUi\Form\SubmitHandler; use EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface; use EzSystems\EzPlatformAdminUi\UI\Service\PathService; +use EzSystems\EzPlatformAdminUi\Util\PermissionUtil; use EzSystems\EzPlatformAdminUiBundle\View\EzPagerfantaView; use EzSystems\EzPlatformAdminUiBundle\View\Template\EzPagerfantaTemplate; use Pagerfanta\Adapter\ArrayAdapter; @@ -74,6 +77,12 @@ class SectionController extends Controller /** @var \EzSystems\EzPlatformAdminUi\UI\Service\PathService */ private $pathService; + /** @var \eZ\Publish\API\Repository\PermissionResolver */ + private $permissionResolver; + + /** @var \EzSystems\EzPlatformAdminUi\Util\PermissionUtil */ + private $permissionUtil; + /** @var int */ private $defaultPaginationLimit; @@ -89,6 +98,8 @@ class SectionController extends Controller * @param \eZ\Publish\API\Repository\ContentTypeService $contentTypeService * @param \eZ\Publish\API\Repository\LocationService $locationService * @param \EzSystems\EzPlatformAdminUi\UI\Service\PathService $pathService + * @param \eZ\Publish\API\Repository\PermissionResolver $permissionResolver + * @param \EzSystems\EzPlatformAdminUi\Util\PermissionUtil $permissionUtil * @param int $defaultPaginationLimit */ public function __construct( @@ -103,6 +114,8 @@ public function __construct( ContentTypeService $contentTypeService, LocationService $locationService, PathService $pathService, + PermissionResolver $permissionResolver, + PermissionUtil $permissionUtil, int $defaultPaginationLimit ) { $this->notificationHandler = $notificationHandler; @@ -117,6 +130,8 @@ public function __construct( $this->locationService = $locationService; $this->pathService = $pathService; $this->defaultPaginationLimit = $defaultPaginationLimit; + $this->permissionResolver = $permissionResolver; + $this->permissionUtil = $permissionUtil; } public function performAccessCheck(): void @@ -130,6 +145,7 @@ public function performAccessCheck(): void * * @return \Symfony\Component\HttpFoundation\Response * + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException */ public function listAction(Request $request): Response @@ -205,6 +221,7 @@ public function viewAction(Section $section): Response * * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ public function viewSectionContentAction(Section $section, int $page = 1, int $limit = 10): Response { @@ -490,9 +507,25 @@ private function getSectionsNumbers(array $sections): array * @param \eZ\Publish\API\Repository\Values\Content\Section $section * * @return bool + * + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ private function canUserAssignSectionToAnyContent(Section $section): bool { - return $this->isGranted(new Attribute('section', 'assign', ['valueObject' => new ContentInfo(), 'targets' => $section])); + $hasAccess = $this->permissionResolver->hasAccess('section', 'assign'); + + if (is_bool($hasAccess)) { + return $hasAccess; + } + + foreach ($this->permissionUtil->flattenArrayOfLimitations($hasAccess) as $limitation) { + if ($limitation instanceof NewSectionLimitation) { + // If one of user limitation is NewSectionLimitation we check if user can assign Content to $section + return in_array($section->id, $limitation->limitationValues); + } + } + + // If a user has other limitation than NewSectionLimitation, then a decision will be taken later, based on selected Content. + return true; } } diff --git a/src/bundle/Resources/views/admin/section/list.html.twig b/src/bundle/Resources/views/admin/section/list.html.twig index a7c6a6e4e4..3da8210811 100644 --- a/src/bundle/Resources/views/admin/section/list.html.twig +++ b/src/bundle/Resources/views/admin/section/list.html.twig @@ -93,7 +93,7 @@ href="#" data-section-id="{{ section.id }}" data-form-action="{{ path("ezplatform.section.assign_content", {"sectionId": section.id}) }}" - data-udw-config="{{ ez_udw_config('multiple', {}) }}" + data-udw-config="{{ ez_udw_config('multiple', {'type': 'section_assign'}) }}" class="btn btn-icon mx-3"> diff --git a/src/lib/UniversalDiscovery/Event/Subscriber/SectionAssign.php b/src/lib/UniversalDiscovery/Event/Subscriber/SectionAssign.php new file mode 100644 index 0000000000..b89646573b --- /dev/null +++ b/src/lib/UniversalDiscovery/Event/Subscriber/SectionAssign.php @@ -0,0 +1,110 @@ +permissionUtil = $permissionUtil; + $this->contentTypeService = $contentTypeService; + $hasAccess = $permissionResolver->hasAccess('section', 'assign'); + $this->allowedContentTypesIdentifiers = is_array($hasAccess) ? $this->checkAllowedContentTypes($hasAccess) : []; + } + + /** + * @return array + */ + public static function getSubscribedEvents(): array + { + return [ + ConfigResolveEvent::NAME => ['onUdwConfigResolve'], + ]; + } + + /** + * @param \EzSystems\EzPlatformAdminUi\UniversalDiscovery\Event\ConfigResolveEvent $event + */ + public function onUdwConfigResolve(ConfigResolveEvent $event): void + { + $configName = $event->getConfigName(); + if ('multiple' !== $configName) { + return; + } + + $context = $event->getContext(); + if ( + !isset($context['type']) + || 'section_assign' !== $context['type'] + ) { + return; + } + + if (!empty($this->allowedContentTypesIdentifiers)) { + $config = $event->getConfig(); + $config['content_on_the_fly']['allowed_content_types'] = $this->allowedContentTypesIdentifiers; + $event->setConfig($config); + } + } + + /** + * @param array $hasAccess + * + * @return array + */ + private function checkAllowedContentTypes(array $hasAccess): array + { + $allowedContentTypesIdentifiers = []; + $allowedContentTypesIds = []; + + foreach ($this->permissionUtil->flattenArrayOfLimitations($hasAccess) as $limitation) { + if ($limitation instanceof ContentTypeLimitation) { + $allowedContentTypesIds[] = $limitation->limitationValues; + } + } + + $allowedContentTypesIds = array_unique(array_merge(...$allowedContentTypesIds)); + foreach ($allowedContentTypesIds as $allowedContentTypeId) { + try { + $identifier = $this->contentTypeService->loadContentType($allowedContentTypeId)->identifier; + $allowedContentTypesIdentifiers[] = $identifier; + } catch (NotFoundException $e) { + } + } + + return $allowedContentTypesIdentifiers; + } +} diff --git a/src/lib/Util/PermissionUtil.php b/src/lib/Util/PermissionUtil.php new file mode 100644 index 0000000000..3bbe8b036b --- /dev/null +++ b/src/lib/Util/PermissionUtil.php @@ -0,0 +1,38 @@ +getLimitations(); + if (!empty($policyLimitations)) { + foreach ($policyLimitations as $policyLimitation) { + $limitations[] = $policyLimitation; + } + } + } + } + + return $limitations; + } +}