fix: prevent race condition on newsletter consent confirmation

This commit is contained in:
Björn Fromme
2026-07-14 09:47:22 +02:00
parent b95944701e
commit 6c4ea07e6e
3 changed files with 39 additions and 4 deletions
@@ -38,4 +38,31 @@ class NewsletterConsentRepository extends ServiceEntityRepository
'mailjetListId' => $mailjetListId,
]);
}
/**
* @param list<int> $mailjetListIds
*
* @return array<int, NewsletterConsent> existing consents indexed by mailjetListId
*/
public function findByEmailAndListIds(string $email, array $mailjetListIds): array
{
if ([] === $mailjetListIds) {
return [];
}
$consents = $this->createQueryBuilder('c')
->where('c.email = :email')
->andWhere('c.mailjetListId IN (:listIds)')
->setParameter('email', mb_strtolower(trim($email)))
->setParameter('listIds', $mailjetListIds)
->getQuery()
->getResult();
$byListId = [];
foreach ($consents as $consent) {
$byListId[$consent->getMailjetListId()] = $consent;
}
return $byListId;
}
}
+4 -3
View File
@@ -327,8 +327,7 @@ class NewsletterManager
$this->newsletterService->ensureSubscribed($confirmation->getEmail(), $mailjetListId);
}
$confirmation->markConfirmed();
$this->upsertConfirmedConsents($confirmation->getEmail(), $mailjetListIds, $confirmation->getFirstName(), $confirmation->getLastName(), false, false);
$this->upsertConfirmedConsents($confirmation->getEmail(), $mailjetListIds, $confirmation->getFirstName(), $confirmation->getLastName(), flush: false, deletePending: false);
$this->entityManager->remove($confirmation);
$this->entityManager->flush();
@@ -468,8 +467,10 @@ class NewsletterManager
*/
private function upsertConfirmedConsents(string $email, array $mailjetListIds, ?string $firstName, ?string $lastName, bool $flush = true, bool $deletePending = true): void
{
$existingByListId = $this->consentRepository->findByEmailAndListIds($email, $mailjetListIds);
foreach ($mailjetListIds as $mailjetListId) {
$consent = $this->consentRepository->findOneByEmailAndListId($email, $mailjetListId);
$consent = $existingByListId[$mailjetListId] ?? null;
if (null === $consent) {
$consent = new NewsletterConsent($email, $mailjetListId, $firstName, $lastName);
$this->entityManager->persist($consent);