diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php index d8543a1e00a..2f918be284f 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -12,15 +12,12 @@ */ require_once(__DIR__ . '/../../../../../../Application/Neos.Behat/Tests/Behat/FlowContextTrait.php'); -require_once(__DIR__ . '/../../../../../../Framework/Neos.Flow/Tests/Behavior/Features/Bootstrap/IsolatedBehatStepsTrait.php'); -require_once(__DIR__ . '/../../../../../Neos.ContentRepository.Security/Tests/Behavior/Features/Bootstrap/NodeAuthorizationTrait.php'); require_once(__DIR__ . '/ProjectionIntegrityViolationDetectionTrait.php'); use Behat\Behat\Context\Context as BehatContext; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Neos\Behat\Tests\Behat\FlowContextTrait; use Neos\ContentGraph\DoctrineDbalAdapter\Tests\Behavior\Features\Bootstrap\ProjectionIntegrityViolationDetectionTrait; -use Neos\ContentRepository\BehavioralTests\Tests\Functional\BehatTestHelper; use Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\CRBehavioralTestsSubjectProvider; use Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\GherkinPyStringNodeBasedNodeTypeManagerFactory; use Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\GherkinTableNodeBasedContentDimensionSourceFactory; @@ -30,7 +27,6 @@ use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteTrait; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; -use Neos\Flow\Tests\Behavior\Features\Bootstrap\IsolatedBehatStepsTrait; /** * Features context @@ -38,13 +34,10 @@ class FeatureContext implements BehatContext { use FlowContextTrait; - use IsolatedBehatStepsTrait; use ProjectionIntegrityViolationDetectionTrait; use CRTestSuiteTrait; use CRBehavioralTestsSubjectProvider; - protected string $behatTestHelperObjectName = BehatTestHelper::class; - protected ContentRepositoryRegistry $contentRepositoryRegistry; public function __construct() diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php index d55e4307a95..31d9bc21b50 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php @@ -12,18 +12,15 @@ */ require_once(__DIR__ . '/../../../../../Application/Neos.Behat/Tests/Behat/FlowContextTrait.php'); -require_once(__DIR__ . '/../../../../Neos.ContentRepository.Security/Tests/Behavior/Features/Bootstrap/NodeAuthorizationTrait.php'); require_once(__DIR__ . '/../../../../Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php'); -require_once(__DIR__ . '/../../../../../Framework/Neos.Flow/Tests/Behavior/Features/Bootstrap/IsolatedBehatStepsTrait.php'); -require_once(__DIR__ . '/../../../../../Framework/Neos.Flow/Tests/Behavior/Features/Bootstrap/SecurityOperationsTrait.php'); use Behat\Behat\Context\Context as BehatContext; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use GuzzleHttp\Psr7\Uri; use Neos\Behat\Tests\Behat\FlowContextTrait; +use Neos\ContentGraph\DoctrineDbalAdapter\Tests\Behavior\Features\Bootstrap\ProjectionIntegrityViolationDetectionTrait; use Neos\ContentRepository\BehavioralTests\ProjectionRaceConditionTester\Dto\TraceEntryType; use Neos\ContentRepository\BehavioralTests\ProjectionRaceConditionTester\RedisInterleavingLogger; -use Neos\ContentRepository\BehavioralTests\Tests\Functional\BehatTestHelper; use Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\CRBehavioralTestsSubjectProvider; use Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\GherkinPyStringNodeBasedNodeTypeManagerFactory; use Neos\ContentRepository\BehavioralTests\TestSuite\Behavior\GherkinTableNodeBasedContentDimensionSourceFactory; @@ -33,19 +30,15 @@ use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Feature\NodeModification\Dto\PropertyValuesToWrite; use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface; -use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteTrait; -use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\MigrationsTrait; -use Neos\ContentGraph\DoctrineDbalAdapter\Tests\Behavior\Features\Bootstrap\ProjectionIntegrityViolationDetectionTrait; -use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\StructureAdjustmentsTrait; use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\DayOfWeek; use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\PostalAddress; use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\PriceSpecification; -use Neos\ContentRepository\Security\Service\AuthorizationService; +use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteTrait; +use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\MigrationsTrait; +use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\StructureAdjustmentsTrait; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Configuration\ConfigurationManager; use Neos\Flow\ObjectManagement\ObjectManagerInterface; -use Neos\Flow\Tests\Behavior\Features\Bootstrap\IsolatedBehatStepsTrait; -use Neos\Flow\Tests\Behavior\Features\Bootstrap\SecurityOperationsTrait; /** * Features context @@ -53,17 +46,12 @@ class FeatureContext implements BehatContext { use FlowContextTrait; - use NodeAuthorizationTrait; - use SecurityOperationsTrait; - use IsolatedBehatStepsTrait; use CRTestSuiteTrait; use CRBehavioralTestsSubjectProvider; use ProjectionIntegrityViolationDetectionTrait; use StructureAdjustmentsTrait; use MigrationsTrait; - protected string $behatTestHelperObjectName = BehatTestHelper::class; - protected ContentRepositoryRegistry $contentRepositoryRegistry; private bool $raceConditionTrackerEnabled = false; @@ -75,8 +63,6 @@ public function __construct() } $this->objectManager = self::$bootstrap->getObjectManager(); - $this->setupSecurity(); - $this->nodeAuthorizationService = $this->getObjectManager()->get(AuthorizationService::class); $this->dbalClient = $this->getObjectManager()->get(DbalClientInterface::class); $this->setupCRTestSuiteTrait(); $this->setUpInterleavingLogger(); diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Functional/BehatTestHelper.php b/Neos.ContentRepository.BehavioralTests/Tests/Functional/BehatTestHelper.php deleted file mode 100644 index 9b9ceb6f80c..00000000000 --- a/Neos.ContentRepository.BehavioralTests/Tests/Functional/BehatTestHelper.php +++ /dev/null @@ -1,111 +0,0 @@ -get(Bootstrap::class); - $this->isolated = false; - } - - /** - * @return mixed - */ - protected function getObjectManager(): ObjectManagerInterface - { - return $this->objectManager; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/AbstractNodePrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/AbstractNodePrivilege.php deleted file mode 100644 index 985e9b89a40..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/AbstractNodePrivilege.php +++ /dev/null @@ -1,194 +0,0 @@ - $parameters - */ - public function __construct( - PrivilegeTarget $privilegeTarget, - string $matcher, - string $permission, - array $parameters - ) { - parent::__construct($privilegeTarget, $matcher, $permission, $parameters); - $this->cacheEntryIdentifier = ''; - } - - /** - * @return void - */ - public function initialize() - { - if ($this->initialized) { - return; - } - $this->initialized = true; - /** @var CompilingEvaluator $eelCompilingEvaluator */ - $eelCompilingEvaluator = $this->objectManager->get(CompilingEvaluator::class); - $this->eelCompilingEvaluator = $eelCompilingEvaluator; - /** @var NodePrivilegeContext $nodeContext */ - $nodeContext = new $this->nodeContextClassName(); - $this->nodeContext = $nodeContext; - $this->initializeMethodPrivilege(); - } - - /** - * @return void - */ - protected function buildCacheEntryIdentifier() - { - $this->cacheEntryIdentifier = md5($this->privilegeTarget->getIdentifier() - . '__methodPrivilege' . '|' . $this->buildMethodPrivilegeMatcher()); - } - - /** - * Unique identifier of this privilege - * - * @return string - */ - public function getCacheEntryIdentifier(): string - { - if ($this->cacheEntryIdentifier === '') { - $this->buildCacheEntryIdentifier(); - } - - return $this->cacheEntryIdentifier; - } - - /** - * @param PrivilegeSubjectInterface|NodePrivilegeSubject|MethodPrivilegeSubject $subject - * (one of NodePrivilegeSubject or MethodPrivilegeSubject) - * @return boolean - * @throws InvalidPrivilegeTypeException - */ - public function matchesSubject(PrivilegeSubjectInterface $subject) - { - if (!$subject instanceof NodePrivilegeSubject && !$subject instanceof MethodPrivilegeSubject) { - throw new InvalidPrivilegeTypeException(sprintf( - 'Privileges of type "%s" only support subjects of type "%s" or "%s",' - . ' but we got a subject of type: "%s".', - AbstractNodePrivilege::class, - NodePrivilegeSubject::class, - MethodPrivilegeSubject::class, - get_class($subject) - ), 1417014368); - } - - if ($subject instanceof MethodPrivilegeSubject) { - $this->initializeMethodPrivilege(); - return $this->methodPrivilege->matchesSubject($subject); - } - - $this->initialize(); - $nodeContext = new $this->nodeContextClassName($subject->getNode()); - $eelContext = new Context($nodeContext); - - return $this->eelCompilingEvaluator->evaluate($this->getParsedMatcher(), $eelContext); - } - - /** - * @param string $className - * @param string $methodName - * @return boolean - */ - public function matchesMethod($className, $methodName) - { - $this->initializeMethodPrivilege(); - return $this->methodPrivilege->matchesMethod($className, $methodName); - } - - /** - * @return PointcutFilterInterface - */ - public function getPointcutFilterComposite() - { - $this->initializeMethodPrivilege(); - return $this->methodPrivilege->getPointcutFilterComposite(); - } - - /** - * @throws \Neos\Flow\Security\Exception - */ - protected function initializeMethodPrivilege(): void - { - if ($this->methodPrivilege !== null) { - return; - } - $methodPrivilegeMatcher = $this->buildMethodPrivilegeMatcher(); - $methodPrivilegeTarget = new PrivilegeTarget( - $this->privilegeTarget->getIdentifier() . '__methodPrivilege', - MethodPrivilege::class, - $methodPrivilegeMatcher - ); - $methodPrivilegeTarget->injectObjectManager($this->objectManager); - /** @var MethodPrivilegeInterface $methodPrivilege */ - $methodPrivilege = $methodPrivilegeTarget->createPrivilege( - $this->getPermission(), - $this->getParameters() - ); - $this->methodPrivilege = $methodPrivilege; - } - - /** - * Evaluates the matcher with this objects nodeContext and returns the result. - * - * @return mixed - */ - protected function evaluateNodeContext() - { - $eelContext = new Context($this->nodeContext); - return $this->eelCompilingEvaluator->evaluate($this->getParsedMatcher(), $eelContext); - } - - /** - * @return string - */ - abstract protected function buildMethodPrivilegeMatcher(); -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/AbstractNodePropertyPrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/AbstractNodePropertyPrivilege.php deleted file mode 100644 index 438f61e7152..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/AbstractNodePropertyPrivilege.php +++ /dev/null @@ -1,97 +0,0 @@ - - */ - protected array $methodNameToPropertyMapping = []; - - /** - * @param PrivilegeSubjectInterface|PropertyAwareNodePrivilegeSubject|MethodPrivilegeSubject $subject - * @throws InvalidPrivilegeTypeException - */ - public function matchesSubject(PrivilegeSubjectInterface $subject): bool - { - if (!$subject instanceof PropertyAwareNodePrivilegeSubject && !$subject instanceof MethodPrivilegeSubject) { - throw new InvalidPrivilegeTypeException(sprintf( - 'Privileges of type "%s" only support subjects of type "%s" or "%s",' - . ' but we got a subject of type: "%s".', - ReadNodePropertyPrivilege::class, - PropertyAwareNodePrivilegeSubject::class, - MethodPrivilegeSubject::class, - get_class($subject) - ), 1417018448); - } - - $this->initialize(); - $this->evaluateNodeContext(); - if ($subject instanceof MethodPrivilegeSubject) { - if ($this->methodPrivilege->matchesSubject($subject) === false) { - return false; - } - - $joinPoint = $subject->getJoinPoint(); - - // if the context isn't restricted to certain properties, it matches *all* properties - if ($this->nodeContext->hasProperties()) { - $methodName = $joinPoint->getMethodName(); - $propertyName = $this->methodNameToPropertyMapping[$methodName] - ?? $joinPoint->getMethodArgument('propertyName'); - if (!in_array($propertyName, $this->nodeContext->getNodePropertyNames())) { - return false; - } - } - - /** @var Node $node */ - $node = $joinPoint->getProxy(); - $nodePrivilegeSubject = new NodePrivilegeSubject($node); - return parent::matchesSubject($nodePrivilegeSubject); - } - if ($subject->hasPropertyName() && !in_array( - $subject->getPropertyName(), - $this->nodeContext->getNodePropertyNames() - )) { - return false; - } - return parent::matchesSubject($subject); - } - - /** - * @return array - */ - public function getNodePropertyNames(): array - { - return $this->nodeContext->getNodePropertyNames(); - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilege.php deleted file mode 100644 index cbbfd195d58..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilege.php +++ /dev/null @@ -1,101 +0,0 @@ -initialize(); - $this->evaluateNodeContext(); - if ($subject instanceof MethodPrivilegeSubject) { - if ($this->methodPrivilege->matchesSubject($subject) === false) { - return false; - } - - $joinPoint = $subject->getJoinPoint(); - $allowedCreationNodeTypes = $this->nodeContext->getCreationNodeTypes(); - $actualNodeType = $joinPoint->getMethodName() === 'createNodeFromTemplate' - ? $joinPoint->getMethodArgument('nodeTemplate')->getNodeType()->getName() - : $joinPoint->getMethodArgument('nodeType')->getName(); - - if ($allowedCreationNodeTypes !== [] && !in_array($actualNodeType, $allowedCreationNodeTypes)) { - return false; - } - - /** @var Node $node */ - $node = $joinPoint->getProxy(); - $nodePrivilegeSubject = new NodePrivilegeSubject($node); - return parent::matchesSubject($nodePrivilegeSubject); - } - - $creationNodeType = $subject->getCreationNodeType(); - if ($this->nodeContext->getCreationNodeTypes() === [] - || ($subject->hasCreationNodeType() === false) - || !is_null($creationNodeType) && in_array( - $creationNodeType->getName(), - $this->nodeContext->getCreationNodeTypes() - ) === true) { - return parent::matchesSubject($subject); - } - return false; - } - - /** - * @return array $creationNodeTypes - */ - public function getCreationNodeTypes(): array - { - return $this->nodeContext->getCreationNodeTypes(); - } - - protected function buildMethodPrivilegeMatcher(): string - { - return 'method(' . CreateNodeVariant::class . '->__construct()) && method(' - . CreateNodeAggregateWithNodeAndSerializedProperties::class . '->__construct())'; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilegeContext.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilegeContext.php deleted file mode 100644 index b2b086dc7ed..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilegeContext.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ - protected string|array $creationNodeTypes; - - /** - * @param string|array $creationNodeTypes either an array of supported node type identifiers - * or a single node type identifier (for example "Neos.Neos:Document") - * @return boolean Has to return true, to evaluate the eel expression correctly in any case - */ - public function createdNodeIsOfType(string|array $creationNodeTypes): bool - { - $this->creationNodeTypes = $creationNodeTypes; - - return true; - } - - /** - * @return array $creationNodeTypes - */ - public function getCreationNodeTypes(): array - { - if (is_array($this->creationNodeTypes)) { - return $this->creationNodeTypes; - } - return [$this->creationNodeTypes]; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilegeSubject.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilegeSubject.php deleted file mode 100644 index acd5a1307eb..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/CreateNodePrivilegeSubject.php +++ /dev/null @@ -1,50 +0,0 @@ -creationNodeType = $creationNodeType; - parent::__construct($node, $joinPoint); - } - - public function hasCreationNodeType(): bool - { - return ($this->creationNodeType !== null); - } - - public function getCreationNodeType(): ?NodeType - { - return $this->creationNodeType; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/EditNodePrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/EditNodePrivilege.php deleted file mode 100644 index 70fb9529486..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/EditNodePrivilege.php +++ /dev/null @@ -1,84 +0,0 @@ -initializeMethodPrivilege(); - if ($this->methodPrivilege->matchesSubject($subject) === false) { - return false; - } - - /** @var Node $node */ - $node = $subject->getJoinPoint()->getProxy(); - $nodePrivilegeSubject = new NodePrivilegeSubject($node); - return parent::matchesSubject($nodePrivilegeSubject); - } - - return parent::matchesSubject($subject); - } - - /** - * This is the pointcut expression for all methods to intercept. - * It targets all public methods that could change the outer state of a node. - * Note: Node::setIndex() is excluded because that might be called by the system - * when redistributing nodes on one level - * - * @return string - */ - protected function buildMethodPrivilegeMatcher() - { - return 'method(' . SetSerializedNodeProperties::class . '->__construct()) || method(' - . SetNodeReferences::class . '->__construct()) || method(' - . RemoveNodeAggregate::class . '->__construct()) || method(' - . MoveNodeAggregate::class . '->__construct()) || method(' - . EnableNodeAggregate::class . '->__construct()) || method(' - . DisableNodeAggregate::class . '->__construct()) || method(' - . ChangeNodeAggregateName::class . '->__construct()) || method(' - . ChangeNodeAggregateType::class . '->__construct())'; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/EditNodePropertyPrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/EditNodePropertyPrivilege.php deleted file mode 100644 index d9fd60f05b9..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/EditNodePropertyPrivilege.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ - protected array $methodNameToPropertyMapping = [ - 'setName' => 'name', - 'setHidden' => 'hidden', - 'setHiddenInIndex' => 'hiddenInIndex', - 'setHiddenBeforeDateTime' => 'hiddenBeforeDateTime', - 'setHiddenAfterDateTime' => 'hiddenAfterDateTime', - 'setAccessRoles' => 'accessRoles', - ]; - - protected function buildMethodPrivilegeMatcher(): string - { - return 'method(' . SetSerializedNodeProperties::class . '->__construct()) || method(' - . SetNodeReferences::class . '->__construct()) || method(' - . EnableNodeAggregate::class . '->__construct()) || method(' - . DisableNodeAggregate::class . '->__construct()) || method(' - . ChangeNodeAggregateName::class . '->__construct()) || method(' - . ChangeNodeAggregateType::class . '->__construct())'; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/NodePrivilegeContext.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/NodePrivilegeContext.php deleted file mode 100644 index 30d267a93f2..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/NodePrivilegeContext.php +++ /dev/null @@ -1,223 +0,0 @@ -node = $node; - } - - /** - * Matches if the selected node is an *ancestor* of the given node specified by $nodePathOrIdentifier - * - * Example: isAncestorNodeOf('/sites/some/path') matches for the nodes "/sites", - * "/sites/some" and "/sites/some/path" but not for "/sites/some/other" - * - * @param string $nodePathOrIdentifier The identifier or absolute path of the node to match - * @return boolean true if the given node matches otherwise false - */ - public function isAncestorNodeOf(string $nodePathOrIdentifier): bool - { - $referenceNodeAggregateId = $this->resolveNodeAggregateIdFromNodePathOrId($nodePathOrIdentifier); - if (!$referenceNodeAggregateId) { - return false; - } - - if ($referenceNodeAggregateId->equals($this->node->nodeAggregateId)) { - return true; - } - - foreach ($this->getSubgraph()->findAncestorNodes( - $referenceNodeAggregateId, - FindAncestorNodesFilter::create() - ) as $ancestorNode) { - if ($ancestorNode->nodeAggregateId->equals($this->node->nodeAggregateId)) { - return true; - } - } - - return false; - } - - /** - * Matches if the selected node is a *descendant* of the given node specified by $nodePathOrIdentifier - * - * Example: isDescendantNodeOf('/sites/some/path') matches for the nodes "/sites/some/path", - * "/sites/some/path/subnode" but not for "/sites/some/other" - * - * @param string $nodePathOrIdentifier The identifier or absolute path of the node to match - * @return bool true if the given node matches otherwise false - */ - public function isDescendantNodeOf(string $nodePathOrIdentifier): bool - { - $referenceNodeAggregateId = $this->resolveNodeAggregateIdFromNodePathOrId($nodePathOrIdentifier); - if (!$referenceNodeAggregateId) { - return false; - } - - if ($referenceNodeAggregateId->equals($this->node->nodeAggregateId)) { - return true; - } - - foreach ($this->getSubgraph()->findAncestorNodes( - $this->node->nodeAggregateId, - FindAncestorNodesFilter::create() - ) as $ancestorNode) { - if ($ancestorNode->nodeAggregateId->equals($referenceNodeAggregateId)) { - return true; - } - } - - return false; - } - - /** - * Matches if the selected node is a *descendant* or *ancestor* of the given node specified by $nodePathOrIdentifier - * - * Example: isAncestorOrDescendantNodeOf('/sites/some') matches for the nodes "/sites", "/sites/some", - * "/sites/some/sub" but not "/sites/other" - * - * @param string $nodePathOrIdentifier The identifier or absolute path of the node to match - * @return bool true if the given node matches otherwise false - */ - public function isAncestorOrDescendantNodeOf(string $nodePathOrIdentifier): bool - { - return $this->isAncestorNodeOf($nodePathOrIdentifier) || $this->isDescendantNodeOf($nodePathOrIdentifier); - } - - /** - * Matches if the selected node is of the given NodeType(s). - * If multiple types are specified, only one entry has to match - * - * Example: nodeIsOfType(['Neos.ContentRepository:NodeType1', 'Neos.ContentRepository:NodeType2'] matches, - * if the selected node is of (sub) type *Neos.ContentRepository:NodeType1* or *Neos.ContentRepository:NodeType1* - * - * @param string|array $nodeTypes A single or an array of fully qualified NodeType name(s), - * e.g. "Neos.Neos:Document" - * @return bool true if the selected node matches the $nodeTypes, otherwise false - */ - public function nodeIsOfType(string|array $nodeTypes): bool - { - if (!is_array($nodeTypes)) { - $nodeTypes = [$nodeTypes]; - } - - foreach ($nodeTypes as $nodeType) { - if ($this->node->nodeType->isOfType($nodeType)) { - return true; - } - } - return false; - } - - /** - * Matches if the selected node belongs to one of the given $workspaceNames - * - * Example: isInWorkspace(['live', 'user-admin']) matches, - * if the selected node is in one of the workspaces "user-admin" or "live" - * - * @param array $workspaceNames An array of workspace names, e.g. ["live", "user-admin"] - * @return bool true if the selected node matches the $workspaceNames, otherwise false - */ - public function isInWorkspace(array $workspaceNames): bool - { - $contentRepository = $this->contentRepositoryRegistry->get($this->node->subgraphIdentity->contentRepositoryId); - - $workspace = $contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId( - $this->node->subgraphIdentity->contentStreamId - ); - return !is_null($workspace) && in_array($workspace->workspaceName->value, $workspaceNames); - } - - /** - * Matches if the currently-selected preset in the passed $dimensionName is one of $presets. - * - * Example: isInDimensionPreset('language', 'de') checks whether the currently-selected language - * preset (in the Neos backend) is "de". - * - * Implementation Note: We deliberately work on the Dimension Preset Name, and not on the - * dimension values itself; as the preset is user-visible and the actual dimension-values - * for a preset are just implementation details. - * - * @param string|array $presets - */ - public function isInDimensionPreset(string $dimensionName, string|array $presets): bool - { - if (!is_array($presets)) { - $presets = [$presets]; - } - - return in_array( - $this->node->subgraphIdentity->dimensionSpacePoint->getCoordinate( - new ContentDimensionId($dimensionName) - ), - $presets - ); - } - - /** - * Resolves the given $nodePathOrIdentifier and returns its node aggregate id if possible - * - * @param string $nodePathOrIdentifier identifier or absolute path for the node to resolve - * @return NodeAggregateId|null depending on whether the given string can be resolved or not - */ - protected function resolveNodeAggregateIdFromNodePathOrId(string $nodePathOrIdentifier): ?NodeAggregateId - { - if (AbsoluteNodePath::patternIsMatchedByString($nodePathOrIdentifier)) { - return $this->getSubgraph()->findNodeByAbsolutePath( - AbsoluteNodePath::fromString($nodePathOrIdentifier) - )?->nodeAggregateId; - } else { - return NodeAggregateId::fromString($nodePathOrIdentifier); - } - } - - private function getSubgraph(): ContentSubgraphInterface - { - if (is_null($this->subgraph)) { - $this->subgraph = $this->contentRepositoryRegistry->subgraphForNode($this->node); - } - - return $this->subgraph; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/NodePrivilegeSubject.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/NodePrivilegeSubject.php deleted file mode 100644 index 51035f43f0a..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/NodePrivilegeSubject.php +++ /dev/null @@ -1,48 +0,0 @@ -node = $node; - $this->joinPoint = $joinPoint; - } - - public function getNode(): Node - { - return $this->node; - } - - public function getJoinPoint(): ?JoinPointInterface - { - return $this->joinPoint; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/PropertyAwareNodePrivilegeContext.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/PropertyAwareNodePrivilegeContext.php deleted file mode 100644 index 5d055ccfa40..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/PropertyAwareNodePrivilegeContext.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - protected array $propertyNames = []; - - /** - * @param string|array $propertyNames - * @return boolean - */ - public function nodePropertyIsIn(string|array $propertyNames): bool - { - if (!is_array($propertyNames)) { - $propertyNames = [$propertyNames]; - } - $this->propertyNames = $propertyNames; - return true; - } - - /** - * @return array - */ - public function getNodePropertyNames(): array - { - return $this->propertyNames; - } - - /** - * Whether or not this context is bound to specific properties - */ - public function hasProperties(): bool - { - return $this->propertyNames !== []; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/PropertyAwareNodePrivilegeSubject.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/PropertyAwareNodePrivilegeSubject.php deleted file mode 100644 index a39801606ed..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/PropertyAwareNodePrivilegeSubject.php +++ /dev/null @@ -1,42 +0,0 @@ -propertyName = $propertyName; - parent::__construct($node, $joinPoint); - } - - public function getPropertyName(): ?string - { - return $this->propertyName; - } - - public function hasPropertyName(): bool - { - return $this->propertyName !== null; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/ReadNodePrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/ReadNodePrivilege.php deleted file mode 100644 index a6256586393..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/ReadNodePrivilege.php +++ /dev/null @@ -1,51 +0,0 @@ -getNode()); - $eelContext = new Context($nodeContext); - /** @var CompilingEvaluator $eelCompilingEvaluator */ - $eelCompilingEvaluator = $this->objectManager->get(CompilingEvaluator::class); - return $eelCompilingEvaluator->evaluate($this->getParsedMatcher(), $eelContext); - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/ReadNodePropertyPrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/ReadNodePropertyPrivilege.php deleted file mode 100644 index 3e848cf8835..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/ReadNodePropertyPrivilege.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ - protected array $methodNameToPropertyMapping = [ - 'getName' => 'name', - 'isHidden' => 'hidden', - 'isHiddenInIndex' => 'hiddenInIndex', - 'getHiddenBeforeDateTime' => 'hiddenBeforeDateTime', - 'getHiddenAfterDateTime' => 'hiddenAfterDateTime', - 'getAccessRoles' => 'accessRoles', - ]; - - protected function buildMethodPrivilegeMatcher(): string - { - return 'within(' . Node::class . ') && method(.*->(getProperty|getProperties)())'; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/RemoveNodePrivilege.php b/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/RemoveNodePrivilege.php deleted file mode 100644 index 1c4c0826cbe..00000000000 --- a/Neos.ContentRepository.Security/Classes/Authorization/Privilege/Node/RemoveNodePrivilege.php +++ /dev/null @@ -1,63 +0,0 @@ -initializeMethodPrivilege(); - if ($this->methodPrivilege->matchesSubject($subject) === false) { - return false; - } - /** @var Node $node */ - $node = $subject->getJoinPoint()->getProxy(); - $nodePrivilegeSubject = new NodePrivilegeSubject($node); - return parent::matchesSubject($nodePrivilegeSubject); - } - return parent::matchesSubject($subject); - } - - /** - * @return string - */ - protected function buildMethodPrivilegeMatcher() - { - return 'method(' . RemoveNodeAggregate::class . '->__construct())'; - } -} diff --git a/Neos.ContentRepository.Security/Classes/Service/AuthorizationService.php b/Neos.ContentRepository.Security/Classes/Service/AuthorizationService.php deleted file mode 100644 index c95ff197d5f..00000000000 --- a/Neos.ContentRepository.Security/Classes/Service/AuthorizationService.php +++ /dev/null @@ -1,184 +0,0 @@ -privilegeManager->isGranted(EditNodePrivilege::class, new NodePrivilegeSubject($node)); - } - - /** - * Returns true if the currently authenticated user is allowed to create a node of type $typeOfNewNode within the given $referenceNode - * - * @param Node $referenceNode - * @param NodeType $typeOfNewNode - * @return boolean - */ - public function isGrantedToCreateNode(Node $referenceNode, NodeType $typeOfNewNode = null) - { - return $this->privilegeManager->isGranted(CreateNodePrivilege::class, new CreateNodePrivilegeSubject($referenceNode, $typeOfNewNode)); - } - - /** - * Returns the node types that the currently authenticated user is *denied* to create within the given $referenceNode - * - * @param Node $referenceNode - * @return string[] Array of granted node type names - */ - public function getNodeTypeNamesDeniedForCreation(Node $referenceNode) - { - $privilegeSubject = new CreateNodePrivilegeSubject($referenceNode); - - $contentRepository = $this->contentRepositoryRegistry->get($referenceNode->subgraphIdentity->contentRepositoryId); - $allNodeTypes = $contentRepository->getNodeTypeManager()->getNodeTypes(); - - $deniedCreationNodeTypes = []; - $grantedCreationNodeTypes = []; - $abstainedCreationNodeTypes = []; - foreach ($this->securityContext->getRoles() as $role) { - /** @var CreateNodePrivilege $createNodePrivilege */ - foreach ($role->getPrivilegesByType(CreateNodePrivilege::class) as $createNodePrivilege) { - if (!$createNodePrivilege->matchesSubject($privilegeSubject)) { - continue; - } - - if ($createNodePrivilege->getCreationNodeTypes() !== []) { - $affectedNodeTypes = $createNodePrivilege->getCreationNodeTypes(); - } else { - $affectedNodeTypes = array_map(static fn (NodeType $nodeType) => $nodeType->name->value, $allNodeTypes); - } - - if ($createNodePrivilege->isGranted()) { - $grantedCreationNodeTypes[] = array_merge($grantedCreationNodeTypes, $affectedNodeTypes); - } elseif ($createNodePrivilege->isDenied()) { - $deniedCreationNodeTypes = array_merge($deniedCreationNodeTypes, $affectedNodeTypes); - } else { - $abstainedCreationNodeTypes = array_merge($abstainedCreationNodeTypes, $affectedNodeTypes); - } - } - } - $implicitlyDeniedNodeTypes = array_diff($abstainedCreationNodeTypes, $grantedCreationNodeTypes); - return array_merge($implicitlyDeniedNodeTypes, $deniedCreationNodeTypes); - } - - /** - * Returns true if the currently authenticated user is allowed to remove the given $node - * - * @param Node $node - * @return boolean - */ - public function isGrantedToRemoveNode(Node $node) - { - $privilegeSubject = new NodePrivilegeSubject($node); - return $this->privilegeManager->isGranted(RemoveNodePrivilege::class, $privilegeSubject); - } - - /** - * @param Node $node - * @param string $propertyName - * @return boolean - */ - public function isGrantedToReadNodeProperty(Node $node, $propertyName) - { - $privilegeSubject = new PropertyAwareNodePrivilegeSubject($node, null, $propertyName); - return $this->privilegeManager->isGranted(ReadNodePropertyPrivilege::class, $privilegeSubject); - } - - /** - * @param Node $node - * @param string $propertyName - * @return boolean - */ - public function isGrantedToEditNodeProperty(Node $node, $propertyName) - { - $privilegeSubject = new PropertyAwareNodePrivilegeSubject($node, null, $propertyName); - return $this->privilegeManager->isGranted(EditNodePropertyPrivilege::class, $privilegeSubject); - } - - /** - * @param Node $node - * @return string[] Array of granted node property names - */ - public function getDeniedNodePropertiesForEditing(Node $node) - { - $privilegeSubject = new PropertyAwareNodePrivilegeSubject($node); - - $deniedNodePropertyNames = []; - $grantedNodePropertyNames = []; - $abstainedNodePropertyNames = []; - foreach ($this->securityContext->getRoles() as $role) { - /** @var EditNodePropertyPrivilege $editNodePropertyPrivilege */ - foreach ($role->getPrivilegesByType(EditNodePropertyPrivilege::class) as $editNodePropertyPrivilege) { - if (!$editNodePropertyPrivilege->matchesSubject($privilegeSubject)) { - continue; - } - if ($editNodePropertyPrivilege->isGranted()) { - $grantedNodePropertyNames = array_merge($grantedNodePropertyNames, $editNodePropertyPrivilege->getNodePropertyNames()); - } elseif ($editNodePropertyPrivilege->isDenied()) { - $deniedNodePropertyNames = array_merge($deniedNodePropertyNames, $editNodePropertyPrivilege->getNodePropertyNames()); - } else { - $abstainedNodePropertyNames = array_merge($abstainedNodePropertyNames, $editNodePropertyPrivilege->getNodePropertyNames()); - } - } - } - - $implicitlyDeniedNodePropertyNames = array_diff($abstainedNodePropertyNames, $grantedNodePropertyNames); - return array_merge($implicitlyDeniedNodePropertyNames, $deniedNodePropertyNames); - } -} diff --git a/Neos.ContentRepository.Security/Tests/Behavior/Features/Bootstrap/NodeAuthorizationTrait.php b/Neos.ContentRepository.Security/Tests/Behavior/Features/Bootstrap/NodeAuthorizationTrait.php deleted file mode 100644 index 5977c310ad6..00000000000 --- a/Neos.ContentRepository.Security/Tests/Behavior/Features/Bootstrap/NodeAuthorizationTrait.php +++ /dev/null @@ -1,639 +0,0 @@ -nodeAuthorizationService - * * $this->nodeTypeManager - * - * Note: This trait expects the IsolatedBehatStepsTrait to be available! - */ -trait NodeAuthorizationTrait -{ - use CRTestSuiteRuntimeVariables; - - /** - * @Flow\Inject - * @var \Neos\ContentRepository\Security\Service\AuthorizationService - */ - protected $nodeAuthorizationService; - - /** - * @Flow\Inject - * @var \Neos\ContentRepository\Core\NodeType\NodeTypeManager - */ - protected $nodeTypeManager; - - /** - * @param string $expectedResult - * @Given /^I should get (true|false) when asking the node authorization service if editing this node is granted$/ - */ - public function iShouldGetTrueWhenAskingTheNodeAuthorizationServiceIfEditingThisNodeIsGranted($expectedResult) - { - if ($this->isolated === true) { - $this->callStepInSubProcess(__METHOD__, sprintf(' %s %s', 'string', escapeshellarg(trim($expectedResult)))); - } else { - if ($expectedResult === 'true') { - if ($this->nodeAuthorizationService->isGrantedToEditNode($this->currentNode) !== true) { - Assert::fail('The node authorization service did not return true!'); - } - } else { - if ($this->nodeAuthorizationService->isGrantedToEditNode($this->currentNode) !== false) { - Assert::fail('The node authorization service did not return false!'); - } - } - } - } - - /** - * @Given /^I should get (true|false) when asking the node authorization service if editing the "([^"]*)" property is granted$/ - */ - public function iShouldGetTrueWhenAskingTheNodeAuthorizationServiceIfEditingThePropertyIsGranted( - $expectedResult, - $propertyName - ) { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s %s %s', - 'string', - escapeshellarg(trim($expectedResult)), - 'string', - escapeshellarg($propertyName) - ) - ); - } elseif ($expectedResult === 'true') { - if ($this->nodeAuthorizationService->isGrantedToEditNodeProperty( - $this->currentNode, - $propertyName - ) !== true) { - Assert::fail('The node authorization service did not return true!'); - } - } elseif ($this->nodeAuthorizationService->isGrantedToEditNodeProperty( - $this->currentNode, - $propertyName - ) !== false) { - Assert::fail('The node authorization service did not return false!'); - } - } - - /** - * @param TableNode $table - * @Then /^I should get the following list of denied node properties from the node authorization service:$/ - */ - public function iShouldGetTheFollowingListOfDeniedNodePropertiesFromTheNodeAuthorizationService($table) - { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s', - escapeshellarg(TableNode::class), - escapeshellarg(json_encode($table->getHash())) - ) - ); - } else { - $rows = $table->getHash(); - $deniedPropertyNames = $this->nodeAuthorizationService->getDeniedNodePropertiesForEditing( - $this->currentNode - ); - - if (count($rows) !== count($deniedPropertyNames)) { - Assert::fail( - 'The node authorization service did not return the expected amount of node property names! Got: ' . implode( - ', ', - $deniedPropertyNames - ) - ); - } - - foreach ($rows as $row) { - if (in_array($row['propertyName'], $deniedPropertyNames) === false) { - Assert::fail( - 'The following property name has not been returned by the node authorization service: ' . $row['propertyName'] - ); - } - } - } - } - - /** - * @param string $not - * @throws AccessDeniedException - * @Then /^I should (not )?be granted to set any of the node's attributes$/ - */ - public function iShouldNotBeGrantedToSetAnyOfTheNodesAttributes($not = '') - { - if ($this->isolated === true) { - $this->callStepInSubProcess(__METHOD__, sprintf(' %s %s', 'string', escapeshellarg(trim($not)))); - } else { - try { - $this->currentNode->setName('some-new-name'); - if ($not === 'not') { - Assert::fail('Name should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->removeProperty('title'); - if ($not === 'not') { - Assert::fail('Title should not be removable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->setContentObject($this->currentNode->getNodeData()); - if ($not === 'not') { - Assert::fail('Content object should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->unsetContentObject(); - if ($not === 'not') { - Assert::fail('Content object should not be unsettable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $nodeTypeManager = $this->getObjectManager()->get(NodeTypeManager::class); - $this->currentNode->setNodeType($nodeTypeManager->getNodeType('Neos.Neos:Node')); - if ($not === 'not') { - Assert::fail('NodeType should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->setHidden(true); - if ($not === 'not') { - Assert::fail('Hidden flag should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->setHiddenBeforeDateTime(new \DateTime()); - if ($not === 'not') { - Assert::fail('Hidden before should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->setHiddenAfterDateTime(new \DateTime()); - if ($not === 'not') { - Assert::fail('Hidden after should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->setHiddenInIndex(true); - if ($not === 'not') { - Assert::fail('Hidden in index should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - - try { - $this->currentNode->setAccessRoles([]); - if ($not === 'not') { - Assert::fail('Access roles in index should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - } - } - - /** - * @param string $not - * @param string $nodeName - * @param string $nodeType - * @throws \Exception - * @Then /^I should (not )?be granted to create a new "([^"]*)" child node of type "([^"]*)"$/ - */ - public function iShouldNotBeGrantedToCreateANewChildNodeOfType($not, $nodeName, $nodeType) - { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s %s %s %s %s', - 'string', - escapeshellarg(trim($not)), - 'string', - escapeshellarg($nodeName), - 'string', - escapeshellarg($nodeType) - ) - ); - } else { - /** @var NodeTypeManager $nodeTypeManager */ - $nodeTypeManager = $this->getObjectManager()->get(NodeTypeManager::class); - - try { - $this->currentNode->createNode($nodeName, $nodeTypeManager->getNodeType($nodeType)); - if ($not === 'not') { - Assert::fail('Should not be able to create a child node of type "' . $nodeType . '"!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - } - } - - /** - * @param string $expectedResult - * @param string $nodeName - * @param string $nodeTypeName - * @throws NodeTypeNotFoundException - * @Given /^I should get (true|false) when asking the node authorization service if creating a new "([^"]*)" child node of type "([^"]*)" is granted$/ - */ - public function iShouldGetFalseWhenAskingTheNodeAuthorizationServiceIfCreatingAChildNodeOfTypeIsGranted( - $expectedResult, - $nodeName, - $nodeTypeName - ) { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s %s %s %s %s', - 'string', - escapeshellarg(trim($expectedResult)), - 'string', - escapeshellarg($nodeName), - 'string', - escapeshellarg($nodeTypeName) - ) - ); - } else { - /** @var NodeTypeManager $nodeTypeManager */ - $nodeTypeManager = $this->getObjectManager()->get(NodeTypeManager::class); - $nodeType = $nodeTypeManager->getNodeType($nodeTypeName); - - if ($expectedResult === 'true') { - if ($this->nodeAuthorizationService->isGrantedToCreateNode( - $this->currentNode, - $nodeType - ) !== true) { - Assert::fail('The node authorization service did not return true!'); - } - } else { - if ($this->nodeAuthorizationService->isGrantedToCreateNode( - $this->currentNode, - $nodeType - ) !== false) { - Assert::fail('The node authorization service did not return false!'); - } - } - } - } - - /** - * @Then /^I should get the following list of denied node types for this node from the node authorization service:$/ - */ - public function iShouldGetTheFollowingListOfDeniedNodeTypesForThisNodeFromTheNodeAuthorizationService($table) - { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s', - escapeshellarg(TableNode::class), - escapeshellarg(json_encode($table->getHash())) - ) - ); - } else { - $rows = $table->getHash(); - $deniedNodeTypeNames = $this->nodeAuthorizationService->getNodeTypeNamesDeniedForCreation( - $this->currentNode - ); - - if (count($rows) !== count($deniedNodeTypeNames)) { - Assert::fail( - 'The node authorization service did not return the expected amount of node type names! Got: ' . implode( - ', ', - $deniedNodeTypeNames - ) - ); - } - - foreach ($rows as $row) { - if (in_array($row['nodeTypeName'], $deniedNodeTypeNames) === false) { - Assert::fail( - 'The following node type name has not been returned by the node authorization service: ' . $row['nodeTypeName'] - ); - } - } - } - } - - /** - * @Then /^I should get the list of all available node types as denied node types for this node from the node authorization service$/ - */ - public function iShouldGetTheListOfAllAvailableNodeTypesAsDeniedNodeTypesForThisNodeFromTheNodeAuthorizationService( - ) - { - if ($this->isolated === true) { - $this->callStepInSubProcess(__METHOD__); - } else { - $availableNodeTypes = $this->nodeTypeManager->getNodeTypes(); - $deniedNodeTypeNames = $this->nodeAuthorizationService->getNodeTypeNamesDeniedForCreation( - $this->currentNode - ); - - if (count($availableNodeTypes) !== count($deniedNodeTypeNames)) { - Assert::fail( - 'The node authorization service did not return the expected amount of node type names! Got: ' . implode( - ', ', - $deniedNodeTypeNames - ) - ); - } - - foreach ($availableNodeTypes as $nodeType) { - if (in_array($nodeType, $deniedNodeTypeNames) === false) { - Assert::fail( - 'The following node type name has not been returned by the node authorization service: ' . $nodeType - ); - } - } - } - } - - - /** - * @param string $not - * @Then /^I should (not )?be granted to remove the node$/ - */ - public function iShouldNotBeGrantedToRemoveTheNode($not = '') - { - if ($this->isolated === true) { - $this->callStepInSubProcess(__METHOD__, sprintf(' %s %s', 'string', escapeshellarg(trim($not)))); - } else { - try { - $this->currentNode->remove(); - if ($not === 'not') { - Assert::fail('Name should not be settable on the current node!'); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - } - } - - /** - * @param string $expectedResult - * @Given /^I should get (true|false) when asking the node authorization service if removal of the node is granted$/ - */ - public function iShouldGetFalseWhenAskingTheNodeAuthorizationServiceIfRemovalOfTheNodeIsGranted($expectedResult) - { - if ($this->isolated === true) { - $this->callStepInSubProcess(__METHOD__, sprintf(' %s %s', 'string', escapeshellarg(trim($expectedResult)))); - } else { - if ($expectedResult === 'true') { - if ($this->nodeAuthorizationService->isGrantedToRemoveNode($this->currentNode) !== true) { - Assert::fail('The node authorization service did not return true!'); - } - } else { - if ($this->nodeAuthorizationService->isGrantedToRemoveNode($this->currentNode) !== false) { - Assert::fail('The node authorization service did not return false!'); - } - } - } - } - - /** - * @Then /^I should (not )?be granted to get the "([^"]*)" property$/ - */ - public function iShouldNotBeGrantedToGetTheProperty($not, $propertyName) - { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf(' %s %s %s %s', 'string', escapeshellarg(trim($not)), 'string', escapeshellarg($propertyName)) - ); - } else { - /** @var Node $currentNode */ - $currentNode = $this->currentNode; - try { - switch ($propertyName) { - case 'name': - $propertyValue = $currentNode->getName(); - break; - case 'hidden': - $propertyValue = $currentNode->isHidden(); - break; - case 'hiddenBeforeDateTime': - $propertyValue = $currentNode->getHiddenBeforeDateTime(); - break; - case 'hiddenAfterDateTime': - $propertyValue = $currentNode->getHiddenAfterDateTime(); - break; - case 'hiddenInIndex': - $propertyValue = $currentNode->isHiddenInIndex(); - break; - case 'accessRoles': - $propertyValue = $currentNode->getAccessRoles(); - break; - default: - $propertyValue = $currentNode->getProperty($propertyName); - break; - } - if ($not === 'not') { - Assert::fail( - 'Property should not be gettable on the current node! But we could read the value: "' . $propertyValue . '"' - ); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - } - } - - /** - * @Given /^I should get (true|false) when asking the node authorization service if getting the "([^"]*)" property is granted$/ - */ - public function iShouldGetFalseWhenAskingTheNodeAuthorizationServiceIfGettingThePropertyIsGranted( - $expectedResult, - $propertyName - ) { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s %s %s', - 'string', - escapeshellarg(trim($expectedResult)), - 'string', - escapeshellarg($propertyName) - ) - ); - } elseif ($expectedResult === 'true') { - if ($this->nodeAuthorizationService->isGrantedToReadNodeProperty( - $this->currentNode, - $propertyName - ) !== true) { - Assert::fail('The node authorization service did not return true!'); - } - } elseif ($this->nodeAuthorizationService->isGrantedToReadNodeProperty( - $this->currentNode, - $propertyName - ) !== false) { - Assert::fail('The node authorization service did not return false!'); - } - } - - /** - * @Then /^I should (not )?be granted to set the "([^"]*)" property to "([^"]*)"$/ - */ - public function iShouldNotBeGrantedToSetThePropertyTo($not, $propertyName, $value) - { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s %s %s %s %s', - 'string', - escapeshellarg(trim($not)), - 'string', - escapeshellarg($propertyName), - 'string', - escapeshellarg($value) - ) - ); - } else { - /** @var Node $currentNode */ - $currentNode = $this->currentNode; - try { - switch ($propertyName) { - case 'name': - $currentNode->setName($value); - break; - case 'hidden': - $currentNode->setHidden($value); - break; - case 'hiddenBeforeDateTime': - $currentNode->setHiddenBeforeDateTime(new \DateTime($value)); - break; - case 'hiddenAfterDateTime': - $currentNode->setHiddenAfterDateTime(new \DateTime($value)); - break; - case 'hiddenInIndex': - $currentNode->setHiddenInIndex($value); - break; - case 'accessRoles': - $currentNode->setAccessRoles([$value]); - break; - default: - $currentNode->setProperty($propertyName, $value); - break; - } - if ($not === 'not') { - Assert::fail( - 'Property should not be settable on the current node! But we could set the value of "' . $propertyName . '" to "' . $value . '"' - ); - } - } catch (AccessDeniedException $exception) { - if ($not !== 'not') { - throw $exception; - } - } - } - } - - /** - * @Given /^I should get (true|false) when asking the node authorization service if setting the "([^"]*)" property is granted$/ - */ - public function iShouldGetFalseWhenAskingTheNodeAuthorizationServiceIfSettingThePropertyIsGranted( - $expectedResult, - $propertyName - ) { - if ($this->isolated === true) { - $this->callStepInSubProcess( - __METHOD__, - sprintf( - ' %s %s %s %s', - 'string', - escapeshellarg(trim($expectedResult)), - 'string', - escapeshellarg($propertyName) - ) - ); - } elseif ($expectedResult === 'true') { - if ($this->nodeAuthorizationService->isGrantedToEditNodeProperty( - $this->currentNode, - $propertyName - ) !== true) { - Assert::fail('The node authorization service did not return true!'); - } - } elseif ($this->nodeAuthorizationService->isGrantedToEditNodeProperty( - $this->currentNode, - $propertyName - ) !== false) { - Assert::fail('The node authorization service did not return false!'); - } - } -} diff --git a/Neos.ContentRepository.Security/composer.json b/Neos.ContentRepository.Security/composer.json deleted file mode 100644 index 35f704ed157..00000000000 --- a/Neos.ContentRepository.Security/composer.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "name": "neos/contentrepository-security", - "type": "neos-package", - "description": "Event sourced Site and Workspace for Neos.", - "license": [ - "GPL-3.0-or-later" - ], - "require": { - "neos/neos": "*", - "neos/neos-ui": "*" - }, - "autoload": { - "psr-4": { - "Neos\\ContentRepository\\Security\\": "Classes" - } - }, - "extra": { - "applied-flow-migrations": [ - "TYPO3.TYPO3CR-20150510103823", - "TYPO3.FLOW3-201201261636", - "TYPO3.Fluid-201205031303", - "TYPO3.FLOW3-201205292145", - "TYPO3.FLOW3-201206271128", - "TYPO3.Flow-201211151101", - "TYPO3.Neos.NodeTypes-130516220640", - "TYPO3.TypoScript-130516234520", - "TYPO3.TypoScript-130516235550", - "TYPO3.TYPO3CR-130523180140", - "TYPO3.Neos.NodeTypes-201309111655", - "TYPO3.Neos-201310021548", - "TYPO3.Flow-201310031523", - "TYPO3.Flow-201405111147", - "TYPO3.Neos-201409071922", - "TYPO3.TYPO3CR-140911160326", - "TYPO3.Neos-201410010000", - "TYPO3.TYPO3CR-141101082142", - "TYPO3.Neos-20141113115300", - "TYPO3.Fluid-20141121091700", - "TYPO3.Neos-20141218134700", - "TYPO3.Fluid-20150214130800", - "TYPO3.Neos-201407061038", - "TYPO3.Flow-201212051340", - "TYPO3.Fluid-20141113120800", - "TYPO3.Flow-20141113121400", - "Typo3.Neos.NodeTypes-201309111655", - "TYPO3.TYPO3CR-20140911160326", - "TYPO3.Flow-201209251426", - "TYPO3.FLOW3-201209201112", - "TYPO3.Neos-20150303231600", - "TYPO3.Flow-20151113161300", - "TYPO3.Form-20160601101500", - "TYPO3.Flow-20161115140400", - "TYPO3.Flow-20161115140430", - "Neos.Flow-20161124204700", - "Neos.Flow-20161124204701", - "Neos.Twitter.Bootstrap-20161124204912", - "Neos.Form-20161124205254", - "Neos.Flow-20161124224015", - "Neos.Party-20161124225257", - "Neos.Eel-20161124230101", - "Neos.Kickstart-20161124230102", - "Neos.Setup-20161124230842", - "Neos.Imagine-20161124231742", - "Neos.Media-20161124233100", - "Neos.NodeTypes-20161125002300", - "Neos.SiteKickstarter-20161125002311", - "Neos.Neos-20161125002322", - "Neos.ContentRepository-20161125012000", - "Neos.Fusion-20161125013710", - "Neos.Setup-20161125014759", - "Neos.SiteKickstarter-20161125095901", - "Neos.Fusion-20161125104701", - "Neos.NodeTypes-20161125104800", - "Neos.Neos-20161125104802", - "Neos.Kickstarter-20161125110814", - "Neos.Flow-20161125124112", - "Neos.Neos-20161125122412", - "TYPO3.FluidAdaptor-20161130112935", - "Neos.Fusion-20161201202543", - "Neos.Neos-20161201222211", - "Neos.Fusion-20161202215034", - "Neos.ContentRepository-20161219093512", - "Neos.Fusion-20170120013047", - "Neos.Flow-20180415105700", - "Neos.Fusion-20161219092345", - "Neos.Media-20161219094126", - "Neos.Neos-20161219094403", - "Neos.Neos-20161219122512", - "Neos.Fusion-20161219130100", - "Neos.Neos-20161220163741", - "Neos.Neos-20170115114620", - "Neos.Flow-20170125103800", - "Neos.Seo-20170127154600", - "Neos.Flow-20170127183102", - "Neos.Fusion-20180211175500", - "Neos.Fusion-20180211184832" - ] - } -} diff --git a/Neos.Neos/Classes/Controller/Backend/MenuHelper.php b/Neos.Neos/Classes/Controller/Backend/MenuHelper.php index 75ad026b9e1..5f9b0415c9c 100644 --- a/Neos.Neos/Classes/Controller/Backend/MenuHelper.php +++ b/Neos.Neos/Classes/Controller/Backend/MenuHelper.php @@ -12,23 +12,17 @@ * source code. */ -use Neos\ContentRepository\Security\Authorization\Privilege\Node\NodePrivilegeSubject; -use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; use Neos\Flow\Http\Exception; use Neos\Flow\Mvc\Controller\ControllerContext; use Neos\Flow\Mvc\Routing\Exception\MissingActionNameException; use Neos\Flow\Security\Authorization\PrivilegeManagerInterface; -use Neos\Neos\Domain\Service\ContentContextFactory; -use Neos\Neos\Domain\Service\SiteService; -use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult; +use Neos\Neos\Domain\Model\Site; +use Neos\Neos\Domain\Repository\SiteRepository; use Neos\Neos\Security\Authorization\Privilege\ModulePrivilege; use Neos\Neos\Security\Authorization\Privilege\ModulePrivilegeSubject; -use Neos\Neos\Security\Authorization\Privilege\NodeTreePrivilege; use Neos\Neos\Service\IconNameMappingService; use Neos\Utility\Arrays; -use Neos\Neos\Domain\Model\Site; -use Neos\Neos\Domain\Repository\SiteRepository; use Neos\Utility\PositionalArraySorter; /** diff --git a/Neos.Neos/Classes/Security/Authorization/Privilege/NodeTreePrivilege.php b/Neos.Neos/Classes/Security/Authorization/Privilege/NodeTreePrivilege.php deleted file mode 100644 index 9ccd5bff3ae..00000000000 --- a/Neos.Neos/Classes/Security/Authorization/Privilege/NodeTreePrivilege.php +++ /dev/null @@ -1,25 +0,0 @@ -nodeAuthorizationService->isGrantedToEditNode($node) === true); + /* TODO: permissions || $this->nodeAuthorizationService->isGrantedToEditNode($node) === true */); } private function isContentStreamOfLiveWorkspace( diff --git a/Neos.Neos/Tests/Unit/Service/ContentElementEditableServiceTest.php b/Neos.Neos/Tests/Unit/Service/ContentElementEditableServiceTest.php index 6242bf9767f..30284b7c987 100644 --- a/Neos.Neos/Tests/Unit/Service/ContentElementEditableServiceTest.php +++ b/Neos.Neos/Tests/Unit/Service/ContentElementEditableServiceTest.php @@ -15,8 +15,6 @@ use Neos\Flow\Security\Authorization\PrivilegeManagerInterface; use Neos\Flow\Tests\UnitTestCase; use Neos\Fusion\Service\HtmlAugmenter; -use Neos\Neos\Domain\Service\ContentContext; -use Neos\ContentRepository\Security\Service\AuthorizationService; use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\Fusion\Core\Runtime; use Neos\Neos\Service\ContentElementEditableService; @@ -36,11 +34,6 @@ class ContentElementEditableServiceTest extends UnitTestCase */ protected $mockPrivilegeManager; - /** - * @var AuthorizationService - */ - protected $mockNodeAuthorizationService; - /** * @var HtmlAugmenter */ diff --git a/Neos.Neos/Tests/Unit/ViewHelpers/ContentElement/EditableViewHelperTest.php b/Neos.Neos/Tests/Unit/ViewHelpers/ContentElement/EditableViewHelperTest.php index 0f1d146e133..388659bbcc7 100644 --- a/Neos.Neos/Tests/Unit/ViewHelpers/ContentElement/EditableViewHelperTest.php +++ b/Neos.Neos/Tests/Unit/ViewHelpers/ContentElement/EditableViewHelperTest.php @@ -16,9 +16,7 @@ use Neos\FluidAdaptor\Tests\Unit\ViewHelpers\ViewHelperBaseTestcase; use Neos\Flow\Security\Authorization\PrivilegeManagerInterface; use Neos\FluidAdaptor\Core\ViewHelper\AbstractViewHelper; -use Neos\Neos\Domain\Service\ContentContext; use Neos\Neos\ViewHelpers\ContentElement\EditableViewHelper; -use Neos\ContentRepository\Security\Service\AuthorizationService; use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\Fusion\Core\Runtime; use Neos\Fusion\FusionObjects\Helpers\FluidView; @@ -40,11 +38,6 @@ class EditableViewHelperTest extends ViewHelperBaseTestcase */ protected $mockPrivilegeManager; - /** - * @var AuthorizationService - */ - protected $mockNodeAuthorizationService; - /** * @var TemplateImplementation */ diff --git a/composer.json b/composer.json index 182650ba9e5..1c558eff5f0 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,6 @@ "neos/contentrepository-legacynodemigration": "self.version", "neos/contentrepository-nodeaccess": "self.version", "neos/contentrepository-nodemigration": "self.version", - "neos/contentrepository-security": "self.version", "neos/contentrepository-structureadjustment": "self.version", "neos/contentrepository-testsuite": "self.version", "neos/contentrepositoryregistry": "self.version", @@ -156,9 +155,6 @@ "Neos\\ContentRepository\\NodeMigration\\": [ "Neos.ContentRepository.NodeMigration/src" ], - "Neos\\ContentRepository\\Security\\": [ - "Neos.ContentRepository.Security/Classes" - ], "Neos\\ContentRepository\\StructureAdjustment\\": [ "Neos.ContentRepository.StructureAdjustment/src" ], diff --git a/phpstan.neon b/phpstan.neon index 2296b6cc8f4..f86c15823ee 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -6,7 +6,6 @@ parameters: - Neos.ContentRepository.BehavioralTests/Classes - Neos.ContentRepository.TestSuite/Classes - Neos.ContentRepository.Core/Classes - - Neos.ContentRepository.Security/Classes - Neos.Neos/Classes excludePaths: analyse: