2025-05-05 14:00:10 +02:00
< ? php
namespace App\State ;
use ApiPlatform\Metadata\Operation ;
use ApiPlatform\Metadata\Post ;
use ApiPlatform\State\ProcessorInterface ;
use App\Entity\Domain ;
use App\Entity\WatchList ;
2025-05-22 14:00:17 +02:00
use App\Entity\WatchListTrigger ;
2025-05-06 14:02:23 +02:00
use App\Notifier\TestChatNotification ;
2025-05-05 14:00:10 +02:00
use App\Repository\DomainRepository ;
2025-05-06 14:02:23 +02:00
use App\Service\ChatNotificationService ;
use App\Service\Connector\AbstractProvider ;
2025-05-05 14:00:10 +02:00
use App\Service\RDAPService ;
2025-05-22 14:00:17 +02:00
use Doctrine\ORM\EntityManagerInterface ;
2025-05-06 14:02:23 +02:00
use Psr\Log\LoggerInterface ;
2025-05-05 14:00:10 +02:00
use Symfony\Bundle\SecurityBundle\Security ;
use Symfony\Component\DependencyInjection\Attribute\Autowire ;
2025-05-06 14:02:23 +02:00
use Symfony\Component\DependencyInjection\ContainerInterface ;
2025-05-05 14:00:10 +02:00
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface ;
2025-05-06 14:02:23 +02:00
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException ;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException ;
2025-05-05 14:00:10 +02:00
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException ;
use Symfony\Component\HttpKernel\KernelInterface ;
use Symfony\Component\RateLimiter\RateLimiterFactory ;
class WatchListUpdateProcessor implements ProcessorInterface
{
public function __construct (
2025-05-06 14:02:23 +02:00
private readonly DomainRepository $domainRepository ,
2025-05-22 14:00:17 +02:00
private readonly RDAPService $RDAPService ,
private readonly KernelInterface $kernel ,
private readonly Security $security ,
private readonly RateLimiterFactory $rdapRequestsLimiter ,
private readonly ParameterBagInterface $parameterBag ,
2025-05-05 14:00:10 +02:00
#[Autowire(service: 'api_platform.doctrine.orm.state.persist_processor')]
2025-05-22 14:00:17 +02:00
private readonly ProcessorInterface $persistProcessor ,
private readonly LoggerInterface $logger ,
2025-05-06 14:02:23 +02:00
private readonly ChatNotificationService $chatNotificationService ,
#[Autowire(service: 'service_container')]
2025-05-22 14:00:17 +02:00
private readonly ContainerInterface $locator ,
private readonly EntityManagerInterface $entityManager ,
2025-05-05 14:00:10 +02:00
)
{}
/**
* @ param WatchList $data
* @ param Operation $operation
* @ param array $uriVariables
* @ param array $context
* @ return WatchList
*/
public function process ( mixed $data , Operation $operation , array $uriVariables = [], array $context = []) : mixed
{
2025-05-06 14:02:23 +02:00
$user = $this -> security -> getUser ();
2025-05-22 14:00:17 +02:00
$data -> setUser ( $user );
2025-05-05 14:00:10 +02:00
2025-05-06 14:02:23 +02:00
if ( $this -> parameterBag -> get ( 'limited_features' )) {
if ( $data -> getDomains () -> count () > ( int ) $this -> parameterBag -> get ( 'limit_max_watchlist_domains' )) {
$this -> logger -> notice ( 'User {username} tried to update a Watchlist. The maximum number of domains has been reached for this Watchlist' , [
'username' => $user -> getUserIdentifier (),
]);
2025-05-22 14:00:17 +02:00
2025-05-06 14:02:23 +02:00
throw new AccessDeniedHttpException ( 'You have exceeded the maximum number of domain names allowed in this Watchlist' );
}
$userWatchLists = $user -> getWatchLists ();
2025-05-05 14:00:10 +02:00
2025-05-06 14:02:23 +02:00
/** @var Domain[] $trackedDomains */
$trackedDomains = $userWatchLists
-> filter ( fn ( WatchList $wl ) => $wl -> getToken () !== $data -> getToken ())
-> reduce ( fn ( array $acc , WatchList $wl ) => [ ... $acc , ... $wl -> getDomains () -> toArray ()], []);
2025-05-05 14:00:10 +02:00
2025-05-06 14:02:23 +02:00
/** @var Domain $domain */
foreach ( $data -> getDomains () -> getIterator () as $domain ) {
if ( in_array ( $domain , $trackedDomains )) {
$ldhName = $domain -> getLdhName ();
$this -> logger -> notice ( 'User {username} tried to update a watchlist with domain name {ldhName}. It is forbidden to register the same domain name twice with limited mode' , [
'username' => $user -> getUserIdentifier (),
'ldhName' => $ldhName ,
]);
throw new AccessDeniedHttpException ( " It is forbidden to register the same domain name twice in your watchlists with limited mode ( $ldhName ) " );
2025-05-05 14:00:10 +02:00
}
}
2025-05-06 14:02:23 +02:00
if ( null !== $data -> getWebhookDsn () && count ( $data -> getWebhookDsn ()) > ( int ) $this -> parameterBag -> get ( 'limit_max_watchlist_webhooks' )) {
$this -> logger -> notice ( 'User {username} tried to update a Watchlist. The maximum number of webhooks has been reached.' , [
'username' => $user -> getUserIdentifier (),
]);
2025-05-22 14:00:17 +02:00
2025-05-06 14:02:23 +02:00
throw new AccessDeniedHttpException ( 'You have exceeded the maximum number of webhooks allowed in this Watchlist' );
}
2025-05-05 14:00:10 +02:00
}
2025-05-06 14:02:23 +02:00
$this -> chatNotificationService -> sendChatNotification ( $data , new TestChatNotification ());
if ( $connector = $data -> getConnector ()) {
if ( ! $user -> getConnectors () -> contains ( $connector )) {
$this -> logger -> notice ( 'The Connector ({connector}) does not belong to the user.' , [
'username' => $user -> getUserIdentifier (),
'connector' => $connector -> getId (),
]);
2025-05-22 14:00:17 +02:00
2025-05-06 14:02:23 +02:00
throw new AccessDeniedHttpException ( 'You cannot create a Watchlist with a connector that does not belong to you' );
}
/** @var Domain $domain */
foreach ( $data -> getDomains () -> getIterator () as $domain ) {
if ( $domain -> getDeleted ()) {
$ldhName = $domain -> getLdhName ();
2025-05-22 14:00:17 +02:00
2025-05-06 14:02:23 +02:00
throw new BadRequestHttpException ( " To add a connector, no domain in this Watchlist must have already expired ( $ldhName ) " );
}
}
$connectorProviderClass = $connector -> getProvider () -> getConnectorProvider ();
/** @var AbstractProvider $connectorProvider */
$connectorProvider = $this -> locator -> get ( $connectorProviderClass );
$connectorProvider -> authenticate ( $connector -> getAuthData ());
$supported = $connectorProvider -> isSupported ( ... $data -> getDomains () -> toArray ());
if ( ! $supported ) {
$this -> logger -> notice ( 'The Connector ({connector}) does not support all TLDs in this Watchlist' , [
'username' => $user -> getUserIdentifier (),
'connector' => $connector -> getId (),
]);
2025-05-22 14:00:17 +02:00
2025-05-06 14:02:23 +02:00
throw new BadRequestHttpException ( 'This connector does not support all TLDs in this Watchlist' );
}
2025-05-05 14:00:10 +02:00
}
2025-05-06 14:02:23 +02:00
$this -> persistProcessor -> process ( $data , $operation , $uriVariables , $context );
2025-05-05 14:00:10 +02:00
return $data ;
}
}