mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-11-10 19:03:12 +00:00
feat: Add the updateDnsRecords
to DNS providers
This commit is contained in:
parent
95e51732fc
commit
eab2f892c9
|
@ -155,7 +155,7 @@ class DesecApi extends RestApiMap {
|
|||
return GenericResult(success: true, data: null);
|
||||
}
|
||||
|
||||
Future<GenericResult<void>> removeSimilarRecords({
|
||||
Future<GenericResult<void>> putRecords({
|
||||
required final String domainName,
|
||||
required final List<DesecDnsRecord> records,
|
||||
}) async {
|
||||
|
|
|
@ -43,6 +43,7 @@ class CloudflareDnsRecord {
|
|||
this.ttl = 3600,
|
||||
this.priority = 10,
|
||||
this.id,
|
||||
this.comment = 'Created by SelfPrivacy app',
|
||||
});
|
||||
|
||||
factory CloudflareDnsRecord.fromDnsRecord(
|
||||
|
@ -90,6 +91,9 @@ class CloudflareDnsRecord {
|
|||
/// `>= 0 <= 65535`
|
||||
final int priority;
|
||||
|
||||
/// Comments or notes about the DNS record. This field has no effect on DNS responses.
|
||||
final String comment;
|
||||
|
||||
static CloudflareDnsRecord fromJson(final Map<String, dynamic> json) =>
|
||||
_$CloudflareDnsRecordFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$CloudflareDnsRecordToJson(this);
|
||||
|
|
|
@ -27,6 +27,7 @@ CloudflareDnsRecord _$CloudflareDnsRecordFromJson(Map<String, dynamic> json) =>
|
|||
ttl: (json['ttl'] as num?)?.toInt() ?? 3600,
|
||||
priority: (json['priority'] as num?)?.toInt() ?? 10,
|
||||
id: json['id'] as String?,
|
||||
comment: json['comment'] as String? ?? 'Created by SelfPrivacy app',
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CloudflareDnsRecordToJson(
|
||||
|
@ -39,4 +40,5 @@ Map<String, dynamic> _$CloudflareDnsRecordToJson(
|
|||
'zone_name': instance.zoneName,
|
||||
'ttl': instance.ttl,
|
||||
'priority': instance.priority,
|
||||
'comment': instance.comment,
|
||||
};
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_settings.graphql.dart';
|
||||
|
||||
part 'dns_records.g.dart';
|
||||
|
||||
@JsonSerializable(createToJson: true, createFactory: false)
|
||||
class DnsRecord {
|
||||
DnsRecord({
|
||||
@JsonSerializable()
|
||||
class DnsRecord extends Equatable {
|
||||
const DnsRecord({
|
||||
required this.type,
|
||||
required this.name,
|
||||
required this.content,
|
||||
|
@ -35,4 +36,14 @@ class DnsRecord {
|
|||
final bool proxied;
|
||||
|
||||
Map<String, dynamic> toJson() => _$DnsRecordToJson(this);
|
||||
|
||||
@override
|
||||
@JsonKey(includeToJson: false)
|
||||
List<Object?> get props => [
|
||||
type,
|
||||
name,
|
||||
content,
|
||||
ttl,
|
||||
priority,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -6,6 +6,16 @@ part of 'dns_records.dart';
|
|||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
DnsRecord _$DnsRecordFromJson(Map<String, dynamic> json) => DnsRecord(
|
||||
type: json['type'] as String,
|
||||
name: json['name'] as String?,
|
||||
content: json['content'] as String?,
|
||||
displayName: json['displayName'] as String?,
|
||||
ttl: (json['ttl'] as num?)?.toInt() ?? 3600,
|
||||
priority: (json['priority'] as num?)?.toInt() ?? 10,
|
||||
proxied: json['proxied'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$DnsRecordToJson(DnsRecord instance) => <String, dynamic>{
|
||||
'type': instance.type,
|
||||
'displayName': instance.displayName,
|
||||
|
|
|
@ -198,6 +198,94 @@ class CloudflareDnsProvider extends DnsProvider {
|
|||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<GenericResult<void>> updateDnsRecords({
|
||||
required final List<DnsRecord> newRecords,
|
||||
required final ServerDomain domain,
|
||||
final List<DnsRecord>? oldRecords,
|
||||
}) async {
|
||||
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
||||
if (!syncZoneIdResult.success) {
|
||||
return syncZoneIdResult;
|
||||
}
|
||||
|
||||
final result = await _adapter.api().getDnsRecords(
|
||||
zoneId: _adapter.cachedZoneId,
|
||||
);
|
||||
if (result.data.isEmpty || !result.success) {
|
||||
return GenericResult(
|
||||
success: false,
|
||||
data: null,
|
||||
code: result.code,
|
||||
message: result.message,
|
||||
);
|
||||
}
|
||||
|
||||
final List<CloudflareDnsRecord> newSelfprivacyRecords = newRecords
|
||||
.map(
|
||||
(final record) => CloudflareDnsRecord.fromDnsRecord(
|
||||
record,
|
||||
domain.domainName,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
final List<CloudflareDnsRecord>? oldSelfprivacyRecords = oldRecords
|
||||
?.map(
|
||||
(final record) => CloudflareDnsRecord.fromDnsRecord(
|
||||
record,
|
||||
domain.domainName,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
final List<CloudflareDnsRecord> cloudflareRecords = result.data;
|
||||
|
||||
final List<CloudflareDnsRecord> recordsToDelete = newSelfprivacyRecords
|
||||
.where(
|
||||
(final newRecord) => cloudflareRecords.any(
|
||||
(final oldRecord) =>
|
||||
newRecord.type == oldRecord.type &&
|
||||
newRecord.name == oldRecord.name,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
if (oldSelfprivacyRecords != null) {
|
||||
recordsToDelete.addAll(
|
||||
oldSelfprivacyRecords
|
||||
.where(
|
||||
(final oldRecord) => !newSelfprivacyRecords.any(
|
||||
(final newRecord) =>
|
||||
newRecord.type == oldRecord.type &&
|
||||
newRecord.name == oldRecord.name,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
if (recordsToDelete.isNotEmpty) {
|
||||
await _adapter.api().removeSimilarRecords(
|
||||
records: cloudflareRecords
|
||||
.where(
|
||||
(final record) => recordsToDelete.any(
|
||||
(final recordToDelete) =>
|
||||
recordToDelete.type == record.type &&
|
||||
recordToDelete.name == record.name,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
zoneId: _adapter.cachedZoneId,
|
||||
);
|
||||
}
|
||||
|
||||
return _adapter.api().createMultipleDnsRecords(
|
||||
zoneId: _adapter.cachedZoneId,
|
||||
records: newSelfprivacyRecords,
|
||||
);
|
||||
}
|
||||
|
||||
Future<GenericResult<void>> syncZoneId(final String domain) async {
|
||||
if (domain == _adapter.cachedDomain && _adapter.cachedZoneId.isNotEmpty) {
|
||||
return GenericResult(
|
||||
|
|
|
@ -112,7 +112,28 @@ class DesecDnsProvider extends DnsProvider {
|
|||
);
|
||||
}
|
||||
|
||||
return _adapter.api().removeSimilarRecords(
|
||||
return _adapter.api().putRecords(
|
||||
domainName: domain.domainName,
|
||||
records: bulkRecords,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<GenericResult<void>> updateDnsRecords({
|
||||
required final List<DnsRecord> newRecords,
|
||||
required final ServerDomain domain,
|
||||
final List<DnsRecord>? oldRecords,
|
||||
}) async {
|
||||
if (oldRecords != null) {
|
||||
await removeDomainRecords(records: oldRecords, domain: domain);
|
||||
}
|
||||
|
||||
final List<DesecDnsRecord> bulkRecords = [];
|
||||
for (final DnsRecord record in newRecords) {
|
||||
bulkRecords.add(DesecDnsRecord.fromDnsRecord(record, domain.domainName));
|
||||
}
|
||||
|
||||
return _adapter.api().putRecords(
|
||||
domainName: domain.domainName,
|
||||
records: bulkRecords,
|
||||
);
|
||||
|
|
|
@ -128,6 +128,79 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
|||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<GenericResult<void>> updateDnsRecords({
|
||||
required final List<DnsRecord> newRecords,
|
||||
required final ServerDomain domain,
|
||||
final List<DnsRecord>? oldRecords,
|
||||
}) async {
|
||||
final result = await _adapter.api().getDnsRecords(domain.domainName);
|
||||
if (result.data.isEmpty || !result.success) {
|
||||
return GenericResult(
|
||||
success: result.success,
|
||||
data: null,
|
||||
code: result.code,
|
||||
message: result.message,
|
||||
);
|
||||
}
|
||||
|
||||
final List<DigitalOceanDnsRecord> newSelfprivacyRecords = newRecords
|
||||
.map(
|
||||
(final record) => DigitalOceanDnsRecord.fromDnsRecord(
|
||||
record,
|
||||
domain.domainName,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
final List<DigitalOceanDnsRecord>? oldSelfprivacyRecords = oldRecords
|
||||
?.map(
|
||||
(final record) => DigitalOceanDnsRecord.fromDnsRecord(
|
||||
record,
|
||||
domain.domainName,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
final List<DigitalOceanDnsRecord> oceanRecords = result.data;
|
||||
|
||||
final List<DigitalOceanDnsRecord> recordsToDelete = newSelfprivacyRecords
|
||||
.where(
|
||||
(final newRecord) => oceanRecords.any(
|
||||
(final oldRecord) =>
|
||||
newRecord.type == oldRecord.type &&
|
||||
newRecord.name == oldRecord.name,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
if (oldSelfprivacyRecords != null) {
|
||||
recordsToDelete.addAll(
|
||||
oldSelfprivacyRecords
|
||||
.where(
|
||||
(final oldRecord) => !newSelfprivacyRecords.any(
|
||||
(final newRecord) =>
|
||||
newRecord.type == oldRecord.type &&
|
||||
newRecord.name == oldRecord.name,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
if (recordsToDelete.isNotEmpty) {
|
||||
return _adapter.api().removeSimilarRecords(
|
||||
domainName: domain.domainName,
|
||||
records: recordsToDelete,
|
||||
);
|
||||
}
|
||||
|
||||
return _adapter.api().createMultipleDnsRecords(
|
||||
domainName: domain.domainName,
|
||||
records: newSelfprivacyRecords,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<GenericResult<List<DnsRecord>>> getDnsRecords({
|
||||
required final ServerDomain domain,
|
||||
|
|
|
@ -54,4 +54,14 @@ abstract class DnsProvider {
|
|||
final DnsRecord record,
|
||||
final ServerDomain domain,
|
||||
);
|
||||
|
||||
/// Tries to update existing domain records
|
||||
///
|
||||
/// If [oldRecords] is provided, it will also remove the records that
|
||||
/// are not in [newRecords
|
||||
Future<GenericResult<void>> updateDnsRecords({
|
||||
required final List<DnsRecord> newRecords,
|
||||
required final ServerDomain domain,
|
||||
final List<DnsRecord>? oldRecords,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ List<DnsRecord> getProjectDnsRecords(
|
|||
final DnsRecord socialA = DnsRecord(type: 'A', name: 'social', content: ip4);
|
||||
final DnsRecord vpn = DnsRecord(type: 'A', name: 'vpn', content: ip4);
|
||||
|
||||
final DnsRecord txt1 = DnsRecord(
|
||||
const DnsRecord txt1 = DnsRecord(
|
||||
type: 'TXT',
|
||||
name: '_dmarc',
|
||||
content: 'v=DMARC1; p=none',
|
||||
|
@ -125,7 +125,7 @@ List<DnsRecord> getProjectDnsRecords(
|
|||
/// We never create this record!
|
||||
/// This declaration is only for removal
|
||||
/// as we need to compare by 'type' and 'name'
|
||||
final DnsRecord txt3 = DnsRecord(
|
||||
const DnsRecord txt3 = DnsRecord(
|
||||
type: 'TXT',
|
||||
name: 'selector._domainkey',
|
||||
content: 'v=DKIM1; k=rsa; p=none',
|
||||
|
|
Loading…
Reference in a new issue