From a45b93cd27aaf9de3452b8bfc5d71dd047a80952 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Wed, 21 Dec 2022 23:31:03 +0400 Subject: [PATCH] feat: Improve Dns Record structure and logic It is to much digital ocean api. The decision with adding optional id is bad, but it will be refactored soon along with entire backend. --- .../dns_providers/cloudflare/cloudflare.dart | 50 +------ .../digital_ocean_dns/digital_ocean_dns.dart | 125 ++++++------------ .../rest_maps/dns_providers/dns_provider.dart | 47 +++++++ lib/logic/models/json/dns_records.dart | 4 + 4 files changed, 94 insertions(+), 132 deletions(-) diff --git a/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare.dart b/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare.dart index 04ff622b..433ee792 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare.dart @@ -196,7 +196,8 @@ class CloudflareApi extends DnsProviderApi { }) async { final String domainName = domain.domainName; final String domainZoneId = domain.zoneId; - final List listDnsRecords = projectDnsRecords(domainName, ip4); + final List listDnsRecords = + getProjectDnsRecords(domainName, ip4); final List allCreateFutures = []; final Dio client = await getClient(); @@ -227,53 +228,6 @@ class CloudflareApi extends DnsProviderApi { return APIGenericResult(success: true, data: null); } - List projectDnsRecords( - final String? domainName, - final String? ip4, - ) { - final DnsRecord domainA = - DnsRecord(type: 'A', name: domainName, content: ip4); - - final DnsRecord mx = DnsRecord(type: 'MX', name: '@', content: domainName); - final DnsRecord apiA = DnsRecord(type: 'A', name: 'api', content: ip4); - final DnsRecord cloudA = DnsRecord(type: 'A', name: 'cloud', content: ip4); - final DnsRecord gitA = DnsRecord(type: 'A', name: 'git', content: ip4); - final DnsRecord meetA = DnsRecord(type: 'A', name: 'meet', content: ip4); - final DnsRecord passwordA = - DnsRecord(type: 'A', name: 'password', content: ip4); - final DnsRecord socialA = - DnsRecord(type: 'A', name: 'social', content: ip4); - final DnsRecord vpn = DnsRecord(type: 'A', name: 'vpn', content: ip4); - - final DnsRecord txt1 = DnsRecord( - type: 'TXT', - name: '_dmarc', - content: 'v=DMARC1; p=none', - ttl: 18000, - ); - - final DnsRecord txt2 = DnsRecord( - type: 'TXT', - name: domainName, - content: 'v=spf1 a mx ip4:$ip4 -all', - ttl: 18000, - ); - - return [ - domainA, - apiA, - cloudA, - gitA, - meetA, - passwordA, - socialA, - mx, - txt1, - txt2, - vpn - ]; - } - @override Future setDnsRecord( final DnsRecord record, diff --git a/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns.dart b/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns.dart index a633fa65..887dc1ca 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns.dart @@ -102,23 +102,15 @@ class DigitalOceanDnsApi extends DnsProviderApi { final String? ip4, }) async { final String domainName = domain.domainName; - final String domainZoneId = domain.zoneId; - - final String url = '/zones/$domainZoneId/dns_records'; final Dio client = await getClient(); try { - final Response response = await client.get(url); - - final List records = response.data['result'] ?? []; - final List allDeleteFutures = []; - + final List allDeleteFutures = []; + final List records = await getDnsRecords(domain: domain); for (final record in records) { - if (record['zone_name'] == domainName) { - allDeleteFutures.add( - client.delete('$url/${record["id"]}'), - ); - } + allDeleteFutures.add( + client.delete('/domains/$domainName/records/${record.id}'), + ); } await Future.wait(allDeleteFutures); } catch (e) { @@ -141,28 +133,31 @@ class DigitalOceanDnsApi extends DnsProviderApi { }) async { Response response; final String domainName = domain.domainName; - final String domainZoneId = domain.zoneId; final List allRecords = []; - final String url = '/zones/$domainZoneId/dns_records'; + /// Default amount is 20, but we will eventually overflow it, + /// so I hardcode it to the maximum available amount in advance just in case + /// + /// https://docs.digitalocean.com/reference/api/api-reference/#operation/domains_list_records + const int amountPerPage = 200; + final String url = '/domains/$domainName/records?per_page=$amountPerPage'; final Dio client = await getClient(); try { response = await client.get(url); - final List records = response.data['result'] ?? []; + final List records = response.data['domain_records'] ?? []; for (final record in records) { - if (record['zone_name'] == domainName) { - allRecords.add( - DnsRecord( - name: record['name'], - type: record['type'], - content: record['content'], - ttl: record['ttl'], - proxied: record['proxied'], - ), - ); - } + allRecords.add( + DnsRecord( + id: record['id'], + name: record['name'], + type: record['type'], + content: record['data'], + ttl: record['ttl'], + proxied: false, + ), + ); } } catch (e) { print(e); @@ -179,17 +174,22 @@ class DigitalOceanDnsApi extends DnsProviderApi { final String? ip4, }) async { final String domainName = domain.domainName; - final String domainZoneId = domain.zoneId; - final List listDnsRecords = projectDnsRecords(domainName, ip4); + final List dnsRecords = getProjectDnsRecords(domainName, ip4); final List allCreateFutures = []; final Dio client = await getClient(); try { - for (final DnsRecord record in listDnsRecords) { + for (final DnsRecord record in dnsRecords) { allCreateFutures.add( client.post( - '/zones/$domainZoneId/dns_records', - data: record.toJson(), + '/domains/$domainName/records', + data: { + 'type': record.type, + 'name': record.name, + 'data': record.content, + 'ttl': record.ttl, + 'priority': record.priority, + }, ), ); } @@ -211,66 +211,23 @@ class DigitalOceanDnsApi extends DnsProviderApi { return APIGenericResult(success: true, data: null); } - List projectDnsRecords( - final String? domainName, - final String? ip4, - ) { - final DnsRecord domainA = - DnsRecord(type: 'A', name: domainName, content: ip4); - - final DnsRecord mx = DnsRecord(type: 'MX', name: '@', content: domainName); - final DnsRecord apiA = DnsRecord(type: 'A', name: 'api', content: ip4); - final DnsRecord cloudA = DnsRecord(type: 'A', name: 'cloud', content: ip4); - final DnsRecord gitA = DnsRecord(type: 'A', name: 'git', content: ip4); - final DnsRecord meetA = DnsRecord(type: 'A', name: 'meet', content: ip4); - final DnsRecord passwordA = - DnsRecord(type: 'A', name: 'password', content: ip4); - final DnsRecord socialA = - DnsRecord(type: 'A', name: 'social', content: ip4); - final DnsRecord vpn = DnsRecord(type: 'A', name: 'vpn', content: ip4); - - final DnsRecord txt1 = DnsRecord( - type: 'TXT', - name: '_dmarc', - content: 'v=DMARC1; p=none', - ttl: 18000, - ); - - final DnsRecord txt2 = DnsRecord( - type: 'TXT', - name: domainName, - content: 'v=spf1 a mx ip4:$ip4 -all', - ttl: 18000, - ); - - return [ - domainA, - apiA, - cloudA, - gitA, - meetA, - passwordA, - socialA, - mx, - txt1, - txt2, - vpn - ]; - } - @override Future setDnsRecord( final DnsRecord record, final ServerDomain domain, ) async { - final String domainZoneId = domain.zoneId; - final String url = '$rootAddress/zones/$domainZoneId/dns_records'; - final Dio client = await getClient(); try { + final domainName = domain.domainName; await client.post( - url, - data: record.toJson(), + '/domains/$domainName/records', + data: { + 'type': record.type, + 'name': record.name, + 'data': record.content, + 'ttl': record.ttl, + 'priority': record.priority, + }, ); } catch (e) { print(e); diff --git a/lib/logic/api_maps/rest_maps/dns_providers/dns_provider.dart b/lib/logic/api_maps/rest_maps/dns_providers/dns_provider.dart index 106d185c..ce308121 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/dns_provider.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/dns_provider.dart @@ -31,4 +31,51 @@ abstract class DnsProviderApi extends ApiMap { Future> isApiTokenValid(final String token); RegExp getApiTokenValidation(); + + List getProjectDnsRecords( + final String? domainName, + final String? ip4, + ) { + final DnsRecord domainA = + DnsRecord(type: 'A', name: domainName, content: ip4); + + final DnsRecord mx = DnsRecord(type: 'MX', name: '@', content: domainName); + final DnsRecord apiA = DnsRecord(type: 'A', name: 'api', content: ip4); + final DnsRecord cloudA = DnsRecord(type: 'A', name: 'cloud', content: ip4); + final DnsRecord gitA = DnsRecord(type: 'A', name: 'git', content: ip4); + final DnsRecord meetA = DnsRecord(type: 'A', name: 'meet', content: ip4); + final DnsRecord passwordA = + DnsRecord(type: 'A', name: 'password', content: ip4); + final DnsRecord socialA = + DnsRecord(type: 'A', name: 'social', content: ip4); + final DnsRecord vpn = DnsRecord(type: 'A', name: 'vpn', content: ip4); + + final DnsRecord txt1 = DnsRecord( + type: 'TXT', + name: '_dmarc', + content: 'v=DMARC1; p=none', + ttl: 18000, + ); + + final DnsRecord txt2 = DnsRecord( + type: 'TXT', + name: domainName, + content: 'v=spf1 a mx ip4:$ip4 -all', + ttl: 18000, + ); + + return [ + domainA, + apiA, + cloudA, + gitA, + meetA, + passwordA, + socialA, + mx, + txt1, + txt2, + vpn + ]; + } } diff --git a/lib/logic/models/json/dns_records.dart b/lib/logic/models/json/dns_records.dart index c4799876..1680e943 100644 --- a/lib/logic/models/json/dns_records.dart +++ b/lib/logic/models/json/dns_records.dart @@ -9,6 +9,7 @@ class DnsRecord { required this.type, required this.name, required this.content, + this.id, this.ttl = 3600, this.priority = 10, this.proxied = false, @@ -31,5 +32,8 @@ class DnsRecord { final int priority; final bool proxied; + /// TODO: Refactoring refactoring refactoring refactoring >:c + final int? id; + Map toJson() => _$DnsRecordToJson(this); }