parent
9e095a6808
commit
d841f9db44
|
@ -0,0 +1 @@
|
||||||
|
extensions:
|
|
@ -168,25 +168,19 @@ class DnsRecordsCubit
|
||||||
|
|
||||||
Future<void> fix() async {
|
Future<void> fix() async {
|
||||||
emit(state.copyWith(dnsState: DnsRecordsStatus.refreshing));
|
emit(state.copyWith(dnsState: DnsRecordsStatus.refreshing));
|
||||||
|
final List<DnsRecord> records = await api.getDnsRecords();
|
||||||
|
|
||||||
|
/// TODO: Error handling?
|
||||||
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||||
final String? ipAddress = serverInstallationCubit.state.serverDetails?.ip4;
|
|
||||||
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
||||||
|
records: records,
|
||||||
domain: domain!,
|
domain: domain!,
|
||||||
);
|
);
|
||||||
await ProvidersController.currentDnsProvider!.createDomainRecords(
|
await ProvidersController.currentDnsProvider!.createDomainRecords(
|
||||||
|
records: records,
|
||||||
domain: domain,
|
domain: domain,
|
||||||
ip4: ipAddress,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final List<DnsRecord> records = await api.getDnsRecords();
|
|
||||||
final DnsRecord? dkimRecord = extractDkimRecord(records);
|
|
||||||
if (dkimRecord != null) {
|
|
||||||
await ProvidersController.currentDnsProvider!.setDnsRecord(
|
|
||||||
dkimRecord,
|
|
||||||
domain,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await load();
|
await load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,12 +264,20 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
final ServerHostingDetails serverDetails,
|
final ServerHostingDetails serverDetails,
|
||||||
) async {
|
) async {
|
||||||
await repository.saveServerDetails(serverDetails);
|
await repository.saveServerDetails(serverDetails);
|
||||||
|
|
||||||
|
/// TODO: Error handling?
|
||||||
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
||||||
ip4: serverDetails.ip4,
|
records: getProjectDnsRecords(
|
||||||
|
state.serverDomain!.domainName,
|
||||||
|
serverDetails.ip4,
|
||||||
|
),
|
||||||
domain: state.serverDomain!,
|
domain: state.serverDomain!,
|
||||||
);
|
);
|
||||||
await ProvidersController.currentDnsProvider!.createDomainRecords(
|
await ProvidersController.currentDnsProvider!.createDomainRecords(
|
||||||
ip4: serverDetails.ip4,
|
records: getProjectDnsRecords(
|
||||||
|
state.serverDomain!.domainName,
|
||||||
|
serverDetails.ip4,
|
||||||
|
),
|
||||||
domain: state.serverDomain!,
|
domain: state.serverDomain!,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -558,14 +558,30 @@ class ServerInstallationRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> deleteServer(final ServerDomain serverDomain) async {
|
Future<bool> deleteServer(final ServerDomain serverDomain) async {
|
||||||
|
final ServerApi api = ServerApi();
|
||||||
|
final dnsRecords = await api.getDnsRecords();
|
||||||
|
final GenericResult<void> removalResult =
|
||||||
|
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
||||||
|
domain: serverDomain,
|
||||||
|
records: dnsRecords,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!removalResult.success) {
|
||||||
|
getIt<NavigationService>().showSnackBar(
|
||||||
|
'modals.dns_removal_error'.tr(),
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final deletionResult =
|
final deletionResult =
|
||||||
await ProvidersController.currentServerProvider!.deleteServer(
|
await ProvidersController.currentServerProvider!.deleteServer(
|
||||||
serverDomain.domainName,
|
serverDomain.domainName,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!deletionResult.success) {
|
if (!deletionResult.success) {
|
||||||
getIt<NavigationService>()
|
getIt<NavigationService>().showSnackBar(
|
||||||
.showSnackBar('modals.server_validators_error'.tr());
|
'modals.server_validators_error'.tr(),
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,13 +592,6 @@ class ServerInstallationRepository {
|
||||||
await box.put(BNames.isLoading, false);
|
await box.put(BNames.isLoading, false);
|
||||||
await box.put(BNames.serverDetails, null);
|
await box.put(BNames.serverDetails, null);
|
||||||
|
|
||||||
final GenericResult<void> removalResult = await ProvidersController
|
|
||||||
.currentDnsProvider!
|
|
||||||
.removeDomainRecords(domain: serverDomain);
|
|
||||||
|
|
||||||
if (!removalResult.success) {
|
|
||||||
getIt<NavigationService>().showSnackBar('modals.dns_removal_error'.tr());
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_providers/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/models/json/dns_records.dart';
|
||||||
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
||||||
import 'package:selfprivacy/utils/network_utils.dart';
|
|
||||||
|
|
||||||
class ApiAdapter {
|
class ApiAdapter {
|
||||||
ApiAdapter({
|
ApiAdapter({
|
||||||
|
@ -80,15 +79,14 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<void>> createDomainRecords({
|
Future<GenericResult<void>> createDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
}) async {
|
}) async {
|
||||||
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
||||||
if (!syncZoneIdResult.success) {
|
if (!syncZoneIdResult.success) {
|
||||||
return syncZoneIdResult;
|
return syncZoneIdResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
final records = getProjectDnsRecords(domain.domainName, ip4);
|
|
||||||
return _adapter.api().createMultipleDnsRecords(
|
return _adapter.api().createMultipleDnsRecords(
|
||||||
zoneId: _adapter.cachedZoneId,
|
zoneId: _adapter.cachedZoneId,
|
||||||
records: records
|
records: records
|
||||||
|
@ -102,16 +100,17 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<void>> removeDomainRecords({
|
Future<GenericResult<void>> removeDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
}) async {
|
}) async {
|
||||||
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
||||||
if (!syncZoneIdResult.success) {
|
if (!syncZoneIdResult.success) {
|
||||||
return syncZoneIdResult;
|
return syncZoneIdResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result =
|
final result = await _adapter.api().getDnsRecords(
|
||||||
await _adapter.api().getDnsRecords(zoneId: _adapter.cachedZoneId);
|
zoneId: _adapter.cachedZoneId,
|
||||||
|
);
|
||||||
if (result.data.isEmpty || !result.success) {
|
if (result.data.isEmpty || !result.success) {
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
success: result.success,
|
success: result.success,
|
||||||
|
@ -121,9 +120,29 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<CloudflareDnsRecord> selfprivacyRecords = records
|
||||||
|
.map(
|
||||||
|
(final record) => CloudflareDnsRecord.fromDnsRecord(
|
||||||
|
record,
|
||||||
|
domain.domainName,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
final List<CloudflareDnsRecord> cloudflareRecords = result.data;
|
||||||
|
|
||||||
|
/// Remove all records that do not match with SelfPrivacy
|
||||||
|
cloudflareRecords.removeWhere(
|
||||||
|
(final oceanRecord) => !selfprivacyRecords.any(
|
||||||
|
(final selfprivacyRecord) =>
|
||||||
|
selfprivacyRecord.type == oceanRecord.type &&
|
||||||
|
selfprivacyRecord.name == oceanRecord.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return _adapter.api().removeSimilarRecords(
|
return _adapter.api().removeSimilarRecords(
|
||||||
zoneId: _adapter.cachedZoneId,
|
zoneId: _adapter.cachedZoneId,
|
||||||
records: result.data,
|
records: cloudflareRecords,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_providers/desec_dns_info.dart';
|
import 'package:selfprivacy/logic/models/json/dns_providers/desec_dns_info.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||||
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
||||||
import 'package:selfprivacy/utils/network_utils.dart';
|
|
||||||
|
|
||||||
class ApiAdapter {
|
class ApiAdapter {
|
||||||
ApiAdapter({final bool isWithToken = true})
|
ApiAdapter({final bool isWithToken = true})
|
||||||
|
@ -75,16 +74,11 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<void>> createDomainRecords({
|
Future<GenericResult<void>> createDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
}) async {
|
}) async {
|
||||||
final List<DnsRecord> listDnsRecords = getProjectDnsRecords(
|
|
||||||
domain.domainName,
|
|
||||||
ip4,
|
|
||||||
);
|
|
||||||
|
|
||||||
final List<DesecDnsRecord> bulkRecords = [];
|
final List<DesecDnsRecord> bulkRecords = [];
|
||||||
for (final DnsRecord record in listDnsRecords) {
|
for (final DnsRecord record in records) {
|
||||||
bulkRecords.add(DesecDnsRecord.fromDnsRecord(record, domain.domainName));
|
bulkRecords.add(DesecDnsRecord.fromDnsRecord(record, domain.domainName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,21 +90,19 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<void>> removeDomainRecords({
|
Future<GenericResult<void>> removeDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
}) async {
|
}) async {
|
||||||
final List<DnsRecord> listDnsRecords = getProjectDnsRecords(
|
|
||||||
domain.domainName,
|
|
||||||
ip4,
|
|
||||||
);
|
|
||||||
|
|
||||||
final List<DesecDnsRecord> bulkRecords = [];
|
final List<DesecDnsRecord> bulkRecords = [];
|
||||||
for (final DnsRecord record in listDnsRecords) {
|
for (final DnsRecord record in records) {
|
||||||
final desecRecord = DesecDnsRecord.fromDnsRecord(
|
final desecRecord = DesecDnsRecord.fromDnsRecord(
|
||||||
record,
|
record,
|
||||||
domain.domainName,
|
domain.domainName,
|
||||||
);
|
);
|
||||||
bulkRecords.add(
|
bulkRecords.add(
|
||||||
|
/// Yes, it looks weird, but exactly forcing 'records' field
|
||||||
|
/// to empty array signals deSEC to remove the DNS record completely
|
||||||
|
/// https://desec.readthedocs.io/en/latest/dns/rrsets.html#deleting-an-rrset
|
||||||
DesecDnsRecord(
|
DesecDnsRecord(
|
||||||
subname: desecRecord.subname,
|
subname: desecRecord.subname,
|
||||||
type: desecRecord.type,
|
type: desecRecord.type,
|
||||||
|
@ -119,14 +111,6 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
bulkRecords.add(
|
|
||||||
DesecDnsRecord(
|
|
||||||
subname: 'selector._domainkey',
|
|
||||||
type: 'TXT',
|
|
||||||
ttl: 18000,
|
|
||||||
records: [],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return _adapter.api().removeSimilarRecords(
|
return _adapter.api().removeSimilarRecords(
|
||||||
domainName: domain.domainName,
|
domainName: domain.domainName,
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_providers/digital_ocean_dns_info.dart';
|
import 'package:selfprivacy/logic/models/json/dns_providers/digital_ocean_dns_info.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||||
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
import 'package:selfprivacy/logic/providers/dns_providers/dns_provider.dart';
|
||||||
import 'package:selfprivacy/utils/network_utils.dart';
|
|
||||||
|
|
||||||
class ApiAdapter {
|
class ApiAdapter {
|
||||||
ApiAdapter({final bool isWithToken = true})
|
ApiAdapter({final bool isWithToken = true})
|
||||||
|
@ -75,15 +74,12 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<void>> createDomainRecords({
|
Future<GenericResult<void>> createDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
}) async =>
|
}) async =>
|
||||||
_adapter.api().createMultipleDnsRecords(
|
_adapter.api().createMultipleDnsRecords(
|
||||||
domainName: domain.domainName,
|
domainName: domain.domainName,
|
||||||
records: getProjectDnsRecords(
|
records: records
|
||||||
domain.domainName,
|
|
||||||
ip4,
|
|
||||||
)
|
|
||||||
.map<DigitalOceanDnsRecord>(
|
.map<DigitalOceanDnsRecord>(
|
||||||
(final e) =>
|
(final e) =>
|
||||||
DigitalOceanDnsRecord.fromDnsRecord(e, domain.domainName),
|
DigitalOceanDnsRecord.fromDnsRecord(e, domain.domainName),
|
||||||
|
@ -93,8 +89,8 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<void>> removeDomainRecords({
|
Future<GenericResult<void>> removeDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
}) async {
|
}) async {
|
||||||
final result = await _adapter.api().getDnsRecords(domain.domainName);
|
final result = await _adapter.api().getDnsRecords(domain.domainName);
|
||||||
if (result.data.isEmpty || !result.success) {
|
if (result.data.isEmpty || !result.success) {
|
||||||
|
@ -106,17 +102,29 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ignoreType = 'SOA';
|
final List<DigitalOceanDnsRecord> selfprivacyRecords = records
|
||||||
final List<DigitalOceanDnsRecord> filteredRecords = [];
|
.map(
|
||||||
for (final record in result.data) {
|
(final record) => DigitalOceanDnsRecord.fromDnsRecord(
|
||||||
if (record.type != ignoreType) {
|
record,
|
||||||
filteredRecords.add(record);
|
domain.domainName,
|
||||||
}
|
),
|
||||||
}
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
final List<DigitalOceanDnsRecord> oceanRecords = result.data;
|
||||||
|
|
||||||
|
/// Remove all records that do not match with SelfPrivacy
|
||||||
|
oceanRecords.removeWhere(
|
||||||
|
(final oceanRecord) => !selfprivacyRecords.any(
|
||||||
|
(final selfprivacyRecord) =>
|
||||||
|
selfprivacyRecord.type == oceanRecord.type &&
|
||||||
|
selfprivacyRecord.name == oceanRecord.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return _adapter.api().removeSimilarRecords(
|
return _adapter.api().removeSimilarRecords(
|
||||||
domainName: domain.domainName,
|
domainName: domain.domainName,
|
||||||
records: filteredRecords,
|
records: oceanRecords,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,23 +23,21 @@ abstract class DnsProvider {
|
||||||
/// Returns list of all available domain entries assigned to the account.
|
/// Returns list of all available domain entries assigned to the account.
|
||||||
Future<GenericResult<List<ServerDomain>>> domainList();
|
Future<GenericResult<List<ServerDomain>>> domainList();
|
||||||
|
|
||||||
/// Tries to create all main domain records needed
|
/// Tries to create domain records
|
||||||
/// for SelfPrivacy to launch on requested domain by ip4.
|
/// by our records list.
|
||||||
///
|
///
|
||||||
/// Doesn't check for duplication, cleaning has
|
/// Doesn't check for duplication, cleaning has
|
||||||
/// to be done beforehand by [removeDomainRecords]
|
/// to be done beforehand by [removeDomainRecords]
|
||||||
Future<GenericResult<void>> createDomainRecords({
|
Future<GenericResult<void>> createDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Tries to remove all domain records of requested domain by ip4.
|
/// Tries to remove all records of requested
|
||||||
///
|
/// domain that match our records list.
|
||||||
/// Will remove all entries, including the ones
|
|
||||||
/// that weren't created by SelfPrivacy.
|
|
||||||
Future<GenericResult<void>> removeDomainRecords({
|
Future<GenericResult<void>> removeDomainRecords({
|
||||||
|
required final List<DnsRecord> records,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Returns list of all [DnsRecord] entries assigned to requested domain.
|
/// Returns list of all [DnsRecord] entries assigned to requested domain.
|
||||||
|
|
Loading…
Reference in New Issue