diff --git a/assets/components/tracking/connector/ConnectorForm.tsx b/assets/components/tracking/connector/ConnectorForm.tsx index d76ee3b..e0dca7a 100644 --- a/assets/components/tracking/connector/ConnectorForm.tsx +++ b/assets/components/tracking/connector/ConnectorForm.tsx @@ -1,8 +1,8 @@ -import type { FormInstance} from 'antd' +import type {FormInstance} from 'antd' import {Alert, Button, Checkbox, Form, Input, Popconfirm, Select, Space, Typography} from 'antd' import React, {useState} from 'react' import type {Connector} from '../../../utils/api/connectors' -import { ConnectorProvider} from '../../../utils/api/connectors' +import {ConnectorProvider} from '../../../utils/api/connectors' import {t} from 'ttag' import {BankOutlined} from '@ant-design/icons' import { @@ -21,7 +21,7 @@ const formItemLayoutWithOutLabel = { } export function ConnectorForm({form, onCreate}: { form: FormInstance, onCreate: (values: Connector) => void }) { - const [provider, setProvider] = useState() + const [provider, setProvider] = useState() const ovhFields = ovhFieldsFunction() const ovhEndpointList = ovhEndpointListFunction() const ovhSubsidiaryList = ovhSubsidiaryListFunction() @@ -62,174 +62,191 @@ export function ConnectorForm({form, onCreate}: { form: FormInstance, onCreate: /> - { - provider === ConnectorProvider.OVH && <> - { - Object.keys(ovhFields).map(fieldName => - - ) - } - - - - - - { - form.resetFields(['authData']) - setOvhPricingModeValue(undefined) - setOpen(false) - }} - onConfirm={() => setOpen(false)} - open={open} - > - - - {t`It indicates the organization that will pay for the ordered product`} - } - required={false} - > - - - - } - { - provider === ConnectorProvider.AUTODNS && <> - -
- {t`Attention: AutoDNS do not support 2-Factor Authentication on API Users for automated systems`} - } - rules={[{required: true, message: t`Required`}]} - > - - - - - - {t`The nic-handle of the domain name owner`}{t`You can get it from this page`} - - } - rules={[{required: true, message: t`Required`}]} - required - > - - - - {t`If you not sure, use the default value 4`} - } - - required={false} - > - - - - - {t`Owner confirms his consent of domain order jobs`} - - - - - } - { - provider === ConnectorProvider.NAMECHEAP && <> - - - - - - - - } - { provider !== undefined && <> + { + [ConnectorProvider.AutoDNS, ConnectorProvider['Name.com']].includes(provider) && + } + { + provider === ConnectorProvider.OVHcloud && <> + { + Object.keys(ovhFields).map(fieldName => + + ) + } + + + + + + { + form.resetFields(['authData']) + setOvhPricingModeValue(undefined) + setOpen(false) + }} + onConfirm={() => setOpen(false)} + open={open} + > + + + {t`It indicates the organization that will pay for the ordered product`} + } + required={false} + > + + + + } + { + provider === ConnectorProvider.AutoDNS && <> +
+ {t`Attention: AutoDNS do not support 2-Factor Authentication on API Users for automated systems`} + } + rules={[{required: true, message: t`Required`}]} + > + + + + + + {t`The nic-handle of the domain name owner`}{t`You can get it from this page`} + + } + rules={[{required: true, message: t`Required`}]} + required + > + + + + {t`If you not sure, use the default value 4`} + } + + required={false} + > + + + + {t`Owner confirms his consent of domain order jobs`} + + + + + } + { + provider === ConnectorProvider.Namecheap && <> + + + + + + + + } + { + provider === ConnectorProvider['Name.com'] && <> + + + + + + + + } const {watchlistCount} = connector + const connectorName = Object.keys(ConnectorProvider).find(p => ConnectorProvider[p as keyof typeof ConnectorProvider] === connector.provider) return <> {contextHolder} - {t`Connector ${connector.provider}`}{connector.id} + {t`Connector ${connectorName}`}{connector.id} } size='small' style={{width: '100%'}} @@ -44,8 +46,16 @@ export function ConnectorsList({connectors, onDelete}: { connectors: ConnectorEl > {jt`Creation date: ${createdAt}`} {t`Used in: ${watchlistCount} Watchlist`} - + + {t`You can stop using a connector at any time. To delete a connector, you must remove it from each linked Watchlist. +The creation date corresponds to the date on which you consented to the creation of the connector and on which you declared in particular that you fulfilled the conditions of use of the supplier's API, waived the right of withdrawal and were of the minimum age to consent to these conditions.`} +   + + {t`The Provider’s conditions are accessible by following this hyperlink.`} + + + }/> diff --git a/assets/utils/api/connectors.ts b/assets/utils/api/connectors.ts index ffa3721..a5aa58d 100644 --- a/assets/utils/api/connectors.ts +++ b/assets/utils/api/connectors.ts @@ -2,10 +2,11 @@ import {request} from './index' import type {ConnectorElement} from '../../components/tracking/connector/ConnectorsList' export enum ConnectorProvider { - OVH = 'ovh', - GANDI = 'gandi', - AUTODNS = 'autodns', - NAMECHEAP = 'namecheap' + OVHcloud = 'ovh', + Gandi = 'gandi', + AutoDNS = 'autodns', + Namecheap = 'namecheap', + 'Name.com' = 'namecom' } export interface Connector { diff --git a/assets/utils/providers/index.tsx b/assets/utils/providers/index.tsx index 5739b43..a7e877b 100644 --- a/assets/utils/providers/index.tsx +++ b/assets/utils/providers/index.tsx @@ -5,7 +5,7 @@ import React from 'react' export const helpGetTokenLink = (provider?: string) => { switch (provider) { - case ConnectorProvider.OVH: + case ConnectorProvider.OVHcloud: return ( { ) - case ConnectorProvider.GANDI: + case ConnectorProvider.Gandi: return ( {t`Retrieve a Personal Access Token from your customer account on the Provider's website`} ) - case ConnectorProvider.NAMECHEAP: + case ConnectorProvider.Namecheap: return ( {t`Retreive an API key and whitelist this instance's IP address on Namecheap's website`} ) - case ConnectorProvider.AUTODNS: + case ConnectorProvider.AutoDNS: return ( {t`Because of some limitations in API of AutoDNS, we suggest to create an dedicated user for API with limited rights`} ) + case ConnectorProvider['Name.com']: + return ( + + {t`Retrieve a set of tokens from your customer account on the Provider's website`} + + ) default: return <> } @@ -40,14 +46,16 @@ export const helpGetTokenLink = (provider?: string) => { export const tosHyperlink = (provider?: string) => { switch (provider) { - case ConnectorProvider.OVH: - return 'https://www.ovhcloud.com/fr/terms-and-conditions/contracts/' - case ConnectorProvider.GANDI: + case ConnectorProvider.OVHcloud: + return 'https://www.ovhcloud.com/en/terms-and-conditions/contracts/' + case ConnectorProvider.Gandi: return 'https://www.gandi.net/en/contracts/terms-of-service' - case ConnectorProvider.NAMECHEAP: + case ConnectorProvider.Namecheap: return 'https://www.namecheap.com/legal/universal/universal-tos/' - case ConnectorProvider.AUTODNS: + case ConnectorProvider.AutoDNS: return 'https://www.internetx.com/agb/' + case ConnectorProvider['Name.com']: + return 'https://www.name.com/policies/' default: return '' } diff --git a/src/Config/ConnectorProvider.php b/src/Config/ConnectorProvider.php index 6051556..78f634d 100644 --- a/src/Config/ConnectorProvider.php +++ b/src/Config/ConnectorProvider.php @@ -5,6 +5,7 @@ namespace App\Config; use App\Service\Connector\AutodnsProvider; use App\Service\Connector\GandiProvider; use App\Service\Connector\NamecheapProvider; +use App\Service\Connector\NameComProvider; use App\Service\Connector\OvhProvider; enum ConnectorProvider: string @@ -13,6 +14,7 @@ enum ConnectorProvider: string case GANDI = 'gandi'; case AUTODNS = 'autodns'; case NAMECHEAP = 'namecheap'; + case NAMECOM = 'namecom'; public function getConnectorProvider(): string { @@ -21,6 +23,7 @@ enum ConnectorProvider: string ConnectorProvider::GANDI => GandiProvider::class, ConnectorProvider::AUTODNS => AutodnsProvider::class, ConnectorProvider::NAMECHEAP => NamecheapProvider::class, + ConnectorProvider::NAMECOM => NameComProvider::class, }; } } diff --git a/src/Entity/Domain.php b/src/Entity/Domain.php index fa005ad..b4bd545 100644 --- a/src/Entity/Domain.php +++ b/src/Entity/Domain.php @@ -131,8 +131,6 @@ class Domain 'pending transfer', 'pending update', 'add period', - 'client hold', - 'server hold', ]; public function __construct() diff --git a/src/Service/Connector/NameComProvider.php b/src/Service/Connector/NameComProvider.php new file mode 100644 index 0000000..88a8dbb --- /dev/null +++ b/src/Service/Connector/NameComProvider.php @@ -0,0 +1,130 @@ +getLdhName(); + if (!$ldhName) { + throw new \InvalidArgumentException('Domain name cannot be null'); + } + + $this->client->request( + 'POST', + '/v4/domains', + (new HttpOptions()) + ->setHeader('Accept', 'application/json') + ->setAuthBasic($this->authData['username'], $this->authData['token']) + ->setBaseUri($dryRun ? self::DEV_BASE_URL : self::BASE_URL) + ->setJson([ + 'domain' => [ + [ + 'domainName' => $domain->getLdhName(), + // 'contacts' => [], + // 'privacyEnabled' => false, + 'locked' => false, + 'autorenewEnabled' => false, + ], + // 'purchasePrice' => 0, + 'purchaseType' => 'registration', + 'years' => 1, + // 'tldRequirements' => [] + ], + ]) + ->toArray() + )->toArray(); + } + + public function verifySpecificAuthData(array $authData): array + { + $username = $authData['username']; + $token = $authData['token']; + + if ( + !is_string($username) || empty($username) + || !is_string($token) || empty($token) + ) { + throw new BadRequestHttpException('Bad authData schema'); + } + + return [ + 'username' => $authData['username'], + 'token' => $authData['token'], + ]; + } + + public function isSupported(Domain ...$domainList): bool + { + return true; + } + + protected function getSupportedTldList(): array + { + return []; + } + + /** + * @throws InvalidArgumentException + */ + protected function getCachedTldList(): CacheItemInterface + { + return $this->cacheItemPool->getItem('app.provider.namecom.supported-tld'); + } + + /** + * @throws TransportExceptionInterface + */ + 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'); + } + + if (Response::HTTP_OK !== $response->getStatusCode()) { + throw new BadRequestHttpException('The status of these credentials is not valid'); + } + } +}