These classes and configurations allow defining an access restriction to pages & content in Neos. But the current implementation adds the acl related query to all queries against the content repository, which slows down queries. So please use carefully in your project or help finding a better solution.
Created
October 22, 2020 07:23
-
-
Save Sebobo/2fde5f0b2eebfacda41fe2a06dedb14c to your computer and use it in GitHub Desktop.
Modified ReadNodePrivilege for Neos CMS to restrict access to pages with subpages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace My\Vendor\Security\Authorization\Privilege\Node\Doctrine; | |
use Neos\Flow\Security\Authorization\Privilege\Entity\Doctrine\FalseConditionGenerator; | |
use Neos\Flow\Security\Authorization\Privilege\Entity\Doctrine\PropertyConditionGenerator; | |
use Neos\Flow\Security\Authorization\Privilege\Entity\Doctrine\SqlGeneratorInterface; | |
/** | |
* {@inheritdoc} | |
*/ | |
class ConditionGenerator extends \Neos\ContentRepository\Security\Authorization\Privilege\Node\Doctrine\ConditionGenerator | |
{ | |
/** | |
* @param string $property | |
* @param mixed $value | |
* @return SqlGeneratorInterface | |
*/ | |
public function nodePropertyIs($property, $value): SqlGeneratorInterface | |
{ | |
$propertyConditionGenerator = new PropertyConditionGenerator('properties'); | |
if (!is_string($property) || is_array($value)) { | |
return new FalseConditionGenerator(); | |
} | |
return $propertyConditionGenerator->like('%"' . trim($property) . '": ' . json_encode($value) . '%'); | |
} | |
/** | |
* @param string $property | |
* @param mixed $value | |
* @return SqlGeneratorInterface | |
*/ | |
public function parentNodePropertyIs($property, $value): SqlGeneratorInterface | |
{ | |
$propertiesConditionGenerator = $this->nodePropertyIs($property, $value); | |
$subqueryGenerator = new ParentNodePropertyGenerator($propertiesConditionGenerator); | |
return $subqueryGenerator; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
My.Vendor:Mixin.Acl: | |
abstract: true | |
properties: | |
accessRestriction: | |
type: string | |
ui: | |
label: 'Restricted to group' | |
inspector: | |
group: 'visibility' | |
editor: 'Neos.Neos/Inspector/Editors/SelectBoxEditor' | |
editorOptions: | |
values: | |
'': | |
label: 'Not restricted' | |
'loggedInUsers': | |
label: 'Logged in users' | |
icon: 'icon-user' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace My\Vendor\Security\Authorization\Privilege\Node\Doctrine; | |
use Doctrine\Common\Persistence\Mapping\ClassMetadata; | |
use Doctrine\ORM\Query\Filter\SQLFilter as DoctrineSqlFilter; | |
use Neos\Flow\Security\Authorization\Privilege\Entity\Doctrine\SqlGeneratorInterface; | |
/** | |
* A sql generator to create a sql subquery. | |
*/ | |
class ParentNodePropertyGenerator implements SqlGeneratorInterface | |
{ | |
/** | |
* @var SqlGeneratorInterface | |
*/ | |
protected $expression; | |
/** | |
* @param SqlGeneratorInterface $expression | |
*/ | |
public function __construct($expression) | |
{ | |
$this->expression = $expression; | |
} | |
/** | |
* @param DoctrineSqlFilter $sqlFilter | |
* @param ClassMetadata $targetEntity Metadata object for the target entity to create the constraint for | |
* @param string $targetTableAlias The target table alias used in the current query | |
* | |
* @return string | |
*/ | |
public function getSql(DoctrineSqlFilter $sqlFilter, ClassMetadata $targetEntity, $targetTableAlias) | |
{ | |
return '( | |
SELECT COUNT(*) FROM neos_contentrepository_domain_model_nodedata as parent | |
WHERE '.$targetTableAlias.'.path LIKE CONCAT(parent.path, "%") | |
AND '.$this->expression->getSql($sqlFilter, $targetEntity, 'parent').')'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
privilegeTargets: | |
'My\Vendor\Security\Authorization\Privilege\Node\ReadNodePrivilege': | |
'My.Vendor:RestrictNodeToLoggedInUsers': | |
matcher: 'nodePropertyIs("accessRestriction", "loggedInUser") || parentNodePropertyIs("accessRestriction", "loggedInUser")' | |
roles: | |
'My.Vendor:Patient': | |
privileges: | |
- privilegeTarget: 'My.Vendor:RestrictNodeToLoggedInUsers' | |
permission: GRANT | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace My\Vendor\Security\Authorization\Privilege\Node; | |
use My\Vendor\Security\Authorization\Privilege\Node\Doctrine\ConditionGenerator; | |
/** | |
* {@inheritdoc} | |
*/ | |
class ReadNodePrivilege extends \Neos\ContentRepository\Security\Authorization\Privilege\Node\ReadNodePrivilege | |
{ | |
/** | |
* {@inheritdoc} | |
* | |
* @return ConditionGenerator | |
*/ | |
protected function getConditionGenerator() | |
{ | |
return new ConditionGenerator(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment