/**
  * Gets the SQL query part to add to a query.
  *
  * @param ClassMetaData $targetEntity Metadata object for the target entity to be filtered
  * @param string $targetTableAlias The target table alias used in the current query
  * @return string The constraint SQL if there is available, empty string otherwise
  */
 public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
 {
     $this->initializeDependencies();
     /*
      * TODO: Instead of checking for class account we could introduce some interface for white listing entities from entity security checks
      * Problem with checking the Account is, that this filter calls getRoles() on the security context while accounts are not
      * yet fully initialized. By this we get a half built account object that will end up in access denied exception,
      * as it has no roles (and other properties) set
      */
     if ($this->securityContext->areAuthorizationChecksDisabled() || $targetEntity->getName() === \TYPO3\Flow\Security\Account::class) {
         return '';
     }
     if (!$this->securityContext->isInitialized()) {
         if (!$this->securityContext->canBeInitialized()) {
             return '';
         }
         $this->securityContext->initialize();
     }
     // This is needed to include the current context of roles into query cache identifier
     $this->setParameter('__contextHash', $this->securityContext->getContextHash(), 'string');
     $sqlConstraints = array();
     $grantedConstraints = array();
     $deniedConstraints = array();
     foreach ($this->securityContext->getRoles() as $role) {
         $entityPrivileges = $role->getPrivilegesByType(\TYPO3\Flow\Security\Authorization\Privilege\Entity\EntityPrivilegeInterface::class);
         /** @var EntityPrivilegeInterface $privilege */
         foreach ($entityPrivileges as $privilege) {
             if (!$privilege->matchesEntityType($targetEntity->getName())) {
                 continue;
             }
             $sqlConstraint = $privilege->getSqlConstraint($targetEntity, $targetTableAlias);
             if ($sqlConstraint === null) {
                 continue;
             }
             $sqlConstraints[] = ' NOT (' . $sqlConstraint . ')';
             if ($privilege->isGranted()) {
                 $grantedConstraints[] = ' NOT (' . $sqlConstraint . ')';
             } elseif ($privilege->isDenied()) {
                 $deniedConstraints[] = ' NOT (' . $sqlConstraint . ')';
             }
         }
     }
     $grantedConstraints = array_diff($grantedConstraints, $deniedConstraints);
     $effectiveConstraints = array_diff($sqlConstraints, $grantedConstraints);
     if (count($effectiveConstraints) > 0) {
         return ' (' . implode(') AND (', $effectiveConstraints) . ') ';
     }
     return '';
 }
 /**
  * Checks whether the current request has the same security context hash as the one of the token
  *
  * @param array $tokenData
  * @param HttpRequest $httpRequest
  * @return void
  * @throws AccessDeniedException
  */
 protected function verifySecurityContextHash(array $tokenData, HttpRequest $httpRequest)
 {
     if (!isset($tokenData['securityContextHash'])) {
         return;
     }
     /** @var $actionRequest ActionRequest */
     $actionRequest = $this->objectManager->get(ActionRequest::class, $httpRequest);
     $this->securityContext->setRequest($actionRequest);
     if ($tokenData['securityContextHash'] !== $this->securityContext->getContextHash()) {
         throw new AccessDeniedException(sprintf('Invalid security hash!%sThis request is signed for a security context hash of "%s", but the current hash is "%s"', chr(10), $tokenData['securityContextHash'], $this->securityContext->getContextHash()), 1429705633);
     }
 }
 /**
  * Returns the web accessible URI pointing to the specified persistent resource
  *
  * @param Resource $resource Resource object
  * @return string The URI
  * @throws Exception
  */
 public function getPublicPersistentResourceUri(Resource $resource)
 {
     $resourceData = array('resourceIdentifier' => $resource->getSha1());
     if ($this->shouldIncludeSecurityContext()) {
         $resourceData['securityContextHash'] = $this->securityContext->getContextHash();
     } elseif (!empty($this->options['tokenLifetime'])) {
         $expirationDateTime = clone $this->now;
         $expirationDateTime = $expirationDateTime->modify(sprintf('+%d seconds', $this->options['tokenLifetime']));
         $resourceData['expirationDateTime'] = $expirationDateTime->format(\DateTime::ISO8601);
     }
     $encodedResourceData = base64_encode(json_encode($resourceData));
     $signedResourceData = $this->hashService->appendHmac($encodedResourceData);
     return $this->detectResourcesBaseUri() . '?__protectedResource=' . $signedResourceData;
 }
 /**
  * Renders an identifier for a content cache entry
  *
  * @param string $typoScriptPath
  * @param array $cacheIdentifierValues
  * @return string An MD5 hash built from the typoScriptPath and certain elements of the given identifier values
  * @throws \TYPO3\TypoScript\Exception\CacheException If an invalid entry identifier value is given
  */
 protected function renderContentCacheEntryIdentifier($typoScriptPath, array $cacheIdentifierValues)
 {
     ksort($cacheIdentifierValues);
     $identifierSource = '';
     foreach ($cacheIdentifierValues as $key => $value) {
         if ($value instanceof CacheAwareInterface) {
             $identifierSource .= $key . '=' . $value->getCacheEntryIdentifier() . '&';
         } elseif (is_string($value) || is_bool($value) || is_integer($value)) {
             $identifierSource .= $key . '=' . $value . '&';
         } elseif ($value !== null) {
             throw new Exception\CacheException(sprintf('Invalid cache entry identifier @cache.entryIdentifier.%s for path "%s". A entry identifier value must be a string or implement CacheAwareInterface.', $key, $typoScriptPath), 1395846615);
         }
     }
     $identifierSource .= 'securityContextHash=' . $this->securityContext->getContextHash();
     return md5($typoScriptPath . '@' . $identifierSource);
 }
 /**
  * Provides a way to identify a context to prevent duplicate context objects.
  *
  * @param array $contextProperties
  * @return string
  */
 protected function getIdentifier(array $contextProperties)
 {
     return md5($this->securityContext->getContextHash() . $this->getIdentifierSource($contextProperties));
 }
 /**
  * @param string $id
  * @return string
  */
 protected function convertCacheIdentifier($id)
 {
     return md5($id . '|' . $this->securityContext->getContextHash());
 }