diff --git a/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart b/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart index 0ba88ee3..2b1711e4 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart @@ -4,7 +4,7 @@ import 'package:dio/dio.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/api_maps/generic_result.dart'; import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart'; -import 'package:selfprivacy/logic/models/json/cloudflare_dns_info.dart'; +import 'package:selfprivacy/logic/models/json/dns_providers/cloudflare_dns_info.dart'; class CloudflareApi extends RestApiMap { CloudflareApi({ diff --git a/lib/logic/models/json/dns_providers/cloudflare_dns_adapter.dart b/lib/logic/models/json/dns_providers/cloudflare_dns_adapter.dart new file mode 100644 index 00000000..8132fde2 --- /dev/null +++ b/lib/logic/models/json/dns_providers/cloudflare_dns_adapter.dart @@ -0,0 +1,27 @@ +part of 'cloudflare_dns_info.dart'; + +CloudflareDnsRecord _fromDnsRecord( + final DnsRecord dnsRecord, + final String rootDomain, +) => + CloudflareDnsRecord( + content: dnsRecord.content, + name: dnsRecord.name, + type: dnsRecord.type, + zoneName: rootDomain, + id: null, + ttl: dnsRecord.ttl, + ); + +DnsRecord _toDnsRecord(final CloudflareDnsRecord cloudflareRecord) => DnsRecord( + content: cloudflareRecord.content, + name: cloudflareRecord.name, + type: cloudflareRecord.type, + ttl: cloudflareRecord.ttl, + ); + +ServerDomain _toServerDomain(final CloudflareZone cloudflareZone) => + ServerDomain( + domainName: cloudflareZone.name, + provider: DnsProviderType.cloudflare, + ); diff --git a/lib/logic/models/json/cloudflare_dns_info.dart b/lib/logic/models/json/dns_providers/cloudflare_dns_info.dart similarity index 82% rename from lib/logic/models/json/cloudflare_dns_info.dart rename to lib/logic/models/json/dns_providers/cloudflare_dns_info.dart index 3cd11bcd..362124d6 100644 --- a/lib/logic/models/json/cloudflare_dns_info.dart +++ b/lib/logic/models/json/dns_providers/cloudflare_dns_info.dart @@ -1,6 +1,9 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:selfprivacy/logic/models/hive/server_domain.dart'; +import 'package:selfprivacy/logic/models/json/dns_records.dart'; part 'cloudflare_dns_info.g.dart'; +part 'cloudflare_dns_adapter.dart'; /// https://developers.cloudflare.com/api/operations/zones-get @JsonSerializable() @@ -26,6 +29,7 @@ class CloudflareZone { static CloudflareZone fromJson(final Map json) => _$CloudflareZoneFromJson(json); + ServerDomain toServerDomain() => _toServerDomain(this); } /// https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-list-dns-records @@ -41,6 +45,12 @@ class CloudflareDnsRecord { this.id, }); + factory CloudflareDnsRecord.fromDnsRecord( + final DnsRecord dnsRecord, + final String rootDomain, + ) => + _fromDnsRecord(dnsRecord, rootDomain); + /// Record identifier /// /// `<= 32 characters` @@ -83,4 +93,5 @@ class CloudflareDnsRecord { static CloudflareDnsRecord fromJson(final Map json) => _$CloudflareDnsRecordFromJson(json); Map toJson() => _$CloudflareDnsRecordToJson(this); + DnsRecord toDnsRecord() => _toDnsRecord(this); } diff --git a/lib/logic/models/json/cloudflare_dns_info.g.dart b/lib/logic/models/json/dns_providers/cloudflare_dns_info.g.dart similarity index 100% rename from lib/logic/models/json/cloudflare_dns_info.g.dart rename to lib/logic/models/json/dns_providers/cloudflare_dns_info.g.dart diff --git a/lib/logic/providers/dns_providers/cloudflare.dart b/lib/logic/providers/dns_providers/cloudflare.dart index 6cf4a494..b34deca9 100644 --- a/lib/logic/providers/dns_providers/cloudflare.dart +++ b/lib/logic/providers/dns_providers/cloudflare.dart @@ -1,9 +1,10 @@ import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart'; import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart'; import 'package:selfprivacy/logic/models/hive/server_domain.dart'; -import 'package:selfprivacy/logic/models/json/cloudflare_dns_info.dart'; +import 'package:selfprivacy/logic/models/json/dns_providers/cloudflare_dns_info.dart'; import 'package:selfprivacy/logic/models/json/dns_records.dart'; import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart'; +import 'package:selfprivacy/utils/network_utils.dart'; class ApiAdapter { ApiAdapter({ @@ -51,8 +52,8 @@ class CloudflareDnsProvider extends DnsProvider { } @override - Future>> domainList() async { - List domains = []; + Future>> domainList() async { + List domains = []; final result = await _adapter.api().getZones(); if (result.data.isEmpty || !result.success) { return GenericResult( @@ -64,8 +65,8 @@ class CloudflareDnsProvider extends DnsProvider { } domains = result.data - .map( - (final el) => el.name, + .map( + (final el) => el.toServerDomain(), ) .toList(); @@ -90,14 +91,8 @@ class CloudflareDnsProvider extends DnsProvider { zoneId: _adapter.cachedZoneId, records: records .map( - (final rec) => CloudflareDnsRecord( - content: rec.content, - name: rec.name, - type: rec.type, - zoneName: domain.domainName, - id: null, - ttl: rec.ttl, - ), + (final rec) => + CloudflareDnsRecord.fromDnsRecord(rec, domain.domainName), ) .toList(), ); @@ -157,14 +152,7 @@ class CloudflareDnsProvider extends DnsProvider { } for (final rawRecord in result.data) { - records.add( - DnsRecord( - name: rawRecord.name, - type: rawRecord.type, - content: rawRecord.content, - ttl: rawRecord.ttl, - ), - ); + records.add(rawRecord.toDnsRecord()); } return GenericResult( @@ -185,16 +173,7 @@ class CloudflareDnsProvider extends DnsProvider { return _adapter.api().createMultipleDnsRecords( zoneId: _adapter.cachedZoneId, - records: [ - CloudflareDnsRecord( - content: record.content, - id: null, - name: record.name, - type: record.type, - zoneName: domain.domainName, - ttl: record.ttl, - ), - ], + records: [CloudflareDnsRecord.fromDnsRecord(record, domain.domainName)], ); } @@ -203,15 +182,18 @@ class CloudflareDnsProvider extends DnsProvider { final ServerDomain domain, final String ip4, final String dkimPublicKey, + final List pendingDnsRecords, ) async { final GenericResult> records = await getDnsRecords(domain: domain); final List foundRecords = []; try { - final List desiredRecords = - getDesiredDnsRecords(domain.domainName, ip4, dkimPublicKey); - for (final DesiredDnsRecord record in desiredRecords) { - if (record.description == 'record.dkim') { + for (final DnsRecord pendingDnsRecord in pendingDnsRecords) { + final record = CloudflareDnsRecord.fromDnsRecord( + pendingDnsRecord, + domain.domainName, + ); + if (record.name == 'selector._domainkey') { final DnsRecord foundRecord = records.data.firstWhere( (final r) => (r.name == record.name) && r.type == record.type, orElse: () => DnsRecord( @@ -227,23 +209,29 @@ class CloudflareDnsProvider extends DnsProvider { // to compare them final String? foundContent = foundRecord.content?.replaceAll(RegExp(r'\s+'), ''); - final String content = record.content.replaceAll(RegExp(r'\s+'), ''); - if (foundContent == content) { - foundRecords.add(record.copyWith(isSatisfied: true)); - } else { - foundRecords.add(record.copyWith(isSatisfied: false)); - } + final String content = + record.content?.replaceAll(RegExp(r'\s+'), '') ?? ''; + foundRecords.add( + DesiredDnsRecord( + name: record.name ?? '', + content: record.content ?? '', + isSatisfied: foundContent == content, + ), + ); } else { - if (records.data.any( + final foundMatch = records.data.any( (final r) => (r.name == record.name) && r.type == record.type && r.content == record.content, - )) { - foundRecords.add(record.copyWith(isSatisfied: true)); - } else { - foundRecords.add(record.copyWith(isSatisfied: false)); - } + ); + foundRecords.add( + DesiredDnsRecord( + name: record.name ?? '', + content: record.content ?? '', + isSatisfied: foundMatch, + ), + ); } } } catch (e) { @@ -260,135 +248,6 @@ class CloudflareDnsProvider extends DnsProvider { ); } - @override - List getDesiredDnsRecords( - final String? domainName, - final String? ip4, - final String? dkimPublicKey, - ) { - if (domainName == null || ip4 == null) { - return []; - } - return [ - DesiredDnsRecord( - name: domainName, - content: ip4, - description: 'record.root', - ), - DesiredDnsRecord( - name: 'api.$domainName', - content: ip4, - description: 'record.api', - ), - DesiredDnsRecord( - name: 'cloud.$domainName', - content: ip4, - description: 'record.cloud', - ), - DesiredDnsRecord( - name: 'git.$domainName', - content: ip4, - description: 'record.git', - ), - DesiredDnsRecord( - name: 'meet.$domainName', - content: ip4, - description: 'record.meet', - ), - DesiredDnsRecord( - name: 'social.$domainName', - content: ip4, - description: 'record.social', - ), - DesiredDnsRecord( - name: 'password.$domainName', - content: ip4, - description: 'record.password', - ), - DesiredDnsRecord( - name: 'vpn.$domainName', - content: ip4, - description: 'record.vpn', - ), - DesiredDnsRecord( - name: domainName, - content: domainName, - description: 'record.mx', - type: 'MX', - category: DnsRecordsCategory.email, - ), - DesiredDnsRecord( - name: '_dmarc.$domainName', - content: 'v=DMARC1; p=none', - description: 'record.dmarc', - type: 'TXT', - category: DnsRecordsCategory.email, - ), - DesiredDnsRecord( - name: domainName, - content: 'v=spf1 a mx ip4:$ip4 -all', - description: 'record.spf', - type: 'TXT', - category: DnsRecordsCategory.email, - ), - if (dkimPublicKey != null) - DesiredDnsRecord( - name: 'selector._domainkey.$domainName', - content: dkimPublicKey, - description: 'record.dkim', - type: 'TXT', - category: DnsRecordsCategory.email, - ), - ]; - } - - 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 - ]; - } - Future> syncZoneId(final String domain) async { if (domain == _adapter.cachedDomain && _adapter.cachedZoneId.isNotEmpty) { return GenericResult(