diff --git a/Classes/Application/ReloadNodes/ReloadNodesQueryHandler.php b/Classes/Application/ReloadNodes/ReloadNodesQueryHandler.php index 2b05c6903d..b43606c7f6 100644 --- a/Classes/Application/ReloadNodes/ReloadNodesQueryHandler.php +++ b/Classes/Application/ReloadNodes/ReloadNodesQueryHandler.php @@ -18,7 +18,6 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindChildNodesFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; @@ -51,10 +50,7 @@ public function handle(ReloadNodesQuery $query, ActionRequest $actionRequest): R { $contentRepository = $this->contentRepositoryRegistry ->get($query->contentRepositoryId); - $subgraph = $contentRepository->getContentGraph($query->workspaceName)->getSubgraph( - $query->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() - ); + $subgraph = $contentRepository->getContentSubgraph($query->workspaceName, $query->dimensionSpacePoint); $baseNodeTypeConstraints = NodeTypeCriteria::fromFilterString($this->baseNodeType); $documentNode = $subgraph->findNodeById($query->documentId); diff --git a/Classes/Application/SyncWorkspace/ConflictsBuilder.php b/Classes/Application/SyncWorkspace/ConflictsBuilder.php index 138ed415fc..33c1ad5a2b 100644 --- a/Classes/Application/SyncWorkspace/ConflictsBuilder.php +++ b/Classes/Application/SyncWorkspace/ConflictsBuilder.php @@ -37,7 +37,6 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateCurrentlyDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; @@ -223,9 +222,9 @@ private function acquireSubgraphFromCommand( return null; } - return $contentGraph->getSubgraph( + return $this->contentRepository->getContentSubgraph( + $this->workspaceName, $dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() ); } diff --git a/Classes/ContentRepository/Service/NeosUiNodeService.php b/Classes/ContentRepository/Service/NeosUiNodeService.php index 07d0b8ee35..63fdad72e5 100644 --- a/Classes/ContentRepository/Service/NeosUiNodeService.php +++ b/Classes/ContentRepository/Service/NeosUiNodeService.php @@ -13,7 +13,6 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; @@ -32,10 +31,7 @@ public function findNodeBySerializedNodeAddress(string $serializedNodeAddress): $nodeAddress = NodeAddress::fromJsonString($serializedNodeAddress); $contentRepository = $this->contentRepositoryRegistry->get($nodeAddress->contentRepositoryId); - $subgraph = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph( - $nodeAddress->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() - ); + $subgraph = $contentRepository->getContentSubgraph($nodeAddress->workspaceName, $nodeAddress->dimensionSpacePoint); return $subgraph->findNodeById($nodeAddress->aggregateId); } } diff --git a/Classes/ContentRepository/Service/WorkspaceService.php b/Classes/ContentRepository/Service/WorkspaceService.php index d1b9834a3c..94a57d78f5 100644 --- a/Classes/ContentRepository/Service/WorkspaceService.php +++ b/Classes/ContentRepository/Service/WorkspaceService.php @@ -14,7 +14,6 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; @@ -92,9 +91,9 @@ public function getPublishableNodeInfo(WorkspaceName $workspaceName, ContentRepo } foreach ($originDimensionSpacePoints as $originDimensionSpacePoint) { - $subgraph = $contentGraph->getSubgraph( + $subgraph = $contentRepository->getContentSubgraph( + $workspaceName, $originDimensionSpacePoint->toDimensionSpacePoint(), - VisibilityConstraints::withoutRestrictions() ); $node = $subgraph->findNodeById($change->nodeAggregateId); if ($node instanceof Node) { diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php index 930035d88f..426c6c1be6 100644 --- a/Classes/Controller/BackendController.php +++ b/Classes/Controller/BackendController.php @@ -13,8 +13,6 @@ */ use Neos\ContentRepository\Core\Feature\SubtreeTagging\Dto\SubtreeTag; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; -use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; @@ -151,9 +149,9 @@ public function indexAction(string $node = null) $rootDimensionSpacePoints = $contentRepository->getVariationGraph()->getRootGeneralizations(); $arbitraryRootDimensionSpacePoint = array_shift($rootDimensionSpacePoints); - $subgraph = $contentGraph->getSubgraph( - $nodeAddress ? $nodeAddress->dimensionSpacePoint : $arbitraryRootDimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() + $subgraph = $contentRepository->getContentSubgraph( + $workspace->workspaceName, + $nodeAddress->dimensionSpacePoint ?? $arbitraryRootDimensionSpacePoint, ); // we assume that the ROOT node is always stored in the CR as "physical" node; so it is safe @@ -222,9 +220,9 @@ public function redirectToAction(string $node): void $contentRepository = $this->contentRepositoryRegistry->get($nodeAddress->contentRepositoryId); - $nodeInstance = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph( - $nodeAddress->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() + $nodeInstance = $contentRepository->getContentSubgraph( + $nodeAddress->workspaceName, + $nodeAddress->dimensionSpacePoint )->findNodeById($nodeAddress->aggregateId); $workspace = $contentRepository->findWorkspaceByName($nodeAddress->workspaceName); diff --git a/Classes/Controller/BackendServiceController.php b/Classes/Controller/BackendServiceController.php index a346851e46..1db5e1a307 100644 --- a/Classes/Controller/BackendServiceController.php +++ b/Classes/Controller/BackendServiceController.php @@ -17,7 +17,6 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Exception\WorkspaceIsNotEmptyException; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Dto\RebaseErrorHandlingStrategy; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateCurrentlyDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateDoesCurrentlyNotCoverDimensionSpacePoint; use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress; @@ -35,6 +34,7 @@ use Neos\Neos\Domain\Service\WorkspacePublishingService; use Neos\Neos\Domain\Service\WorkspaceService; use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult; +use Neos\Neos\Security\Authorization\ContentRepositoryAuthorizationService; use Neos\Neos\Service\UserService; use Neos\Neos\Ui\Application\ChangeTargetWorkspace; use Neos\Neos\Ui\Application\DiscardAllChanges; @@ -156,6 +156,12 @@ class BackendServiceController extends ActionController */ protected $reloadNodesQueryHandler; + /** + * @Flow\Inject + * @var ContentRepositoryAuthorizationService + */ + protected $contentRepositoryAuthorizationService; + /** * Set the controller context on the feedback collection after the controller * has been initialized @@ -451,11 +457,10 @@ public function changeBaseWorkspaceAction(string $targetWorkspaceName, string $d } $contentRepository = $this->contentRepositoryRegistry->get($documentNodeAddress->contentRepositoryId); - $subgraph = $contentRepository->getContentGraph($userWorkspace->workspaceName) - ->getSubgraph( - $command->documentNode->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() - ); + $subgraph = $contentRepository->getContentSubgraph( + $userWorkspace->workspaceName, + $command->documentNode->dimensionSpacePoint, + ); $documentNodeInstance = $subgraph->findNodeById($command->documentNode->aggregateId); assert($documentNodeInstance !== null); @@ -579,9 +584,9 @@ public function getAdditionalNodeMetadataAction(array $nodes): void foreach ($nodes as $nodeAddressString) { $nodeAddress = NodeAddress::fromJsonString($nodeAddressString); $contentRepository = $this->contentRepositoryRegistry->get($nodeAddress->contentRepositoryId); - $subgraph = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph( + $subgraph = $contentRepository->getContentSubgraph( + $nodeAddress->workspaceName, $nodeAddress->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() ); $node = $subgraph->findNodeById($nodeAddress->aggregateId); @@ -590,13 +595,16 @@ public function getAdditionalNodeMetadataAction(array $nodes): void return $this->getCurrentDimensionPresetIdentifiersForNode($node); }, $node->getOtherNodeVariants())));*/ if (!is_null($node)) { + $authenticatedAccount = $this->securityContext->getAccount(); + $nodePrivileges = $authenticatedAccount === null + ? $this->contentRepositoryAuthorizationService->getNodePermissionsForAnonymousUser($node) + : $this->contentRepositoryAuthorizationService->getNodePermissionsForAccount($node, $authenticatedAccount); $result[$nodeAddress->toJson()] = [ - // todo reimplement nodePolicyService 'policy' => [ - 'disallowedNodeTypes' => [], - 'canRemove' => true, - 'canEdit' => true, - 'disallowedProperties' => [] + 'disallowedNodeTypes' => [], // not implemented for Neos 9.0 + 'canRemove' => $nodePrivileges->edit, + 'canEdit' => $nodePrivileges->edit, + 'disallowedProperties' => [] // not implemented for Neos 9.0 ] //'dimensions' => $this->getCurrentDimensionPresetIdentifiersForNode($node), //'otherNodeVariants' => $otherNodeVariants @@ -623,9 +631,9 @@ public function getPolicyInformationAction(array $nodes): void $result = []; foreach ($nodes as $nodeAddress) { $contentRepository = $this->contentRepositoryRegistry->get($nodeAddress->contentRepositoryId); - $subgraph = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph( + $subgraph = $contentRepository->getContentSubgraph( + $nodeAddress->workspaceName, $nodeAddress->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() ); $node = $subgraph->findNodeById($nodeAddress->aggregateId); if (!is_null($node)) { @@ -704,9 +712,9 @@ public function generateUriPathSegmentAction(string $contextNode, string $text): { $contextNodeAddress = NodeAddress::fromJsonString($contextNode); $contentRepository = $this->contentRepositoryRegistry->get($contextNodeAddress->contentRepositoryId); - $subgraph = $contentRepository->getContentGraph($contextNodeAddress->workspaceName)->getSubgraph( + $subgraph = $contentRepository->getContentSubgraph( + $contextNodeAddress->workspaceName, $contextNodeAddress->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() ); $contextNode = $subgraph->findNodeById($contextNodeAddress->aggregateId); diff --git a/Classes/Domain/Model/Changes/CopyAfter.php b/Classes/Domain/Model/Changes/CopyAfter.php index 30d3dfc638..5396ee4175 100644 --- a/Classes/Domain/Model/Changes/CopyAfter.php +++ b/Classes/Domain/Model/Changes/CopyAfter.php @@ -14,7 +14,6 @@ use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\Feature\NodeDuplication\Command\CopyNodesRecursively; -use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; /** * @internal These objects internally reflect possible operations made by the Neos.Ui. @@ -64,9 +63,9 @@ public function apply(): void $contentRepository = $this->contentRepositoryRegistry->get($subject->contentRepositoryId); $command = CopyNodesRecursively::createFromSubgraphAndStartNode( - $contentRepository->getContentGraph($subject->workspaceName)->getSubgraph( + $contentRepository->getContentSubgraph( + $subject->workspaceName, $subject->dimensionSpacePoint, - VisibilityConstraints::withoutRestrictions() ), $subject->workspaceName, $subject, diff --git a/Classes/Fusion/Helper/WorkspaceHelper.php b/Classes/Fusion/Helper/WorkspaceHelper.php index a3b316ff22..3d02ce1045 100644 --- a/Classes/Fusion/Helper/WorkspaceHelper.php +++ b/Classes/Fusion/Helper/WorkspaceHelper.php @@ -18,6 +18,7 @@ use Neos\Flow\Security\Context; use Neos\Neos\Domain\Service\UserService; use Neos\Neos\Domain\Service\WorkspaceService; +use Neos\Neos\Security\Authorization\ContentRepositoryAuthorizationService; use Neos\Neos\Ui\ContentRepository\Service\WorkspaceService as UiWorkspaceService; /** @@ -55,6 +56,12 @@ class WorkspaceHelper implements ProtectedContextAwareInterface */ protected $workspaceService; + /** + * @Flow\Inject + * @var ContentRepositoryAuthorizationService + */ + protected $contentRepositoryAuthorizationService; + /** * @return array */ @@ -64,9 +71,13 @@ public function getPersonalWorkspace(ContentRepositoryId $contentRepositoryId): if ($currentUser === null) { return []; } + $authenticatedAccount = $this->securityContext->getAccount(); + if ($authenticatedAccount === null) { + return []; + } $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); $personalWorkspace = $this->workspaceService->getPersonalWorkspaceForUser($contentRepositoryId, $currentUser->getId()); - $personalWorkspacePermissions = $this->workspaceService->getWorkspacePermissionsForUser($contentRepositoryId, $personalWorkspace->workspaceName, $currentUser); + $personalWorkspacePermissions = $this->contentRepositoryAuthorizationService->getWorkspacePermissionsForAccount($contentRepositoryId, $personalWorkspace->workspaceName, $authenticatedAccount); $publishableNodes = $this->uiWorkspaceService->getPublishableNodeInfo($personalWorkspace->workspaceName, $contentRepository->id); return [ 'name' => $personalWorkspace->workspaceName->value, diff --git a/Classes/Infrastructure/Configuration/ConfigurationProvider.php b/Classes/Infrastructure/Configuration/ConfigurationProvider.php index 15e1752c2c..10c7a7cdf8 100644 --- a/Classes/Infrastructure/Configuration/ConfigurationProvider.php +++ b/Classes/Infrastructure/Configuration/ConfigurationProvider.php @@ -18,8 +18,10 @@ use Neos\Flow\Annotations as Flow; use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\Mvc\Routing\UriBuilder; +use Neos\Flow\Security\Context as SecurityContext; use Neos\Neos\Domain\Model\WorkspaceClassification; use Neos\Neos\Domain\Service\WorkspaceService; +use Neos\Neos\Security\Authorization\ContentRepositoryAuthorizationService; use Neos\Neos\Service\UserService; use Neos\Neos\Ui\Domain\InitialData\CacheConfigurationVersionProviderInterface; use Neos\Neos\Ui\Domain\InitialData\ConfigurationProviderInterface; @@ -33,12 +35,18 @@ final class ConfigurationProvider implements ConfigurationProviderInterface #[Flow\Inject] protected UserService $userService; + #[Flow\Inject] + protected SecurityContext $securityContext; + #[Flow\Inject] protected ConfigurationManager $configurationManager; #[Flow\Inject] protected WorkspaceService $workspaceService; + #[Flow\Inject] + protected ContentRepositoryAuthorizationService $contentRepositoryAuthorizationService; + #[Flow\Inject] protected CacheConfigurationVersionProviderInterface $cacheConfigurationVersionProvider; @@ -93,8 +101,8 @@ public function getConfiguration( */ private function getAllowedTargetWorkspaces(ContentRepository $contentRepository): array { - $backendUser = $this->userService->getBackendUser(); - if ($backendUser === null) { + $authenticatedAccount = $this->securityContext->getAccount(); + if ($authenticatedAccount === null) { return []; } $result = []; @@ -103,7 +111,7 @@ private function getAllowedTargetWorkspaces(ContentRepository $contentRepository if (!in_array($workspaceMetadata->classification, [WorkspaceClassification::ROOT, WorkspaceClassification::SHARED], true)) { continue; } - $workspacePermissions = $this->workspaceService->getWorkspacePermissionsForUser($contentRepository->id, $workspace->workspaceName, $backendUser); + $workspacePermissions = $this->contentRepositoryAuthorizationService->getWorkspacePermissionsForAccount($contentRepository->id, $workspace->workspaceName, $authenticatedAccount); if ($workspacePermissions->read === false) { continue; }