Skip to content

Instantly share code, notes, and snippets.

@Sebobo
Created October 22, 2020 07:23
Show Gist options
  • Save Sebobo/2fde5f0b2eebfacda41fe2a06dedb14c to your computer and use it in GitHub Desktop.
Save Sebobo/2fde5f0b2eebfacda41fe2a06dedb14c to your computer and use it in GitHub Desktop.
Modified ReadNodePrivilege for Neos CMS to restrict access to pages with subpages

Please read

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.

<?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;
}
}
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'
<?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').')';
}
}
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
<?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