vendor/shopware/core/Framework/Api/Acl/AclWriteValidator.php line 22

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Api\Acl;
  3. use Shopware\Core\Framework\Api\Acl\Role\AclRoleDefinition;
  4. use Shopware\Core\Framework\Api\Context\AdminApiSource;
  5. use Shopware\Core\Framework\Api\Exception\MissingPrivilegeException;
  6. use Shopware\Core\Framework\Context;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityTranslationDefinition;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommand;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
  10. use Shopware\Core\Framework\Uuid\Uuid;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. class AclWriteValidator implements EventSubscriberInterface
  13. {
  14.     public static function getSubscribedEvents()
  15.     {
  16.         return [PreWriteValidationEvent::class => 'preValidate'];
  17.     }
  18.     public function preValidate(PreWriteValidationEvent $event): void
  19.     {
  20.         if ($event->getContext()->getScope() === Context::SYSTEM_SCOPE) {
  21.             return;
  22.         }
  23.         $commands $event->getCommands();
  24.         $source $event->getContext()->getSource();
  25.         if (!$source instanceof AdminApiSource || $source->isAdmin()) {
  26.             return;
  27.         }
  28.         $missingPrivileges = [];
  29.         foreach ($commands as $command) {
  30.             $resource $command->getDefinition()->getEntityName();
  31.             $privilege $command->getPrivilege();
  32.             if ($privilege === null) {
  33.                 continue;
  34.             }
  35.             if (is_subclass_of($command->getDefinition(), EntityTranslationDefinition::class)) {
  36.                 $resource $command->getDefinition()->getParentDefinition()->getEntityName();
  37.                 if ($privilege !== AclRoleDefinition::PRIVILEGE_DELETE) {
  38.                     $privilege $this->getPrivilegeForParentWriteOperation($command$commands);
  39.                 }
  40.             }
  41.             if (!$source->isAllowed($resource ':' $privilege)) {
  42.                 $missingPrivileges[] = $resource ':' $privilege;
  43.             }
  44.         }
  45.         $this->tryToThrow($missingPrivileges);
  46.     }
  47.     private function tryToThrow(array $missingPrivileges): void
  48.     {
  49.         if (!empty($missingPrivileges)) {
  50.             throw new MissingPrivilegeException($missingPrivileges);
  51.         }
  52.     }
  53.     /**
  54.      * @param WriteCommand[] $commands
  55.      */
  56.     private function getPrivilegeForParentWriteOperation(WriteCommand $command, array $commands): string
  57.     {
  58.         $pathSuffix '/translations/' Uuid::fromBytesToHex($command->getPrimaryKey()['language_id']);
  59.         $parentCommandPath str_replace($pathSuffix''$command->getPath());
  60.         $parentCommand $this->findCommandByPath($parentCommandPath$commands);
  61.         // writes to translation need privilege from parent command
  62.         // if we update e.g. a product and add translations for a new language
  63.         // the writeCommand on the translation would be an insert
  64.         if ($parentCommand) {
  65.             return (string) $parentCommand->getPrivilege();
  66.         }
  67.         // if we don't have a parentCommand it must be a update,
  68.         // because the parentEntity must already exist
  69.         return AclRoleDefinition::PRIVILEGE_UPDATE;
  70.     }
  71.     /**
  72.      * @param WriteCommand[] $commands
  73.      */
  74.     private function findCommandByPath(string $commandPath, array $commands): ?WriteCommand
  75.     {
  76.         foreach ($commands as $command) {
  77.             if ($command->getPath() === $commandPath) {
  78.                 return $command;
  79.             }
  80.         }
  81.         return null;
  82.     }
  83. }