refactor: change log level and add exceptions

This commit is contained in:
Maël Gangloff
2025-10-13 13:51:51 +02:00
parent efa56055d0
commit 0af22ff989
36 changed files with 253 additions and 135 deletions

View File

@@ -70,6 +70,8 @@ jobs:
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ github.repository }},name-canonical=true,push=true
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Export digest
run: |

View File

@@ -41,3 +41,8 @@ api_platform:
App\Exception\MalformedDomainException: 400
App\Exception\TldNotSupportedException: 400
App\Exception\UnknownRdapServerException: 400
App\Exception\UnsupportedDsnScheme: 400
# Provider exception
App\Exception\Provider\UserNoExplicitConsentException: 451
App\Exception\Provider\AbstractProviderException: 400

View File

@@ -2,12 +2,12 @@
namespace App\Config;
use App\Service\Connector\AutodnsProvider;
use App\Service\Connector\EppClientProvider;
use App\Service\Connector\GandiProvider;
use App\Service\Connector\NamecheapProvider;
use App\Service\Connector\NameComProvider;
use App\Service\Connector\OvhProvider;
use App\Service\Provider\AutodnsProvider;
use App\Service\Provider\EppClientProvider;
use App\Service\Provider\GandiProvider;
use App\Service\Provider\NamecheapProvider;
use App\Service\Provider\NameComProvider;
use App\Service\Provider\OvhProvider;
enum ConnectorProvider: string
{

View File

@@ -58,7 +58,7 @@ class DomainRefreshController extends AbstractController
&& !$this->kernel->isDebug()
&& true !== filter_var($request->get('forced', false), FILTER_VALIDATE_BOOLEAN)
) {
$this->logger->info('It is not necessary to update the domain name', [
$this->logger->debug('It is not necessary to update the domain name', [
'ldhName' => $idnDomain,
'updatedAt' => $domain->getUpdatedAt()->format(\DateTimeInterface::ATOM),
]);

View File

@@ -4,8 +4,8 @@ namespace App\Exception;
class DomainNotFoundException extends \Exception
{
public static function fromDomain(string $ldhName): DomainNotFoundException
public static function fromDomain(string $ldhName): self
{
return new DomainNotFoundException("The domain name $ldhName is not present in the WHOIS database");
return new self("The domain name $ldhName is not present in the WHOIS database");
}
}

View File

@@ -4,8 +4,8 @@ namespace App\Exception;
class MalformedDomainException extends \Exception
{
public static function fromDomain(string $ldhName): MalformedDomainException
public static function fromDomain(string $ldhName): self
{
return new MalformedDomainException("Domain name ($ldhName) must contain at least one dot");
return new self("Domain name ($ldhName) must contain at least one dot");
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace App\Exception\Provider;
abstract class AbstractProviderException extends \Exception
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace App\Exception\Provider;
class DomainOrderFailedExeption extends AbstractProviderException
{
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class EppContactIsAvailableException extends AbstractProviderException
{
public static function fromContact(string $handle): self
{
return new self("At least one of the entered contacts cannot be used because it is indicated as available ($handle)");
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class ExpiredLoginException extends AbstractProviderException
{
public static function fromIdentifier(string $identifier): self
{
return new self("Expired login for identifier $identifier");
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Exception\Provider;
class InvalidLoginException extends AbstractProviderException
{
public function __construct(string $message = '')
{
parent::__construct('' === $message ? 'The status of these credentials is not valid' : $message);
}
public static function fromIdentifier(string $identifier): self
{
return new self("Invalid login for identifier $identifier");
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class InvalidLoginStatusException extends AbstractProviderException
{
public static function fromStatus(string $status): self
{
return new self("The status of these credentials is not valid ($status)");
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class NamecheapRequiresAddressException extends AbstractProviderException
{
public function __construct()
{
parent::__construct('Namecheap account requires at least one address to purchase a domain');
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class PermissionErrorException extends AbstractProviderException
{
public static function fromIdentifier(string $identifier): self
{
return new self("Not enough permissions for identifier $identifier");
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class ProviderGenericErrorException extends AbstractProviderException
{
public function __construct(string $message)
{
parent::__construct($message);
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception\Provider;
class UserNoExplicitConsentException extends AbstractProviderException
{
public function __construct()
{
parent::__construct('The user has not given explicit consent');
}
}

View File

@@ -4,8 +4,8 @@ namespace App\Exception;
class TldNotSupportedException extends \Exception
{
public static function fromTld(string $tld): TldNotSupportedException
public static function fromTld(string $tld): self
{
return new TldNotSupportedException("The requested TLD $tld is not yet supported, please try again with another one");
return new self("The requested TLD $tld is not yet supported, please try again with another one");
}
}

View File

@@ -4,8 +4,8 @@ namespace App\Exception;
class UnknownRdapServerException extends \Exception
{
public static function fromTld(string $tld): UnknownRdapServerException
public static function fromTld(string $tld): self
{
return new UnknownRdapServerException("TLD $tld: Unable to determine which RDAP server to contact");
return new self("TLD $tld: Unable to determine which RDAP server to contact");
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Exception;
class UnsupportedDsnSchemeException extends \Exception
{
public static function fromScheme(string $scheme): UnsupportedDsnSchemeException
{
return new UnsupportedDsnSchemeException("The DSN scheme ($scheme) is not supported");
}
}

View File

@@ -10,8 +10,8 @@ use App\Notifier\DomainOrderNotification;
use App\Repository\DomainRepository;
use App\Repository\WatchListRepository;
use App\Service\ChatNotificationService;
use App\Service\Connector\AbstractProvider;
use App\Service\InfluxdbService;
use App\Service\Provider\AbstractProvider;
use App\Service\StatService;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
@@ -118,7 +118,7 @@ final readonly class OrderDomainHandler
* The purchase was not successful (for several possible reasons that we have not determined).
* The user is informed and the exception is raised, which may allow you to try again.
*/
$this->logger->warning('Unable to complete purchase : an error message is sent to user', [
$this->logger->warning('Unable to complete purchase : an error message is sent to the user', [
'watchlist' => $message->watchListToken,
'connector' => $connector->getId(),
'ldhName' => $message->ldhName,

View File

@@ -73,22 +73,29 @@ final readonly class SendDomainEventNotifHandler
/** @var WatchListTrigger $watchListTrigger */
foreach ($watchListTriggers->getIterator() as $watchListTrigger) {
$this->logger->info('New action has been detected on this domain name : a notification is sent to user', [
'event' => $event->getAction(),
'ldhName' => $message->ldhName,
'username' => $watchList->getUser()->getUserIdentifier(),
]);
$recipient = new Recipient($watchList->getUser()->getEmail());
$notification = new DomainUpdateNotification($this->sender, $event);
if (TriggerAction::SendEmail == $watchListTrigger->getAction()) {
$this->logger->info('New action has been detected on this domain name : an email is sent to user', [
'event' => $event->getAction(),
'ldhName' => $message->ldhName,
'username' => $watchList->getUser()->getUserIdentifier(),
]);
$this->mailer->send($notification->asEmailMessage($recipient)->getMessage());
} elseif (TriggerAction::SendChat == $watchListTrigger->getAction()) {
$webhookDsn = $watchList->getWebhookDsn();
if (null === $webhookDsn || 0 === count($webhookDsn)) {
continue;
}
$this->logger->info('New action has been detected on this domain name : a notification is sent to user', [
'event' => $event->getAction(),
'ldhName' => $message->ldhName,
'username' => $watchList->getUser()->getUserIdentifier(),
]);
$this->chatNotificationService->sendChatNotification($watchList, $notification);
}

View File

@@ -14,8 +14,8 @@ use App\Notifier\DomainDeletedNotification;
use App\Repository\DomainRepository;
use App\Repository\WatchListRepository;
use App\Service\ChatNotificationService;
use App\Service\Connector\AbstractProvider;
use App\Service\Connector\CheckDomainProviderInterface;
use App\Service\Provider\AbstractProvider;
use App\Service\Provider\CheckDomainProviderInterface;
use App\Service\RDAPService;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
@@ -55,7 +55,7 @@ final readonly class UpdateDomainsFromWatchlistHandler
/** @var WatchList $watchList */
$watchList = $this->watchListRepository->findOneBy(['token' => $message->watchListToken]);
$this->logger->info('Domain names listed in the Watchlist will be updated', [
$this->logger->debug('Domain names listed in the Watchlist will be updated', [
'watchlist' => $message->watchListToken,
]);
@@ -63,18 +63,19 @@ final readonly class UpdateDomainsFromWatchlistHandler
$connectorProvider = $this->getConnectorProvider($watchList);
if ($connectorProvider instanceof CheckDomainProviderInterface) {
$this->logger->notice('Watchlist is linked to a connector', [
$this->logger->debug('Watchlist is linked to a connector', [
'watchlist' => $watchList->getToken(),
'connector' => $watchList->getConnector()->getId(),
]);
$domainList = array_unique(array_map(fn (Domain $d) => $d->getLdhName(), $watchList->getDomains()->toArray()));
try {
$checkedDomains = $connectorProvider->checkDomains(
...array_unique(array_map(fn (Domain $d) => $d->getLdhName(), $watchList->getDomains()->toArray()))
);
$checkedDomains = $connectorProvider->checkDomains(...$domainList);
} catch (\Throwable $exception) {
$this->logger->warning('Unable to check domain names availability with this connector', [
'connector' => $watchList->getConnector()->getId(),
'ldhName' => $domainList,
]);
throw $exception;

View File

@@ -5,7 +5,7 @@ namespace App\MessageHandler;
use App\Message\ValidateConnectorCredentials;
use App\Notifier\ValidateConnectorCredentialsErrorNotification;
use App\Repository\ConnectorRepository;
use App\Service\Connector\AbstractProvider;
use App\Service\Provider\AbstractProvider;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;

View File

@@ -4,10 +4,9 @@ namespace App\Service;
use App\Config\WebhookScheme;
use App\Entity\WatchList;
use App\Exception\UnsupportedDsnSchemeException;
use App\Notifier\DomainWatchdogNotification;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Notifier\Exception\InvalidArgumentException;
use Symfony\Component\Notifier\Exception\TransportExceptionInterface;
use Symfony\Component\Notifier\Recipient\NoRecipient;
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
use Symfony\Component\Notifier\Transport\Dsn;
@@ -15,10 +14,13 @@ use Symfony\Component\Notifier\Transport\Dsn;
readonly class ChatNotificationService
{
public function __construct(
private LoggerInterface $logger,
) {
}
/**
* @throws UnsupportedDsnSchemeException
* @throws TransportExceptionInterface
*/
public function sendChatNotification(WatchList $watchList, DomainWatchdogNotification $notification): void
{
$webhookDsn = $watchList->getWebhookDsn();
@@ -28,17 +30,13 @@ readonly class ChatNotificationService
}
foreach ($webhookDsn as $dsnString) {
try {
$dsn = new Dsn($dsnString);
} catch (InvalidArgumentException $exception) {
throw new BadRequestHttpException($exception->getMessage());
}
$dsn = new Dsn($dsnString);
$scheme = $dsn->getScheme();
$webhookScheme = WebhookScheme::tryFrom($scheme);
if (null === $webhookScheme) {
throw new BadRequestHttpException("The DSN scheme ($scheme) is not supported");
throw new UnsupportedDsnSchemeException($scheme);
}
$transportFactoryClass = $webhookScheme->getChatTransportFactory();
@@ -48,29 +46,14 @@ readonly class ChatNotificationService
$push = $notification->asPushMessage(new NoRecipient());
$chat = $notification->asChatMessage(new NoRecipient(), $webhookScheme->value);
try {
$factory = $transportFactory->create($dsn);
$factory = $transportFactory->create($dsn);
if ($factory->supports($push)) {
$factory->send($push);
} elseif ($factory->supports($chat)) {
$factory->send($chat);
} else {
throw new BadRequestHttpException('Unsupported message type');
}
$this->logger->info('Chat message sent', [
'username' => $watchList->getUser()->getUserIdentifier(),
'scheme' => $webhookScheme->name,
'watchlist' => $watchList->getToken(),
]);
} catch (\Throwable $exception) {
$this->logger->error('Unable to send a chat message', [
'username' => $watchList->getUser()->getUserIdentifier(),
'scheme' => $webhookScheme->name,
'watchlist' => $watchList->getToken(),
]);
throw new BadRequestHttpException($exception->getMessage());
if ($factory->supports($push)) {
$factory->send($push);
} elseif ($factory->supports($chat)) {
$factory->send($chat);
} else {
throw new \InvalidArgumentException('Unsupported message type');
}
}
}

View File

@@ -1,9 +1,10 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\DefaultProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\UserNoExplicitConsentException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
@@ -65,7 +66,7 @@ abstract class AbstractProvider
*
* @return array raw authentication data as supplied by the user
*
* @throws HttpException when the user does not accept the necessary conditions
* @throws UserNoExplicitConsentException when the user does not accept the necessary conditions
*/
private function verifyLegalAuthData(array $authData): array
{
@@ -76,7 +77,7 @@ abstract class AbstractProvider
if (true !== $acceptConditions
|| true !== $ownerLegalAge
|| true !== $waiveRetractationPeriod) {
throw new HttpException(451, 'The user has not given explicit consent');
throw new UserNoExplicitConsentException();
}
return $authData;

View File

@@ -1,17 +1,17 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\AutodnsProviderDto;
use App\Dto\Connector\DefaultProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\InvalidLoginException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@@ -201,26 +201,23 @@ class AutodnsProvider extends AbstractProvider
/**
* @throws TransportExceptionInterface
* @throws InvalidLoginException
*/
protected function assertAuthentication(): void
{
try {
$response = $this->client->request(
'GET',
'/v1/hello',
(new HttpOptions())
->setAuthBasic($this->authData->username, $this->authData->password)
->setHeader('Accept', 'application/json')
->setHeader('X-Domainrobot-Context', (string) $this->authData->context)
->setBaseUri(self::BASE_URL)
->toArray()
);
} catch (\Exception) {
throw new BadRequestHttpException('Invalid Login');
}
$response = $this->client->request(
'GET',
'/v1/hello',
(new HttpOptions())
->setAuthBasic($this->authData->username, $this->authData->password)
->setHeader('Accept', 'application/json')
->setHeader('X-Domainrobot-Context', (string) $this->authData->context)
->setBaseUri(self::BASE_URL)
->toArray()
);
if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new BadRequestHttpException('The status of these credentials is not valid');
throw InvalidLoginException::fromIdentifier($this->authData->username);
}
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
interface CheckDomainProviderInterface
{

View File

@@ -1,10 +1,11 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\DefaultProviderDto;
use App\Dto\Connector\EppClientProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\EppContactIsAvailableException;
use Metaregistrar\EPP\eppCheckContactRequest;
use Metaregistrar\EPP\eppCheckContactResponse;
use Metaregistrar\EPP\eppCheckDomainRequest;
@@ -18,7 +19,6 @@ use Metaregistrar\EPP\eppHelloRequest;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
@@ -57,7 +57,7 @@ class EppClientProvider extends AbstractProvider implements CheckDomainProviderI
$resp = $this->eppClient->request(new eppCheckContactRequest($contacts));
foreach ($resp->getCheckedContacts() as $contact => $available) {
if ($available) {
throw new BadRequestHttpException("At least one of the entered contacts cannot be used because it is indicated as available ($contact).");
throw EppContactIsAvailableException::fromContact($contact);
}
}

View File

@@ -1,17 +1,17 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\DefaultProviderDto;
use App\Dto\Connector\GandiProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\DomainOrderFailedExeption;
use App\Exception\Provider\InvalidLoginException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@@ -94,12 +94,13 @@ class GandiProvider extends AbstractProvider
if ((!$dryRun && Response::HTTP_ACCEPTED !== $res->getStatusCode())
|| ($dryRun && Response::HTTP_OK !== $res->getStatusCode())) {
throw new HttpException($res->toArray()['message']);
throw new DomainOrderFailedExeption($res->toArray()['message']);
}
}
/**
* @throws TransportExceptionInterface
* @throws InvalidLoginException
*/
protected function assertAuthentication(): void
{
@@ -111,7 +112,7 @@ class GandiProvider extends AbstractProvider
);
if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new BadRequestHttpException('The status of these credentials is not valid');
throw new InvalidLoginException();
}
}

View File

@@ -1,17 +1,17 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\DefaultProviderDto;
use App\Dto\Connector\NameComProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\InvalidLoginException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
@@ -98,25 +98,22 @@ class NameComProvider extends AbstractProvider
/**
* @throws TransportExceptionInterface
* @throws InvalidLoginException
*/
protected function assertAuthentication(): void
{
try {
$response = $this->client->request(
'GET',
'/v4/hello',
(new HttpOptions())
->setHeader('Accept', 'application/json')
->setAuthBasic($this->authData->username, $this->authData->token)
->setBaseUri($this->kernel->isDebug() ? self::DEV_BASE_URL : self::BASE_URL)
->toArray()
);
} catch (\Exception) {
throw new BadRequestHttpException('Invalid Login');
}
$response = $this->client->request(
'GET',
'/v4/hello',
(new HttpOptions())
->setHeader('Accept', 'application/json')
->setAuthBasic($this->authData->username, $this->authData->token)
->setBaseUri($this->kernel->isDebug() ? self::DEV_BASE_URL : self::BASE_URL)
->toArray()
);
if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new BadRequestHttpException('The status of these credentials is not valid');
throw InvalidLoginException::fromIdentifier($this->authData->username);
}
}
}

View File

@@ -1,15 +1,16 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\DefaultProviderDto;
use App\Dto\Connector\NamecheapProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\NamecheapRequiresAddressException;
use App\Exception\Provider\ProviderGenericErrorException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@@ -49,7 +50,7 @@ class NamecheapProvider extends AbstractProvider
$addresses = $this->call('namecheap.users.address.getList', [], $dryRun)->AddressGetListResult->List;
if (count($addresses) < 1) {
throw new BadRequestHttpException('Namecheap account requires at least one address to purchase a domain');
throw new NamecheapRequiresAddressException();
}
$addressId = (string) $addresses->attributes()['AddressId'];
@@ -105,7 +106,7 @@ class NamecheapProvider extends AbstractProvider
$data = new \SimpleXMLElement($response->getContent());
if ($data->Errors->Error) {
throw new BadRequestHttpException($data->Errors->Error);
throw new ProviderGenericErrorException($data->Errors->Error);
}
return $data->CommandResponse;
@@ -116,13 +117,14 @@ class NamecheapProvider extends AbstractProvider
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
* @throws NamecheapRequiresAddressException
*/
protected function assertAuthentication(): void
{
$addresses = $this->call('namecheap.users.address.getList', [], false)->AddressGetListResult->List;
if (count($addresses) < 1) {
throw new BadRequestHttpException('Namecheap account requires at least one address to purchase a domain');
throw new NamecheapRequiresAddressException();
}
}

View File

@@ -1,10 +1,15 @@
<?php
namespace App\Service\Connector;
namespace App\Service\Provider;
use App\Dto\Connector\DefaultProviderDto;
use App\Dto\Connector\OvhProviderDto;
use App\Entity\Domain;
use App\Exception\Provider\DomainOrderFailedExeption;
use App\Exception\Provider\ExpiredLoginException;
use App\Exception\Provider\InvalidLoginStatusException;
use App\Exception\Provider\PermissionErrorException;
use App\Exception\Provider\ProviderGenericErrorException;
use GuzzleHttp\Exception\ClientException;
use Ovh\Api;
use Ovh\Exceptions\InvalidParameterException;
@@ -12,7 +17,6 @@ use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@@ -104,7 +108,7 @@ class OvhProvider extends AbstractProvider
);
if (empty($offer)) {
$conn->delete("/order/cart/{$cartId}");
throw new \InvalidArgumentException('Cannot buy this domain name');
throw new DomainOrderFailedExeption();
}
$item = $conn->post("/order/cart/{$cartId}/domain", [
@@ -153,15 +157,15 @@ class OvhProvider extends AbstractProvider
try {
$res = $conn->get('/auth/currentCredential');
if (null !== $res['expiration'] && new \DateTimeImmutable($res['expiration']) < new \DateTimeImmutable()) {
throw new BadRequestHttpException('These credentials have expired');
throw ExpiredLoginException::fromIdentifier($this->authData->appKey);
}
$status = $res['status'];
if ('validated' !== $status) {
throw new BadRequestHttpException("The status of these credentials is not valid ($status)");
throw InvalidLoginStatusException::fromStatus($status);
}
} catch (ClientException $exception) {
throw new BadRequestHttpException($exception->getMessage());
throw new ProviderGenericErrorException($exception->getMessage());
}
foreach (self::REQUIRED_ROUTES as $requiredRoute) {
@@ -177,7 +181,7 @@ class OvhProvider extends AbstractProvider
}
if (!$ok) {
throw new BadRequestHttpException('This Connector does not have enough permissions on the Provider API. Please recreate this Connector.');
throw PermissionErrorException::fromIdentifier($this->authData->appKey);
}
}
}

View File

@@ -119,7 +119,7 @@ class RDAPService
$idnDomain = RDAPService::convertToIdn($fqdn);
$tld = $this->getTld($idnDomain);
$this->logger->info('Update request for a domain name is requested', [
$this->logger->debug('Update request for a domain name is requested', [
'ldhName' => $idnDomain,
]);
@@ -187,7 +187,7 @@ class RDAPService
$tldEntity = $this->tldRepository->findOneBy(['tld' => $tld, 'deletedAt' => null]);
if (null === $tldEntity) {
$this->logger->warning('Domain name cannot be updated because the TLD is not supported', [
$this->logger->debug('Domain name cannot be updated because the TLD is not supported', [
'ldhName' => $domain,
]);
throw TldNotSupportedException::fromTld($tld);
@@ -210,7 +210,7 @@ class RDAPService
$rdapServer = $this->rdapServerRepository->findOneBy(['tld' => $tldString], ['updatedAt' => 'DESC']);
if (null === $rdapServer) {
$this->logger->warning('Unable to determine which RDAP server to contact', [
$this->logger->debug('Unable to determine which RDAP server to contact', [
'tld' => $tldString,
]);
@@ -231,7 +231,7 @@ class RDAPService
private function fetchRdapResponse(RdapServer $rdapServer, string $idnDomain, ?Domain $domain): array
{
$rdapServerUrl = $rdapServer->getUrl();
$this->logger->notice('An RDAP query to update this domain name will be made', [
$this->logger->info('An RDAP query to update this domain name will be made', [
'ldhName' => $idnDomain,
'server' => $rdapServerUrl,
]);
@@ -261,7 +261,7 @@ class RDAPService
|| ($e instanceof TransportExceptionInterface && null !== $response && !in_array('content-length', $response->getHeaders(false)) && 404 === $response->getStatusCode())
) {
if (null !== $domain) {
$this->logger->notice('Domain name has been deleted from the WHOIS database', [
$this->logger->info('Domain name has been deleted from the WHOIS database', [
'ldhName' => $idnDomain,
]);
@@ -295,7 +295,7 @@ class RDAPService
{
$domain = new Domain();
$this->logger->info('Domain name was not known to this instance', [
$this->logger->debug('Domain name was not known to this instance', [
'ldhName' => $idnDomain,
]);
@@ -304,7 +304,7 @@ class RDAPService
private function updateDomainStatus(Domain $domain, array $rdapData): void
{
if (isset($rdapData['status'])) {
if (isset($rdapData['status']) && is_array($rdapData['status'])) {
$status = array_unique($rdapData['status']);
$addedStatus = array_diff($status, $domain->getStatus());
$deletedStatus = array_diff($domain->getStatus(), $status);
@@ -429,7 +429,7 @@ class RDAPService
*/
private function updateDomainNameservers(Domain $domain, array $rdapData): void
{
if (array_key_exists('nameservers', $rdapData) && is_array($rdapData['nameservers'])) {
if (isset($rdapData['nameservers']) && is_array($rdapData['nameservers'])) {
$domain->getNameservers()->clear();
$this->em->persist($domain);
@@ -549,7 +549,7 @@ class RDAPService
if (null === $entity) {
$entity = (new Entity())->setTld($tld);
$this->logger->info('Entity was not known to this instance', [
$this->logger->debug('Entity was not known to this instance', [
'handle' => $rdapEntity['handle'],
'ldhName' => $domain,
]);

View File

@@ -7,8 +7,8 @@ use ApiPlatform\State\ProcessorInterface;
use App\Config\ConnectorProvider;
use App\Entity\Connector;
use App\Entity\User;
use App\Service\Connector\AbstractProvider;
use App\Service\Connector\EppClientProvider;
use App\Service\Provider\AbstractProvider;
use App\Service\Provider\EppClientProvider;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

View File

@@ -6,7 +6,7 @@ use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Config\ConnectorProvider;
use App\Entity\Connector;
use App\Service\Connector\EppClientProvider;
use App\Service\Provider\EppClientProvider;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

View File

@@ -9,7 +9,7 @@ use App\Entity\User;
use App\Entity\WatchList;
use App\Notifier\TestChatNotification;
use App\Service\ChatNotificationService;
use App\Service\Connector\AbstractProvider;
use App\Service\Provider\AbstractProvider;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
@@ -68,7 +68,7 @@ readonly class WatchListUpdateProcessor implements ProcessorInterface
foreach ($data->getDomains()->getIterator() as $domain) {
if (in_array($domain, $trackedDomains)) {
$ldhName = $domain->getLdhName();
$this->logger->notice('User tried to update a watchlist : it is forbidden to register the same domain name twice with limited mode', [
$this->logger->notice('User tried to update a Watchlist : it is forbidden to register the same domain name twice with limited mode', [
'username' => $user->getUserIdentifier(),
'watchlist' => $data->getToken(),
'ldhName' => $ldhName,
@@ -117,7 +117,7 @@ readonly class WatchListUpdateProcessor implements ProcessorInterface
$supported = $connectorProvider->isSupported(...$data->getDomains()->toArray());
if (!$supported) {
$this->logger->notice('Connector does not support all TLDs in this Watchlist', [
$this->logger->debug('Connector does not support all TLDs in this Watchlist', [
'username' => $user->getUserIdentifier(),
'connector' => $connector->getId(),
'provider' => $connector->getProvider()->value,