Skip to content

Instantly share code, notes, and snippets.

@aertmann
Last active August 28, 2018 13:13
Show Gist options
  • Save aertmann/f92aa09c71c96ad92eb1e3e96ea9e1a3 to your computer and use it in GitHub Desktop.
Save aertmann/f92aa09c71c96ad92eb1e3e96ea9e1a3 to your computer and use it in GitHub Desktop.

Revisions

  1. aertmann revised this gist Aug 28, 2018. 1 changed file with 0 additions and 5 deletions.
    5 changes: 0 additions & 5 deletions SiteAwarePersistedUsernamePasswordProvider.php
    Original file line number Diff line number Diff line change
    @@ -51,11 +51,6 @@ class SiteAwarePersistedUsernamePasswordProvider extends PersistedUsernamePasswo
    protected $entityManager;

    /**
    * Checks if a user has access to a site by enabling entity privileges and checking if user has access to current site
    *
    * @param TokenInterface $authenticationToken The token to be authenticated
    * @return void
    */ /**
    * Checks if a user has access to a site by enabling entity privileges and checking if user has access to current site
    *
    * @param TokenInterface $authenticationToken The token to be authenticated
  2. aertmann revised this gist Aug 23, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion SiteAwarePersistedUsernamePasswordProvider.php
    Original file line number Diff line number Diff line change
    @@ -64,7 +64,7 @@ class SiteAwarePersistedUsernamePasswordProvider extends PersistedUsernamePasswo
    public function authenticate(TokenInterface $authenticationToken)
    {
    parent::authenticate($authenticationToken);
    if (!$authenticationToken->getAuthenticationStatus() === TokenInterface::AUTHENTICATION_SUCCESSFUL) {
    if ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) {
    return;
    }

  3. aertmann revised this gist Nov 6, 2017. 1 changed file with 27 additions and 12 deletions.
    39 changes: 27 additions & 12 deletions SiteAwarePersistedUsernamePasswordProvider.php
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,16 @@
    <?php
    namespace Acme\Package\Security\Authentication\Provider;

    use Doctrine\Common\Persistence\ObjectManager;
    use Doctrine\ORM\EntityNotFoundException;
    use Neos\Flow\Annotations as Flow;
    use Neos\Flow\Reflection\ObjectAccess;
    use Neos\Flow\Security\Authentication\AuthenticationManagerInterface;
    use Neos\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
    use Neos\Flow\Security\Authentication\TokenInterface;
    use Neos\Flow\Security\Policy\PolicyService;
    use Neos\Neos\Domain\Repository\DomainRepository;
    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Reflection\ObjectAccess;
    use TYPO3\Flow\Security\Authentication\AuthenticationManagerInterface;
    use TYPO3\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
    use TYPO3\Flow\Security\Authentication\TokenInterface;
    use TYPO3\Flow\Security\Policy\PolicyService;
    use TYPO3\Neos\Domain\Repository\DomainRepository;
    use TYPO3\Neos\Domain\Repository\SiteRepository;

    /**
    * A custom site aware authentication provider extending the existing persisted username password provider
    @@ -22,6 +24,12 @@ class SiteAwarePersistedUsernamePasswordProvider extends PersistedUsernamePasswo
    */
    protected $domainRepository;

    /**
    * @Flow\Inject
    * @var SiteRepository
    */
    protected $siteRepository;

    /**
    * @Flow\Inject
    * @var AuthenticationManagerInterface
    @@ -33,6 +41,14 @@ class SiteAwarePersistedUsernamePasswordProvider extends PersistedUsernamePasswo
    * @var PolicyService
    */
    protected $policyService;

    /**
    * Doctrine's Entity Manager
    *
    * @Flow\Inject
    * @var ObjectManager
    */
    protected $entityManager;

    /**
    * Checks if a user has access to a site by enabling entity privileges and checking if user has access to current site
    @@ -63,11 +79,10 @@ public function authenticate(TokenInterface $authenticationToken)
    return;
    }

    $site = $domain->getSite();
    try {
    $site->getName();
    // Site access allowed, continue
    } catch(EntityNotFoundException $e) {
    // Check if user can access site and ensure it's not already loaded
    $this->entityManager->clear('TYPO3\Neos\Domain\Model\Site');
    $site = $this->siteRepository->findByIdentifier(ObjectAccess::getProperty($domain->getSite(), 'Persistence_Object_Identifier', true));
    if (!$site) {
    $this->rollback($authenticationToken);
    }
    }
  4. aertmann revised this gist Oct 17, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion SiteAwarePersistedUsernamePasswordProvider.php
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,7 @@ public function authenticate(TokenInterface $authenticationToken)

    $domain = $this->domainRepository->findOneByActiveRequest();
    if (!$domain) {
    if (!array_key_exists('TYPO3.Neos:Administrator', $this->securityContext->getRoles())) {
    if (!array_key_exists('Neos.Neos:Administrator', $this->securityContext->getRoles())) {
    $this->rollback($authenticationToken);
    }
    return;
  5. aertmann revised this gist Oct 17, 2017. 2 changed files with 9 additions and 9 deletions.
    4 changes: 2 additions & 2 deletions Settings.yaml
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    TYPO3:
    Neos:
    Flow:
    security:
    authentication:
    providers:
    Typo3BackendProvider:
    NeosBackendProvider:
    provider: 'Acme\Package\Security\Authentication\Provider\SiteAwarePersistedUsernamePasswordProvider'
    14 changes: 7 additions & 7 deletions SiteAwarePersistedUsernamePasswordProvider.php
    Original file line number Diff line number Diff line change
    @@ -2,13 +2,13 @@
    namespace Acme\Package\Security\Authentication\Provider;

    use Doctrine\ORM\EntityNotFoundException;
    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Reflection\ObjectAccess;
    use TYPO3\Flow\Security\Authentication\AuthenticationManagerInterface;
    use TYPO3\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
    use TYPO3\Flow\Security\Authentication\TokenInterface;
    use TYPO3\Flow\Security\Policy\PolicyService;
    use TYPO3\Neos\Domain\Repository\DomainRepository;
    use Neos\Flow\Annotations as Flow;
    use Neos\Flow\Reflection\ObjectAccess;
    use Neos\Flow\Security\Authentication\AuthenticationManagerInterface;
    use Neos\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
    use Neos\Flow\Security\Authentication\TokenInterface;
    use Neos\Flow\Security\Policy\PolicyService;
    use Neos\Neos\Domain\Repository\DomainRepository;

    /**
    * A custom site aware authentication provider extending the existing persisted username password provider
  6. aertmann revised this gist Oct 13, 2017. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions Settings.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    TYPO3:
    Flow:
    security:
    authentication:
    providers:
    Typo3BackendProvider:
    provider: 'Acme\Package\Security\Authentication\Provider\SiteAwarePersistedUsernamePasswordProvider'
  7. aertmann revised this gist Oct 13, 2017. 1 changed file with 0 additions and 85 deletions.
    85 changes: 0 additions & 85 deletions UserInformationContext.php
    Original file line number Diff line number Diff line change
    @@ -1,85 +0,0 @@
    <?php
    namespace Acme\Package\Security;

    use Admhuset\RealEstateWebsites\Domain\Model\Site;
    use Admhuset\RealEstateWebsites\Domain\Repository\SiteRepository;
    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Cache\CacheAwareInterface;
    use TYPO3\Flow\Persistence\PersistenceManagerInterface;
    use TYPO3\Flow\Security\Account;
    use TYPO3\Flow\Security\Context;
    use TYPO3\Neos\Domain\Model\User;
    use TYPO3\Party\Domain\Service\PartyService;

    /**
    * @Flow\Scope("singleton")
    */
    class UserInformationContext implements CacheAwareInterface {

    /**
    * @Flow\Inject
    * @var SiteRepository
    */
    protected $siteRepository;

    /**
    * @Flow\Inject
    * @var Context
    */
    protected $securityContext;

    /**
    * @Flow\Inject
    * @var PersistenceManagerInterface
    */
    protected $persistenceManager;

    /**
    * @Flow\Inject
    * @var PartyService
    */
    protected $partyService;

    /**
    * @return Account
    */
    public function getAccount() {
    return $this->securityContext->getAccount();
    }

    /**
    * @return User
    */
    public function getUser() {
    $account = $this->getAccount();
    if (!$account) {
    return NULL;
    }
    /** @var User $user */
    $user = $this->partyService->getAssignedPartyOfAccount($account);
    return $user;
    }

    /**
    * @return Site
    */
    public function getSite() {
    $user = $this->getUser();
    if (!$user) {
    return NULL;
    }
    return $this->siteRepository->findOneByUser($user);
    }

    /**
    * @return string
    */
    public function getCacheEntryIdentifier() {
    $account = $this->getAccount();
    if (!$account) {
    return NULL;
    }
    return $this->persistenceManager->getIdentifierByObject($account);
    }

    }
  8. aertmann revised this gist Oct 13, 2017. 1 changed file with 0 additions and 9 deletions.
    9 changes: 0 additions & 9 deletions Policy.yaml
    Original file line number Diff line number Diff line change
    @@ -1,9 +0,0 @@
    privilegeTargets:

    'TYPO3\Neos\Security\Authorization\Privilege\NodeTreePrivilege':

    'Acme.Package:Nodes.Alpha':
    matcher: 'isDescendantNodeOf("/sites/alpha")'

    'Acme.Package:Nodes.Beta':
    matcher: 'isDescendantNodeOf("/sites/beta")'
  9. aertmann revised this gist Oct 13, 2017. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions Policy.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    privilegeTargets:

    'TYPO3\Neos\Security\Authorization\Privilege\NodeTreePrivilege':

    'Acme.Package:Nodes.Alpha':
    matcher: 'isDescendantNodeOf("/sites/alpha")'

    'Acme.Package:Nodes.Beta':
    matcher: 'isDescendantNodeOf("/sites/beta")'
  10. aertmann revised this gist Oct 13, 2017. 1 changed file with 85 additions and 0 deletions.
    85 changes: 85 additions & 0 deletions UserInformationContext.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    <?php
    namespace Acme\Package\Security;

    use Admhuset\RealEstateWebsites\Domain\Model\Site;
    use Admhuset\RealEstateWebsites\Domain\Repository\SiteRepository;
    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Cache\CacheAwareInterface;
    use TYPO3\Flow\Persistence\PersistenceManagerInterface;
    use TYPO3\Flow\Security\Account;
    use TYPO3\Flow\Security\Context;
    use TYPO3\Neos\Domain\Model\User;
    use TYPO3\Party\Domain\Service\PartyService;

    /**
    * @Flow\Scope("singleton")
    */
    class UserInformationContext implements CacheAwareInterface {

    /**
    * @Flow\Inject
    * @var SiteRepository
    */
    protected $siteRepository;

    /**
    * @Flow\Inject
    * @var Context
    */
    protected $securityContext;

    /**
    * @Flow\Inject
    * @var PersistenceManagerInterface
    */
    protected $persistenceManager;

    /**
    * @Flow\Inject
    * @var PartyService
    */
    protected $partyService;

    /**
    * @return Account
    */
    public function getAccount() {
    return $this->securityContext->getAccount();
    }

    /**
    * @return User
    */
    public function getUser() {
    $account = $this->getAccount();
    if (!$account) {
    return NULL;
    }
    /** @var User $user */
    $user = $this->partyService->getAssignedPartyOfAccount($account);
    return $user;
    }

    /**
    * @return Site
    */
    public function getSite() {
    $user = $this->getUser();
    if (!$user) {
    return NULL;
    }
    return $this->siteRepository->findOneByUser($user);
    }

    /**
    * @return string
    */
    public function getCacheEntryIdentifier() {
    $account = $this->getAccount();
    if (!$account) {
    return NULL;
    }
    return $this->persistenceManager->getIdentifierByObject($account);
    }

    }
  11. aertmann created this gist Oct 13, 2017.
    86 changes: 86 additions & 0 deletions SiteAwarePersistedUsernamePasswordProvider.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    <?php
    namespace Acme\Package\Security\Authentication\Provider;

    use Doctrine\ORM\EntityNotFoundException;
    use TYPO3\Flow\Annotations as Flow;
    use TYPO3\Flow\Reflection\ObjectAccess;
    use TYPO3\Flow\Security\Authentication\AuthenticationManagerInterface;
    use TYPO3\Flow\Security\Authentication\Provider\PersistedUsernamePasswordProvider;
    use TYPO3\Flow\Security\Authentication\TokenInterface;
    use TYPO3\Flow\Security\Policy\PolicyService;
    use TYPO3\Neos\Domain\Repository\DomainRepository;

    /**
    * A custom site aware authentication provider extending the existing persisted username password provider
    */
    class SiteAwarePersistedUsernamePasswordProvider extends PersistedUsernamePasswordProvider
    {

    /**
    * @Flow\Inject
    * @var DomainRepository
    */
    protected $domainRepository;

    /**
    * @Flow\Inject
    * @var AuthenticationManagerInterface
    */
    protected $authenticationManager;

    /**
    * @Flow\Inject
    * @var PolicyService
    */
    protected $policyService;

    /**
    * Checks if a user has access to a site by enabling entity privileges and checking if user has access to current site
    *
    * @param TokenInterface $authenticationToken The token to be authenticated
    * @return void
    */ /**
    * Checks if a user has access to a site by enabling entity privileges and checking if user has access to current site
    *
    * @param TokenInterface $authenticationToken The token to be authenticated
    * @return void
    */
    public function authenticate(TokenInterface $authenticationToken)
    {
    parent::authenticate($authenticationToken);
    if (!$authenticationToken->getAuthenticationStatus() === TokenInterface::AUTHENTICATION_SUCCESSFUL) {
    return;
    }

    // Force set isAuthenticated to true on authentication manager to update roles needed for entity privileges
    ObjectAccess::setProperty($this->authenticationManager, 'isAuthenticated', true, true);

    $domain = $this->domainRepository->findOneByActiveRequest();
    if (!$domain) {
    if (!array_key_exists('TYPO3.Neos:Administrator', $this->securityContext->getRoles())) {
    $this->rollback($authenticationToken);
    }
    return;
    }

    $site = $domain->getSite();
    try {
    $site->getName();
    // Site access allowed, continue
    } catch(EntityNotFoundException $e) {
    $this->rollback($authenticationToken);
    }
    }

    /**
    * @param TokenInterface $authenticationToken
    * @return void
    */
    protected function rollback(TokenInterface $authenticationToken)
    {
    $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS);
    ObjectAccess::setProperty($this->authenticationManager, 'isAuthenticated', false, true);
    $this->policyService->reset();
    $this->securityContext->refreshRoles();
    }
    }