vendor/ezsystems/ezpublish-kernel/eZ/Publish/Core/Repository/Permission/CachedPermissionService.php line 142

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright Copyright (C) eZ Systems AS. All rights reserved.
  4.  * @license For full copyright and license information view LICENSE file distributed with this source code.
  5.  */
  6. namespace eZ\Publish\Core\Repository\Permission;
  7. use eZ\Publish\API\Repository\PermissionResolver as APIPermissionResolver;
  8. use eZ\Publish\API\Repository\PermissionCriterionResolver as APIPermissionCriterionResolver;
  9. use eZ\Publish\API\Repository\Repository as RepositoryInterface;
  10. use eZ\Publish\API\Repository\Values\User\LookupLimitationResult;
  11. use eZ\Publish\API\Repository\Values\User\UserReference;
  12. use eZ\Publish\API\Repository\Values\ValueObject;
  13. use Exception;
  14. /**
  15.  * Cache implementation of PermissionResolver and PermissionCriterionResolver interface.
  16.  *
  17.  * Implements both interfaces as the cached permission criterion lookup needs to be
  18.  * expired when a different user is set as current users in the system.
  19.  *
  20.  * Cache is only done for content/read policy, as that is the one needed by search service.
  21.  *
  22.  * The logic here uses a cache TTL of a few seconds, as this is in-memory cache we are not
  23.  * able to know if any other concurrent user might be changing permissions.
  24.  */
  25. class CachedPermissionService implements APIPermissionResolverAPIPermissionCriterionResolver
  26. {
  27.     /** @var \eZ\Publish\API\Repository\PermissionResolver */
  28.     private $permissionResolver;
  29.     /** @var \eZ\Publish\API\Repository\PermissionCriterionResolver */
  30.     private $permissionCriterionResolver;
  31.     /** @var int */
  32.     private $cacheTTL;
  33.     /**
  34.      * Counter for the current sudo nesting level {@see sudo()}.
  35.      *
  36.      * @var int
  37.      */
  38.     private $sudoNestingLevel 0;
  39.     /**
  40.      * Cached value for current user's getCriterion() result.
  41.      *
  42.      * Value is null if not yet set or cleared.
  43.      *
  44.      * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
  45.      */
  46.     private $permissionCriterion;
  47.     /**
  48.      * Cache time stamp.
  49.      *
  50.      * @var int
  51.      */
  52.     private $permissionCriterionTs;
  53.     /**
  54.      * CachedPermissionService constructor.
  55.      *
  56.      * @param \eZ\Publish\API\Repository\PermissionResolver $permissionResolver
  57.      * @param \eZ\Publish\API\Repository\PermissionCriterionResolver $permissionCriterionResolver
  58.      * @param int $cacheTTL By default set to 5 seconds, should be low to avoid to many permission exceptions on long running requests / processes (even if tolerant search service should handle that)
  59.      */
  60.     public function __construct(
  61.         APIPermissionResolver $permissionResolver,
  62.         APIPermissionCriterionResolver $permissionCriterionResolver,
  63.         $cacheTTL 5
  64.     ) {
  65.         $this->permissionResolver $permissionResolver;
  66.         $this->permissionCriterionResolver $permissionCriterionResolver;
  67.         $this->cacheTTL $cacheTTL;
  68.     }
  69.     public function getCurrentUserReference()
  70.     {
  71.         return $this->permissionResolver->getCurrentUserReference();
  72.     }
  73.     public function setCurrentUserReference(UserReference $userReference)
  74.     {
  75.         $this->permissionCriterion null;
  76.         return $this->permissionResolver->setCurrentUserReference($userReference);
  77.     }
  78.     public function hasAccess($module$functionUserReference $userReference null)
  79.     {
  80.         return $this->permissionResolver->hasAccess($module$function$userReference);
  81.     }
  82.     public function canUser($module$functionValueObject $object, array $targets = [])
  83.     {
  84.         return $this->permissionResolver->canUser($module$function$object$targets);
  85.     }
  86.     /**
  87.      * {@inheritdoc}
  88.      */
  89.     public function lookupLimitations(
  90.         string $module,
  91.         string $function,
  92.         ValueObject $object,
  93.         array $targets = [],
  94.         array $limitations = []
  95.     ): LookupLimitationResult {
  96.         return $this->permissionResolver->lookupLimitations($module$function$object$targets$limitations);
  97.     }
  98.     public function getPermissionsCriterion($module 'content'$function 'read', ?array $targets null)
  99.     {
  100.         // We only cache content/read lookup as those are the once frequently done, and it's only one we can safely
  101.         // do that won't harm the system if it becomes stale (but user might experience permissions exceptions if it do)
  102.         if ($module !== 'content' || $function !== 'read' || $this->sudoNestingLevel 0) {
  103.             return $this->permissionCriterionResolver->getPermissionsCriterion($module$function$targets);
  104.         }
  105.         if ($this->permissionCriterion !== null) {
  106.             // If we are still within the cache TTL, then return the cached value
  107.             if ((time() - $this->permissionCriterionTs) < $this->cacheTTL) {
  108.                 return $this->permissionCriterion;
  109.             }
  110.         }
  111.         $this->permissionCriterionTs time();
  112.         $this->permissionCriterion $this->permissionCriterionResolver->getPermissionsCriterion($module$function$targets);
  113.         return $this->permissionCriterion;
  114.     }
  115.     /**
  116.      * @internal For internal use only, do not depend on this method.
  117.      */
  118.     public function sudo(callable $callbackRepositoryInterface $outerRepository)
  119.     {
  120.         ++$this->sudoNestingLevel;
  121.         try {
  122.             $returnValue $this->permissionResolver->sudo($callback$outerRepository);
  123.         } catch (Exception $e) {
  124.             --$this->sudoNestingLevel;
  125.             throw $e;
  126.         }
  127.         --$this->sudoNestingLevel;
  128.         return $returnValue;
  129.     }
  130. }