fix: use plain password in configuration for MailJet webhook url
This commit is contained in:
@@ -26,6 +26,7 @@ final class MailjetNewsletterWebhookCommand extends Command
|
||||
private const string ACTION_REMOVE = 'remove';
|
||||
private const string ACTION_DEACTIVATE = 'deactivate';
|
||||
private const string EVENT_TYPE_UNSUBSCRIBE = 'unsub';
|
||||
private const string WEBHOOK_BASIC_AUTH_USER = 'mailjet';
|
||||
private const string WEBHOOK_PATH = '/webhooks/mailjet/newsletter';
|
||||
private const int WEBHOOK_VERSION = 2;
|
||||
|
||||
@@ -33,6 +34,8 @@ final class MailjetNewsletterWebhookCommand extends Command
|
||||
private readonly MailjetApiClient $mailjetApiClient,
|
||||
#[Autowire('%env(APP_BASE_URL)%')]
|
||||
private readonly string $defaultBaseUrl,
|
||||
#[Autowire('%env(MAILJET_WEBHOOK_BASIC_PASSWORD)%')]
|
||||
private readonly string $basicAuthPassword,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
parent::__construct();
|
||||
@@ -43,7 +46,7 @@ final class MailjetNewsletterWebhookCommand extends Command
|
||||
$this
|
||||
->addArgument('action', InputArgument::REQUIRED, 'One of: register, remove, deactivate')
|
||||
->addArgument('callback_id', InputArgument::OPTIONAL, 'Callback ID required for remove/deactivate')
|
||||
->addOption('url', null, InputOption::VALUE_REQUIRED, 'Override the webhook URL to register');
|
||||
->addOption('url', null, InputOption::VALUE_REQUIRED, 'Override the webhook URL to register before Basic Auth credentials are added');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
@@ -72,9 +75,10 @@ final class MailjetNewsletterWebhookCommand extends Command
|
||||
private function register(SymfonyStyle $io, mixed $overrideUrl): int
|
||||
{
|
||||
$webhookUrl = $this->resolveWebhookUrl($overrideUrl);
|
||||
$payload = $this->mailjetApiClient->createEventCallbackUrl(self::EVENT_TYPE_UNSUBSCRIBE, $webhookUrl, self::WEBHOOK_VERSION);
|
||||
$authenticatedWebhookUrl = $this->prependBasicAuth($webhookUrl);
|
||||
$payload = $this->mailjetApiClient->createEventCallbackUrl(self::EVENT_TYPE_UNSUBSCRIBE, $authenticatedWebhookUrl, self::WEBHOOK_VERSION);
|
||||
|
||||
$io->success(sprintf('Created Mailjet newsletter webhook at %s.', $webhookUrl));
|
||||
$io->success(sprintf('Created Mailjet newsletter webhook at %s.', $authenticatedWebhookUrl));
|
||||
$io->writeln($this->formatPayload($payload));
|
||||
|
||||
return Command::SUCCESS;
|
||||
@@ -115,6 +119,47 @@ final class MailjetNewsletterWebhookCommand extends Command
|
||||
return rtrim(trim($this->defaultBaseUrl), '/').self::WEBHOOK_PATH;
|
||||
}
|
||||
|
||||
private function prependBasicAuth(string $url): string
|
||||
{
|
||||
if ('' === trim($this->basicAuthPassword)) {
|
||||
throw new \InvalidArgumentException('MAILJET_WEBHOOK_BASIC_PASSWORD is not configured.');
|
||||
}
|
||||
|
||||
$parts = parse_url($url);
|
||||
if (false === is_array($parts) || false === isset($parts['scheme'], $parts['host'])) {
|
||||
throw new \InvalidArgumentException('The webhook URL is not valid.');
|
||||
}
|
||||
|
||||
$host = $parts['host'];
|
||||
if (false === str_starts_with($host, '[') && true === str_contains($host, ':')) {
|
||||
$host = sprintf('[%s]', $host);
|
||||
}
|
||||
|
||||
$authenticatedUrl = sprintf(
|
||||
'%s://%s:%s@%s',
|
||||
$parts['scheme'],
|
||||
rawurlencode(self::WEBHOOK_BASIC_AUTH_USER),
|
||||
rawurlencode($this->basicAuthPassword),
|
||||
$host,
|
||||
);
|
||||
|
||||
if (isset($parts['port'])) {
|
||||
$authenticatedUrl .= sprintf(':%d', $parts['port']);
|
||||
}
|
||||
|
||||
$authenticatedUrl .= $parts['path'] ?? '';
|
||||
|
||||
if (isset($parts['query'])) {
|
||||
$authenticatedUrl .= '?'.$parts['query'];
|
||||
}
|
||||
|
||||
if (isset($parts['fragment'])) {
|
||||
$authenticatedUrl .= '#'.$parts['fragment'];
|
||||
}
|
||||
|
||||
return $authenticatedUrl;
|
||||
}
|
||||
|
||||
private function resolveCallbackId(mixed $callbackId): int
|
||||
{
|
||||
if (true === is_int($callbackId) && $callbackId > 0) {
|
||||
|
||||
@@ -22,7 +22,7 @@ final class MailjetNewsletterWebhookController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/webhooks/mailjet/newsletter', name: 'app_webhook_mailjet_newsletter', methods: ['POST'])]
|
||||
public function __invoke(Request $request): JsonResponse
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$payload = json_decode($request->getContent(), true);
|
||||
if (JSON_ERROR_NONE !== json_last_error() || false === is_array($payload)) {
|
||||
@@ -51,8 +51,7 @@ final class MailjetNewsletterWebhookController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $payload
|
||||
*
|
||||
* @param array<string, mixed> $payload
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function normalizeEvents(array $payload): array
|
||||
|
||||
Reference in New Issue
Block a user