<?php
namespace Swag\Security\Fixes\NEXT32886;
use Doctrine\DBAL\Connection;
use Psr\Log\LoggerInterface;
use Shopware\Core\Content\Flow\Dispatching\StorableFlow;
use Shopware\Core\Content\Media\File\FileUrlValidatorInterface;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Event\FlowEvent;
use Shopware\Core\Framework\Uuid\Uuid;
use Swag\FlowBuilderProfessional\Core\Content\Flow\Dispatching\Action\CallWebhookAction;
class CallWebhookActionFix extends CallWebhookAction
{
/**
* @var FileUrlValidatorInterface
*/
private $fileUrlValidator;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var Connection
*/
private $connection;
public function setFileUrlValidator(FileUrlValidatorInterface $fileUrlValidator): void
{
$this->fileUrlValidator = $fileUrlValidator;
}
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
public function setConnection(Connection $connection): void
{
$this->connection = $connection;
}
public function handleFlow(StorableFlow $flow): void
{
$url = $flow->getConfig()['baseUrl'];
if (!$this->validate($url, $flow->getName(), $flow->getFlowState()->getSequenceId())) {
return;
}
parent::handleFlow($flow);
}
public function handle(FlowEvent $event): void
{
$url = $event->getConfig()['baseUrl'];
if (!$this->validate($url, $event->getName(), $event->getFlowState()->getSequenceId())) {
return;
}
parent::handle($event);
}
private function validate(string $url, string $eventName, string $sequenceId): bool
{
if ($this->fileUrlValidator->isValid($url)) {
return true;
}
$this->logger->error('Webhook url is not valid: Webhook urls must be publicly accessible.');
$webhookEventId = Uuid::randomBytes();
$this->connection->executeStatement(
'INSERT INTO
`webhook_event_log` (id, delivery_status, timestamp, webhook_name, event_name, url, request_content, response_content, created_at)
VALUES (:webhookEventId, :deliveryStatus, :timestamp, :webhookName, :eventName, :url, :requestContent, :responseContent, :createdAt)',
[
'webhookEventId' => $webhookEventId,
'deliveryStatus' => 'failed',
'timestamp' => time(),
'webhookName' => $url,
'eventName' => $eventName,
'url' => $url,
'requestContent' => '{}',
'responseContent' => \json_encode([
'message' => 'Webhook url is not valid: Webhook urls must be publicly accessible.',
]),
'createdAt' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
]
);
$this->connection->executeStatement(
'INSERT INTO `swag_sequence_webhook_event_log` (sequence_id, webhook_event_log_id)
VALUES (:sequenceId, :webhookEventId)',
[
'sequenceId' => Uuid::fromHexToBytes($sequenceId),
'webhookEventId' => $webhookEventId,
]
);
return false;
}
}