diff --git a/.env b/.env index 221b2c4..7ae15ac 100644 --- a/.env +++ b/.env @@ -67,6 +67,11 @@ OAUTH_TOKEN_URL= OAUTH_USERINFO_URL= OAUTH_SCOPE= +# Typically your IP address, this envvar is required for +# some connectors that need to be provided with your host's +# outgoing IP address. +OUTGOING_IP= + LIMITED_FEATURES=false LIMIT_MAX_WATCHLIST=0 LIMIT_MAX_WATCHLIST_DOMAINS=0 diff --git a/assets/utils/api/connectors.ts b/assets/utils/api/connectors.ts index c1e87f5..7fd692d 100644 --- a/assets/utils/api/connectors.ts +++ b/assets/utils/api/connectors.ts @@ -2,7 +2,8 @@ import {request} from "./index"; export enum ConnectorProvider { OVH = 'ovh', - GANDI = 'gandi' + GANDI = 'gandi', + NAMECHEAP = 'namecheap' } export type Connector = { diff --git a/assets/utils/providers/index.tsx b/assets/utils/providers/index.tsx index 6867436..ce6beb1 100644 --- a/assets/utils/providers/index.tsx +++ b/assets/utils/providers/index.tsx @@ -15,6 +15,10 @@ export const helpGetTokenLink = (provider?: string) => { return {t`Retrieve a Personal Access Token from your customer account on the Provider's website`} + case ConnectorProvider.NAMECHEAP: + return + {t`Retreive an API key and whitelist this instance's IP address on Namecheap's website`} + default: return <> diff --git a/config/services.yaml b/config/services.yaml index bc8ea08..ac49546 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -21,6 +21,7 @@ services: bind: $mailerSenderEmail: '%mailer_sender_email%' $mailerSenderName: '%mailer_sender_name%' + $outgoingIp: '%env(string:OUTGOING_IP)%' # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name diff --git a/src/Service/Connector/NamecheapConnector.php b/src/Service/Connector/NamecheapConnector.php index 609182d..3e70f0f 100644 --- a/src/Service/Connector/NamecheapConnector.php +++ b/src/Service/Connector/NamecheapConnector.php @@ -11,20 +11,20 @@ class NamecheapConnector extends AbstractConnector public const SANDBOX_BASE_URL = 'http://api.sandbox.namecheap.com/xml.response'; - public function __construct(private HttpClientInterface $client) + public function __construct(private HttpClientInterface $client, private string $outgoingIp) { } public function orderDomain(Domain $domain, $dryRun): void { - $addresses = $this->call('namecheap.users.address.getList'); + $addresses = $this->call('namecheap.users.address.getList', [], $dryRun); if (count($addresses) < 1) { throw new \Exception('Namecheap account requires at least one address to purchase a domain'); } $addressId = $addresses->{0}->AddressId; - $address = $this->call('namecheap.users.address.getinfo', ['AddressId' => $addressId]); + $address = $this->call('namecheap.users.address.getinfo', ['AddressId' => $addressId], $dryRun); $domainAddresses = []; @@ -38,30 +38,26 @@ class NamecheapConnector extends AbstractConnector 'Years' => 1, 'AddFreeWhoisguard' => 'yes', 'WGEnabled' => 'yes', - ], $domainAddresses)); + ], $domainAddresses), $dryRun); } private static function mergePrefixKeys(string $prefix, array|object $src, array &$dest) { foreach ($src as $key => $value) { - $dest[$prefix.$key] = $value; + $dest[$prefix . $key] = $value; } } - private function call(string $command, array $parameters = [], ?array $authData = null): object + private function call(string $command, array $parameters = [], bool $dryRun = true): object { - if (is_null($authData)) { - $authData = $this->authData; - } - $actualParams = array_merge([ 'Command' => $command, - 'ApiUser' => $authData['ApiUser'], - 'ApiKey' => $authData['ApiKey'], - 'ClientIp' => '', // TODO DW instance IP envvar + 'ApiUser' => $this->authData['ApiUser'], + 'ApiKey' => $this->authData['ApiKey'], + 'ClientIp' => $this->outgoingIp, ], $parameters); - $response = $this->client->request('POST', self::BASE_URL, [ + $response = $this->client->request('POST', $dryRun ? self::SANDBOX_BASE_URL : self::BASE_URL, [ 'query' => $actualParams, ]);