refactor(digital-ocean-dns): Implement basic DTO for Digital Ocean DNS to avoid dynamic objects

pull/247/head
NaiJi ✨ 2023-07-27 20:55:32 -03:00
parent 146350f8f4
commit ccac0ff7fa
4 changed files with 167 additions and 41 deletions

View File

@ -4,8 +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/hive/server_domain.dart';
import 'package:selfprivacy/logic/models/json/dns_records.dart';
import 'package:selfprivacy/logic/models/json/digital_ocean_dns_info.dart';
class DigitalOceanDnsApi extends RestApiMap {
DigitalOceanDnsApi({
@ -92,13 +91,17 @@ class DigitalOceanDnsApi extends RestApiMap {
);
}
Future<GenericResult<List>> getDomains() async {
List domains = [];
Future<GenericResult<List<DigitalOceanDomain>>> getDomains() async {
List<DigitalOceanDomain> domains = [];
final Dio client = await getClient();
try {
final Response response = await client.get('/domains');
domains = response.data['domains'];
domains = response.data['domains']!
.map<DigitalOceanDomain>(
(final e) => DigitalOceanDomain.fromJson(e),
)
.toList();
} catch (e) {
print(e);
return GenericResult(
@ -114,25 +117,18 @@ class DigitalOceanDnsApi extends RestApiMap {
}
Future<GenericResult<void>> createMultipleDnsRecords({
required final ServerDomain domain,
required final List<DnsRecord> records,
required final String domainName,
required final List<DigitalOceanDnsRecord> records,
}) async {
final String domainName = domain.domainName;
final List<Future> allCreateFutures = <Future>[];
final Dio client = await getClient();
try {
for (final DnsRecord record in records) {
for (final DigitalOceanDnsRecord record in records) {
allCreateFutures.add(
client.post(
'/domains/$domainName/records',
data: {
'type': record.type,
'name': record.name,
'data': record.content,
'ttl': record.ttl,
'priority': record.priority,
},
data: record.toJson(),
),
);
}
@ -155,17 +151,15 @@ class DigitalOceanDnsApi extends RestApiMap {
}
Future<GenericResult<void>> removeSimilarRecords({
required final ServerDomain domain,
required final List records,
required final String domainName,
required final List<DigitalOceanDnsRecord> records,
}) async {
final String domainName = domain.domainName;
final Dio client = await getClient();
try {
final List<Future> allDeleteFutures = [];
for (final record in records) {
allDeleteFutures.add(
client.delete("/domains/$domainName/records/${record['id']}"),
client.delete('/domains/$domainName/records/${record.id}'),
);
}
await Future.wait(allDeleteFutures);
@ -183,12 +177,11 @@ class DigitalOceanDnsApi extends RestApiMap {
return GenericResult(success: true, data: null);
}
Future<GenericResult<List>> getDnsRecords({
required final ServerDomain domain,
}) async {
Future<GenericResult<List<DigitalOceanDnsRecord>>> getDnsRecords(
final String domainName,
) async {
Response response;
final String domainName = domain.domainName;
List allRecords = [];
List<DigitalOceanDnsRecord> allRecords = [];
/// Default amount is 20, but we will eventually overflow it,
/// so I hardcode it to the maximum available amount in advance just in case
@ -200,7 +193,12 @@ class DigitalOceanDnsApi extends RestApiMap {
final Dio client = await getClient();
try {
response = await client.get(url);
allRecords = response.data['domain_records'] ?? [];
allRecords = response.data['domain_records']
.map<DigitalOceanDnsRecord>(
(final e) => DigitalOceanDnsRecord.fromJson(e),
)
.toList() ??
[];
} catch (e) {
print(e);
GenericResult(

View File

@ -0,0 +1,66 @@
import 'package:json_annotation/json_annotation.dart';
part 'digital_ocean_dns_info.g.dart';
/// https://docs.digitalocean.com/reference/api/api-reference/#tag/Domains
@JsonSerializable()
class DigitalOceanDomain {
DigitalOceanDomain({
required this.name,
this.ttl,
});
/// The name of the domain itself.
/// This should follow the standard domain format of domain.TLD.
///
/// For instance, example.com is a valid domain name.
final String name;
/// This value is the time to live for the records on this domain, in seconds.
///
/// This defines the time frame that clients can cache queried information before a refresh should be requested.
final int? ttl;
static DigitalOceanDomain fromJson(final Map<String, dynamic> json) =>
_$DigitalOceanDomainFromJson(json);
}
/// https://docs.digitalocean.com/reference/api/api-reference/#tag/Domain-Records
@JsonSerializable()
class DigitalOceanDnsRecord {
DigitalOceanDnsRecord({
required this.id,
required this.name,
required this.type,
required this.ttl,
required this.data,
this.priority,
});
/// A unique identifier for each domain record.
final int? id;
/// The host name, alias, or service being defined by the record.
final String name;
/// The type of the DNS record. For example: A, CNAME, TXT, ...
final String type;
/// This value is the time to live for the record, in seconds.
///
/// This defines the time frame that clients can cache queried information before a refresh should be requested.
final int ttl;
/// Variable data depending on record type.
///
/// For example, the "data" value for an A record would be the IPv4 address to which the domain will be mapped.
/// For a CAA record, it would contain the domain name of the CA being granted permission to issue certificates.
final String data;
/// The priority for SRV and MX records.
final int? priority;
static DigitalOceanDnsRecord fromJson(final Map<String, dynamic> json) =>
_$DigitalOceanDnsRecordFromJson(json);
Map<String, dynamic> toJson() => _$DigitalOceanDnsRecordToJson(this);
}

View File

@ -0,0 +1,41 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'digital_ocean_dns_info.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
DigitalOceanDomain _$DigitalOceanDomainFromJson(Map<String, dynamic> json) =>
DigitalOceanDomain(
name: json['name'] as String,
ttl: json['ttl'] as int?,
);
Map<String, dynamic> _$DigitalOceanDomainToJson(DigitalOceanDomain instance) =>
<String, dynamic>{
'name': instance.name,
'ttl': instance.ttl,
};
DigitalOceanDnsRecord _$DigitalOceanDnsRecordFromJson(
Map<String, dynamic> json) =>
DigitalOceanDnsRecord(
id: json['id'] as int?,
name: json['name'] as String,
type: json['type'] as String,
ttl: json['ttl'] as int,
data: json['data'] as String,
priority: json['priority'] as int?,
);
Map<String, dynamic> _$DigitalOceanDnsRecordToJson(
DigitalOceanDnsRecord instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'type': instance.type,
'ttl': instance.ttl,
'data': instance.data,
'priority': instance.priority,
};

View File

@ -1,6 +1,7 @@
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns_api.dart';
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
import 'package:selfprivacy/logic/models/json/digital_ocean_dns_info.dart';
import 'package:selfprivacy/logic/models/json/dns_records.dart';
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
@ -59,7 +60,7 @@ class DigitalOceanDnsProvider extends DnsProvider {
domains = result.data
.map<String>(
(final el) => el['name'] as String,
(final el) => el.name,
)
.toList();
@ -75,11 +76,22 @@ class DigitalOceanDnsProvider extends DnsProvider {
final String? ip4,
}) async =>
_adapter.api().createMultipleDnsRecords(
domain: domain,
domainName: domain.domainName,
records: getProjectDnsRecords(
domain.domainName,
ip4,
),
)
.map<DigitalOceanDnsRecord>(
(final e) => DigitalOceanDnsRecord(
name: e.name ?? '',
id: null,
data: e.content ?? '',
ttl: e.ttl,
type: e.type,
priority: e.priority,
),
)
.toList(),
);
@override
@ -87,7 +99,7 @@ class DigitalOceanDnsProvider extends DnsProvider {
required final ServerDomain domain,
final String? ip4,
}) async {
final result = await _adapter.api().getDnsRecords(domain: domain);
final result = await _adapter.api().getDnsRecords(domain.domainName);
if (result.data.isEmpty || !result.success) {
return GenericResult(
success: result.success,
@ -98,15 +110,15 @@ class DigitalOceanDnsProvider extends DnsProvider {
}
const ignoreType = 'SOA';
final filteredRecords = [];
final List<DigitalOceanDnsRecord> filteredRecords = [];
for (final record in result.data) {
if (record['type'] != ignoreType) {
if (record.type != ignoreType) {
filteredRecords.add(record);
}
}
return _adapter.api().removeSimilarRecords(
domain: domain,
domainName: domain.domainName,
records: filteredRecords,
);
}
@ -116,7 +128,7 @@ class DigitalOceanDnsProvider extends DnsProvider {
required final ServerDomain domain,
}) async {
final List<DnsRecord> records = [];
final result = await _adapter.api().getDnsRecords(domain: domain);
final result = await _adapter.api().getDnsRecords(domain.domainName);
if (result.data.isEmpty || !result.success) {
return GenericResult(
success: result.success,
@ -129,10 +141,10 @@ class DigitalOceanDnsProvider extends DnsProvider {
for (final rawRecord in result.data) {
records.add(
DnsRecord(
name: rawRecord['name'],
type: rawRecord['type'],
content: rawRecord['data'],
ttl: rawRecord['ttl'],
name: rawRecord.name,
type: rawRecord.type,
content: rawRecord.data,
ttl: rawRecord.ttl,
proxied: false,
),
);
@ -147,8 +159,17 @@ class DigitalOceanDnsProvider extends DnsProvider {
final ServerDomain domain,
) async =>
_adapter.api().createMultipleDnsRecords(
domain: domain,
records: [record],
domainName: domain.domainName,
records: [
DigitalOceanDnsRecord(
data: record.content ?? '',
id: null,
name: record.name ?? '',
ttl: record.ttl,
type: record.type,
priority: record.priority,
),
],
);
@override