diff --git a/src/Controller/WatchListController.php b/src/Controller/WatchListController.php index e504a64..025f777 100644 --- a/src/Controller/WatchListController.php +++ b/src/Controller/WatchListController.php @@ -18,6 +18,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\LockMode; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Exception\ORMException; +use Doctrine\ORM\OptimisticLockException; use Eluceo\iCal\Domain\Entity\Attendee; use Eluceo\iCal\Domain\Entity\Calendar; use Eluceo\iCal\Domain\Entity\Event; @@ -81,6 +82,7 @@ class WatchListController extends AbstractController * @throws DecodingExceptionInterface * @throws ClientExceptionInterface * @throws \JsonException + * @throws \Exception */ #[Route( path: '/api/watchlists', @@ -93,36 +95,7 @@ class WatchListController extends AbstractController )] public function createWatchList(Request $request): WatchList { - /** @var WatchList $watchList */ - $watchList = $this->serializer->deserialize($request->getContent(), WatchList::class, 'json', ['groups' => 'watchlist:create']); - - $data = json_decode($request->getContent(), true, 512, JSON_THROW_ON_ERROR); - - if (!is_array($data) || !isset($data['domains']) || !is_array($data['domains'])) { - throw new BadRequestHttpException('Invalid payload: missing or invalid "domains" field.'); - } - - $domains = array_map(fn (string $d) => str_replace('/api/domains/', '', $d), $data['domains']); - - foreach ($domains as $ldhName) { - /** @var ?Domain $domain */ - $domain = $this->domainRepository->findOneBy(['ldhName' => $ldhName]); - - if (null === $domain) { - $domain = $this->RDAPService->registerDomain($ldhName); - - if (false === $this->kernel->isDebug() && true === $this->getParameter('limited_features')) { - $limiter = $this->rdapRequestsLimiter->create($this->getUser()->getUserIdentifier()); - $limit = $limiter->consume(); - - if (!$limit->isAccepted()) { - throw new TooManyRequestsHttpException($limit->getRetryAfter()->getTimestamp() - time()); - } - } - } - - $watchList->addDomain($domain); - } + $watchList = $this->registerDomainsInWatchlist($request->getContent(), ['watchlist:create']); /** @var User $user */ $user = $this->getUser(); @@ -250,6 +223,14 @@ class WatchListController extends AbstractController /** * @throws ORMException + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws \JsonException + * @throws OptimisticLockException + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws ExceptionInterface * @throws \Exception */ #[Route( @@ -261,8 +242,10 @@ class WatchListController extends AbstractController ], methods: ['PUT'] )] - public function putWatchList(WatchList $watchList): WatchList + public function putWatchList(Request $request): WatchList { + $watchList = $this->registerDomainsInWatchlist($request->getContent(), ['watchlist:create', 'watchlist:token']); + /** @var User $user */ $user = $this->getUser(); $watchList->setUser($user); @@ -451,4 +434,48 @@ class WatchListController extends AbstractController return $domains; } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws \JsonException + */ + private function registerDomainsInWatchlist(string $content, array $groups): WatchList + { + /** @var WatchList $watchList */ + $watchList = $this->serializer->deserialize($content, WatchList::class, 'json', ['groups' => $groups]); + + $data = json_decode($content, true, 512, JSON_THROW_ON_ERROR); + + if (!is_array($data) || !isset($data['domains']) || !is_array($data['domains'])) { + throw new BadRequestHttpException('Invalid payload: missing or invalid "domains" field.'); + } + + $domains = array_map(fn (string $d) => str_replace('/api/domains/', '', $d), $data['domains']); + + foreach ($domains as $ldhName) { + /** @var ?Domain $domain */ + $domain = $this->domainRepository->findOneBy(['ldhName' => $ldhName]); + + if (null === $domain) { + $domain = $this->RDAPService->registerDomain($ldhName); + + if (false === $this->kernel->isDebug() && true === $this->getParameter('limited_features')) { + $limiter = $this->rdapRequestsLimiter->create($this->getUser()->getUserIdentifier()); + $limit = $limiter->consume(); + + if (!$limit->isAccepted()) { + throw new TooManyRequestsHttpException($limit->getRetryAfter()->getTimestamp() - time()); + } + } + } + + $watchList->addDomain($domain); + } + + return $watchList; + } }