<?php declare(strict_types=1);
namespace Swag\Security\Fixes\GHSAp5892ff83wfw;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\DefinitionInstanceRegistry;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\WriteProtected;
use Shopware\Core\Framework\Validation\WriteConstraintViolationException;
use Shopware\Core\PlatformRequest;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
class CloneProtectionSubscriber implements EventSubscriberInterface
{
/**
* @var DefinitionInstanceRegistry
*/
private $registry;
public function __construct(DefinitionInstanceRegistry $registry)
{
$this->registry = $registry;
}
public static function getSubscribedEvents(): array
{
return [KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments'];
}
public function onControllerArguments(ControllerArgumentsEvent $event): void
{
// isMainRequest() existiert erst ab Symfony 5.3, isMasterRequest() ist dort deprecated
$isMainRequest = method_exists($event, 'isMainRequest') ? $event->isMainRequest() : $event->isMasterRequest();
if (!$isMainRequest) {
return;
}
$request = $event->getRequest();
if ($request->attributes->get('_route') !== 'api.clone') {
return;
}
$entity = $request->attributes->get('entity');
if (\in_array($entity, ['user', 'integration'], true)) {
throw new AccessDeniedHttpException(sprintf('Clone access for entity "%s" is not allowed.', $entity));
}
if (!\is_string($entity)) {
return;
}
$context = $request->attributes->get(PlatformRequest::ATTRIBUTE_CONTEXT_OBJECT);
if (!$context instanceof Context) {
return;
}
$definition = $this->registry->getByEntityName(str_replace('-', '_', $entity));
foreach ($request->request->all('overwrites') as $propertyName => $value) {
$field = $definition->getFields()->get($propertyName);
if ($field === null) {
continue;
}
$writeProtection = $field->getFlag(WriteProtected::class);
if ($writeProtection === null || $writeProtection->isAllowed($context->getScope())) {
continue;
}
throw new WriteConstraintViolationException(new ConstraintViolationList([
new ConstraintViolation('This field is write-protected.', 'This field is write-protected.', [], $value, $propertyName, $value),
]), '/' . $propertyName);
}
}
}