mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
feat: ovh API implement
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240728210044 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SEQUENCE connector_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE connector (id INT NOT NULL, user_id INT NOT NULL, auth_data JSON NOT NULL, provider VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_148C456EA76ED395 ON connector (user_id)');
|
||||
$this->addSql('ALTER TABLE connector ADD CONSTRAINT FK_148C456EA76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('DROP SEQUENCE connector_id_seq CASCADE');
|
||||
$this->addSql('ALTER TABLE connector DROP CONSTRAINT FK_148C456EA76ED395');
|
||||
$this->addSql('DROP TABLE connector');
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240729093649 extends AbstractMigration
|
||||
final class Version20240729131244 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
@@ -20,7 +20,12 @@ final class Version20240729093649 extends AbstractMigration
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE watch_list_trigger ADD connector_id INT DEFAULT NULL');
|
||||
$this->addSql('CREATE TABLE connector (id UUID NOT NULL, user_id INT NOT NULL, auth_data JSON NOT NULL, provider VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_148C456EA76ED395 ON connector (user_id)');
|
||||
$this->addSql('COMMENT ON COLUMN connector.id IS \'(DC2Type:uuid)\'');
|
||||
$this->addSql('ALTER TABLE connector ADD CONSTRAINT FK_148C456EA76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE watch_list_trigger ADD connector_id UUID DEFAULT NULL');
|
||||
$this->addSql('COMMENT ON COLUMN watch_list_trigger.connector_id IS \'(DC2Type:uuid)\'');
|
||||
$this->addSql('ALTER TABLE watch_list_trigger ADD CONSTRAINT FK_CF857A4C4D085745 FOREIGN KEY (connector_id) REFERENCES connector (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_CF857A4C4D085745 ON watch_list_trigger (connector_id)');
|
||||
}
|
||||
@@ -30,6 +35,8 @@ final class Version20240729093649 extends AbstractMigration
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('ALTER TABLE watch_list_trigger DROP CONSTRAINT FK_CF857A4C4D085745');
|
||||
$this->addSql('ALTER TABLE connector DROP CONSTRAINT FK_148C456EA76ED395');
|
||||
$this->addSql('DROP TABLE connector');
|
||||
$this->addSql('DROP INDEX IDX_CF857A4C4D085745');
|
||||
$this->addSql('ALTER TABLE watch_list_trigger DROP connector_id');
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Config;
|
||||
namespace App\Config\Connector;
|
||||
|
||||
use App\Entity\Domain;
|
||||
|
||||
interface ConnectorInterface
|
||||
{
|
||||
public static function verifyAuthData(array $authData): array;
|
||||
|
||||
public function orderDomain(Domain $domain,
|
||||
bool $acceptConditions,
|
||||
bool $ownerLegalAge,
|
||||
@@ -1,17 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
namespace App\Config\Connector;
|
||||
|
||||
use App\Config\ConnectorInterface;
|
||||
use App\Repository\OVHConnectorRepository;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use App\Entity\Domain;
|
||||
use Exception;
|
||||
use Ovh\Api;
|
||||
|
||||
#[Entity(repositoryClass: OVHConnectorRepository::class)]
|
||||
class OVHConnector extends Connector implements ConnectorInterface
|
||||
readonly class OvhConnector implements ConnectorInterface
|
||||
{
|
||||
|
||||
public function __construct(private array $authData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Order a domain name with the OVH API
|
||||
* @throws Exception
|
||||
@@ -23,12 +25,12 @@ class OVHConnector extends Connector implements ConnectorInterface
|
||||
bool $dryRyn = false
|
||||
): void
|
||||
{
|
||||
if (!$domain->getDeleted()) throw new Exception('The domain name still appears in the WHOIS database.');
|
||||
if (!$domain->getDeleted()) throw new Exception('The domain name still appears in the WHOIS database');
|
||||
|
||||
$ldhName = $domain->getLdhName();
|
||||
if (!$ldhName) throw new Exception("Domain name cannot be null.");
|
||||
if (!$ldhName) throw new Exception("Domain name cannot be null");
|
||||
|
||||
$authData = $this->getAuthData();
|
||||
$authData = self::verifyAuthData($this->authData);
|
||||
|
||||
$appKey = $authData['appKey'];
|
||||
$appSecret = $authData['appSecret'];
|
||||
@@ -37,14 +39,6 @@ class OVHConnector extends Connector implements ConnectorInterface
|
||||
$ovhSubsidiary = $authData['ovhSubsidiary'];
|
||||
$pricingMode = $authData['pricingMode'];
|
||||
|
||||
if (!$appKey ||
|
||||
!$appSecret ||
|
||||
!$apiEndpoint ||
|
||||
!$consumerKey ||
|
||||
!$ovhSubsidiary ||
|
||||
!$pricingMode
|
||||
) throw new Exception("Auth data cannot be null.");
|
||||
|
||||
$conn = new Api(
|
||||
$appKey,
|
||||
$appSecret,
|
||||
@@ -65,7 +59,7 @@ class OVHConnector extends Connector implements ConnectorInterface
|
||||
$offer['orderable'] === true &&
|
||||
$offers['pricingMode'] === $pricingMode
|
||||
);
|
||||
if (empty($offer)) throw new Exception('Cannot buy this domain name.');
|
||||
if (empty($offer)) throw new Exception('Cannot buy this domain name');
|
||||
|
||||
$item = $conn->post("/order/cart/{$cartId}/domain", [
|
||||
"domain" => $ldhName,
|
||||
@@ -98,4 +92,34 @@ class OVHConnector extends Connector implements ConnectorInterface
|
||||
"waiveRetractationPeriod" => $waiveRetractationPeriod
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function verifyAuthData(array $authData): array
|
||||
{
|
||||
$appKey = $authData['appKey'];
|
||||
$appSecret = $authData['appSecret'];
|
||||
$apiEndpoint = $authData['apiEndpoint'];
|
||||
$consumerKey = $authData['consumerKey'];
|
||||
$ovhSubsidiary = $authData['ovhSubsidiary'];
|
||||
$pricingMode = $authData['pricingMode'];
|
||||
|
||||
if (!is_string($appKey) || empty($appKey) ||
|
||||
!is_string($appSecret) || empty($appSecret) ||
|
||||
!is_string($consumerKey) || empty($consumerKey) ||
|
||||
!is_string($apiEndpoint) || empty($apiEndpoint) ||
|
||||
!is_string($ovhSubsidiary) || empty($ovhSubsidiary) ||
|
||||
!is_string($pricingMode) || empty($pricingMode)
|
||||
) throw new Exception("Bad data schema.");
|
||||
|
||||
return [
|
||||
"appKey" => $appKey,
|
||||
"appSecret" => $appSecret,
|
||||
"apiEndpoint" => $apiEndpoint,
|
||||
"consumerKey" => $consumerKey,
|
||||
"ovhSubsidiary" => $ovhSubsidiary,
|
||||
"pricingMode" => $pricingMode
|
||||
];
|
||||
}
|
||||
}
|
||||
68
src/Controller/ConnectorController.php
Normal file
68
src/Controller/ConnectorController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Config\Connector\OvhConnector;
|
||||
use App\Config\ConnectorProvider;
|
||||
use App\Entity\Connector;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
class ConnectorController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SerializerInterface $serializer, private readonly EntityManagerInterface $em
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#[Route(
|
||||
path: '/api/connectors',
|
||||
name: 'connector_get_all_mine',
|
||||
defaults: [
|
||||
'_api_resource_class' => Connector::class,
|
||||
'_api_operation_name' => 'get_all_mine',
|
||||
],
|
||||
methods: ['GET']
|
||||
)]
|
||||
public function getConnector(): Collection
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
return $user->getConnectors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Route(
|
||||
path: '/api/connectors',
|
||||
name: 'connector_create',
|
||||
defaults: [
|
||||
'_api_resource_class' => Connector::class,
|
||||
'_api_operation_name' => 'create',
|
||||
],
|
||||
methods: ['POST']
|
||||
)]
|
||||
public function createConnector(Request $request): Connector
|
||||
{
|
||||
$connector = $this->serializer->deserialize($request->getContent(), Connector::class, 'json', ['groups' => 'connector:create']);
|
||||
$connector->setUser($this->getUser());
|
||||
|
||||
if ($connector->getProvider() === ConnectorProvider::OVH) {
|
||||
$connector->setAuthData(OvhConnector::verifyAuthData($connector->getAuthData()));
|
||||
} else throw new Exception('Unknown provider');
|
||||
|
||||
$this->em->persist($connector);
|
||||
$this->em->flush();
|
||||
|
||||
return $connector;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,32 +2,61 @@
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use App\Config\ConnectorProvider;
|
||||
use App\Repository\ConnectorRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\ORM\Mapping\DiscriminatorColumn;
|
||||
use Doctrine\ORM\Mapping\DiscriminatorMap;
|
||||
use Doctrine\ORM\Mapping\InheritanceType;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
#[ApiResource(
|
||||
shortName: 'Connector',
|
||||
operations: [
|
||||
new GetCollection(
|
||||
routeName: 'connector_get_all_mine',
|
||||
normalizationContext: ['groups' => 'connector:list'],
|
||||
name: 'get_all_mine',
|
||||
),
|
||||
new Get(
|
||||
normalizationContext: ['groups' => 'connector:list']
|
||||
),
|
||||
new Post(
|
||||
routeName: 'connector_create', normalizationContext: ['groups' => 'connector:create'],
|
||||
denormalizationContext: ['groups' => 'connector:create'],
|
||||
name: 'create'
|
||||
),
|
||||
new Patch(
|
||||
normalizationContext: ['groups' => 'connector:list'],
|
||||
denormalizationContext: ['groups' => 'connector:create']
|
||||
),
|
||||
new Delete()
|
||||
]
|
||||
)]
|
||||
#[ORM\Entity(repositoryClass: ConnectorRepository::class)]
|
||||
#[InheritanceType('SINGLE_TABLE')]
|
||||
#[DiscriminatorColumn(name: 'provider', enumType: ConnectorProvider::class)]
|
||||
#[DiscriminatorMap([ConnectorProvider::OVH->value => OVHConnector::class])]
|
||||
class Connector
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
private ?string $provider = null;
|
||||
#[ORM\Column(type: 'uuid')]
|
||||
#[Groups(['connector:list'])]
|
||||
private ?string $id;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'connectors')]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?User $user = null;
|
||||
|
||||
|
||||
#[Groups(['connector:list', 'connector:create'])]
|
||||
#[ORM\Column(enumType: ConnectorProvider::class)]
|
||||
private ?ConnectorProvider $provider = null;
|
||||
|
||||
#[Groups(['connector:create'])]
|
||||
#[ORM\Column]
|
||||
private array $authData = [];
|
||||
|
||||
@@ -37,28 +66,18 @@ class Connector
|
||||
#[ORM\OneToMany(targetEntity: WatchListTrigger::class, mappedBy: 'connector')]
|
||||
private Collection $watchListTriggers;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->id = Uuid::v4();
|
||||
$this->watchListTriggers = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getProvider(): ?string
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
public function setProvider(?string $provider): static
|
||||
{
|
||||
$this->provider = $provider;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
@@ -113,4 +132,16 @@ class Connector
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProvider(): ?ConnectorProvider
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
public function setProvider(ConnectorProvider $provider): static
|
||||
{
|
||||
$this->provider = $provider;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
/**
|
||||
* @var Collection<int, Connector>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Connector::class, mappedBy: 'userr', orphanRemoval: true)]
|
||||
#[ORM\OneToMany(targetEntity: Connector::class, mappedBy: 'user', orphanRemoval: true)]
|
||||
private Collection $connectors;
|
||||
|
||||
public function __construct()
|
||||
@@ -188,7 +188,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
{
|
||||
if (!$this->connectors->contains($connector)) {
|
||||
$this->connectors->add($connector);
|
||||
$connector->setUserr($this);
|
||||
$connector->setUser($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -198,8 +198,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
{
|
||||
if ($this->connectors->removeElement($connector)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($connector->getUserr() === $this) {
|
||||
$connector->setUserr(null);
|
||||
if ($connector->getUser() === $this) {
|
||||
$connector->setUser(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
namespace App\MessageHandler;
|
||||
|
||||
use App\Config\Connector\OvhConnector;
|
||||
use App\Config\ConnectorProvider;
|
||||
use App\Config\TriggerAction;
|
||||
use App\Entity\Domain;
|
||||
use App\Entity\DomainEvent;
|
||||
use App\Entity\OVHConnector;
|
||||
use App\Entity\User;
|
||||
use App\Entity\WatchList;
|
||||
use App\Entity\WatchListTrigger;
|
||||
@@ -14,6 +15,7 @@ use App\Repository\DomainRepository;
|
||||
use App\Repository\WatchListRepository;
|
||||
use Exception;
|
||||
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||
@@ -27,6 +29,7 @@ final readonly class ProcessDomainTriggerHandler
|
||||
private MailerInterface $mailer,
|
||||
private WatchListRepository $watchListRepository,
|
||||
private DomainRepository $domainRepository,
|
||||
private KernelInterface $kernel
|
||||
|
||||
)
|
||||
{
|
||||
@@ -58,9 +61,18 @@ final readonly class ProcessDomainTriggerHandler
|
||||
case TriggerAction::BuyDomain :
|
||||
if ($watchListTrigger->getConnector() === null) throw new Exception('Connector is missing');
|
||||
$connector = $watchListTrigger->getConnector();
|
||||
if ($connector::class === OVHConnector::class) {
|
||||
$connector->orderDomain($domain, true, true, true, true);
|
||||
}
|
||||
if ($connector->getProvider() === ConnectorProvider::OVH) {
|
||||
$ovh = new OVHConnector($connector->getAuthData());
|
||||
$isDebug = $this->kernel->isDebug();
|
||||
$ovh->orderDomain(
|
||||
$domain,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
$isDebug
|
||||
);
|
||||
|
||||
} else throw new Exception("Unknown provider");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\OVHConnector;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method OVHConnector|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method OVHConnector|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method OVHConnector[] findAll()
|
||||
* @method OVHConnector[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class OVHConnectorRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, OVHConnector::class);
|
||||
}
|
||||
}
|
||||
10
src/Service/ConnectorService.php
Normal file
10
src/Service/ConnectorService.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
readonly class ConnectorService
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user