mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-08 00:51:20 +00:00
Merge pull request 'refactor: Implement Cloudflare-specific objects to avoid usage of global models' (#268) from dto into master
Reviewed-on: https://git.selfprivacy.org/SelfPrivacy/selfprivacy.org.app/pulls/268 Reviewed-by: Inex Code <inex.code@selfprivacy.org>
This commit is contained in:
commit
a17b66c729
|
@ -4,8 +4,7 @@ import 'package:dio/dio.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/generic_result.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/api_maps/rest_maps/rest_api_map.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_records.dart';
|
|
||||||
|
|
||||||
class CloudflareApi extends RestApiMap {
|
class CloudflareApi extends RestApiMap {
|
||||||
CloudflareApi({
|
CloudflareApi({
|
||||||
|
@ -92,9 +91,9 @@ class CloudflareApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List>> getDomains() async {
|
Future<GenericResult<List<CloudflareZone>>> getZones() async {
|
||||||
final String url = '$rootAddress/zones';
|
final String url = '$rootAddress/zones';
|
||||||
List domains = [];
|
List<CloudflareZone> domains = [];
|
||||||
|
|
||||||
late final Response? response;
|
late final Response? response;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
|
@ -103,7 +102,11 @@ class CloudflareApi extends RestApiMap {
|
||||||
url,
|
url,
|
||||||
queryParameters: {'per_page': 50},
|
queryParameters: {'per_page': 50},
|
||||||
);
|
);
|
||||||
domains = response.data['result'];
|
domains = response.data['result']!
|
||||||
|
.map<CloudflareZone>(
|
||||||
|
(final json) => CloudflareZone.fromJson(json),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
|
@ -125,18 +128,17 @@ class CloudflareApi extends RestApiMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> createMultipleDnsRecords({
|
Future<GenericResult<void>> createMultipleDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final String zoneId,
|
||||||
required final List<DnsRecord> records,
|
required final List<CloudflareDnsRecord> records,
|
||||||
}) async {
|
}) async {
|
||||||
final String domainZoneId = domain.zoneId;
|
|
||||||
final List<Future> allCreateFutures = <Future>[];
|
final List<Future> allCreateFutures = <Future>[];
|
||||||
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
for (final DnsRecord record in records) {
|
for (final CloudflareDnsRecord record in records) {
|
||||||
allCreateFutures.add(
|
allCreateFutures.add(
|
||||||
client.post(
|
client.post(
|
||||||
'/zones/$domainZoneId/dns_records',
|
'/zones/$zoneId/dns_records',
|
||||||
data: record.toJson(),
|
data: record.toJson(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -160,11 +162,10 @@ class CloudflareApi extends RestApiMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> removeSimilarRecords({
|
Future<GenericResult<void>> removeSimilarRecords({
|
||||||
required final ServerDomain domain,
|
required final String zoneId,
|
||||||
required final List records,
|
required final List<CloudflareDnsRecord> records,
|
||||||
}) async {
|
}) async {
|
||||||
final String domainZoneId = domain.zoneId;
|
final String url = '/zones/$zoneId/dns_records';
|
||||||
final String url = '/zones/$domainZoneId/dns_records';
|
|
||||||
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
|
@ -172,7 +173,7 @@ class CloudflareApi extends RestApiMap {
|
||||||
|
|
||||||
for (final record in records) {
|
for (final record in records) {
|
||||||
allDeleteFutures.add(
|
allDeleteFutures.add(
|
||||||
client.delete('$url/${record["id"]}'),
|
client.delete('$url/${record.id}'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await Future.wait(allDeleteFutures);
|
await Future.wait(allDeleteFutures);
|
||||||
|
@ -190,26 +191,21 @@ class CloudflareApi extends RestApiMap {
|
||||||
return GenericResult(success: true, data: null);
|
return GenericResult(success: true, data: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List>> getDnsRecords({
|
Future<GenericResult<List<CloudflareDnsRecord>>> getDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final String zoneId,
|
||||||
}) async {
|
}) async {
|
||||||
Response response;
|
Response response;
|
||||||
final String domainName = domain.domainName;
|
List<CloudflareDnsRecord> allRecords = [];
|
||||||
final String domainZoneId = domain.zoneId;
|
|
||||||
final List allRecords = [];
|
|
||||||
|
|
||||||
final String url = '/zones/$domainZoneId/dns_records';
|
|
||||||
|
|
||||||
|
final String url = '/zones/$zoneId/dns_records';
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(url);
|
response = await client.get(url);
|
||||||
final List records = response.data['result'] ?? [];
|
allRecords = response.data['result']!
|
||||||
|
.map<CloudflareDnsRecord>(
|
||||||
for (final record in records) {
|
(final json) => CloudflareDnsRecord.fromJson(json),
|
||||||
if (record['zone_name'] == domainName) {
|
)
|
||||||
allRecords.add(record);
|
.toList();
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
|
@ -223,30 +219,4 @@ class CloudflareApi extends RestApiMap {
|
||||||
|
|
||||||
return GenericResult(data: allRecords, success: true);
|
return GenericResult(data: allRecords, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List<dynamic>>> getZones(final String domain) async {
|
|
||||||
List zones = [];
|
|
||||||
|
|
||||||
late final Response? response;
|
|
||||||
final Dio client = await getClient();
|
|
||||||
try {
|
|
||||||
response = await client.get(
|
|
||||||
'/zones',
|
|
||||||
queryParameters: {'name': domain},
|
|
||||||
);
|
|
||||||
zones = response.data['result'];
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
GenericResult(
|
|
||||||
success: false,
|
|
||||||
data: zones,
|
|
||||||
code: response?.statusCode,
|
|
||||||
message: response?.statusMessage,
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
close(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GenericResult(success: true, data: zones);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,23 +25,17 @@ class DomainSetupCubit extends Cubit<DomainSetupState> {
|
||||||
Future<void> saveDomain() async {
|
Future<void> saveDomain() async {
|
||||||
assert(state is Loaded, 'wrong state');
|
assert(state is Loaded, 'wrong state');
|
||||||
final String domainName = (state as Loaded).domain;
|
final String domainName = (state as Loaded).domain;
|
||||||
|
|
||||||
emit(Loading(LoadingTypes.saving));
|
emit(Loading(LoadingTypes.saving));
|
||||||
|
|
||||||
final dnsProvider = ProvidersController.currentDnsProvider!;
|
final dnsProvider = ProvidersController.currentDnsProvider!;
|
||||||
final GenericResult<String?> zoneIdResult =
|
|
||||||
await dnsProvider.getZoneId(domainName);
|
|
||||||
|
|
||||||
if (zoneIdResult.success || zoneIdResult.data != null) {
|
final ServerDomain domain = ServerDomain(
|
||||||
final ServerDomain domain = ServerDomain(
|
domainName: domainName,
|
||||||
domainName: domainName,
|
provider: dnsProvider.type,
|
||||||
zoneId: zoneIdResult.data!,
|
);
|
||||||
provider: dnsProvider.type,
|
|
||||||
);
|
|
||||||
|
|
||||||
serverInstallationCubit.setDomain(domain);
|
serverInstallationCubit.setDomain(domain);
|
||||||
emit(DomainSet());
|
emit(DomainSet());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -467,7 +467,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
final ServerDomain serverDomain = ServerDomain(
|
final ServerDomain serverDomain = ServerDomain(
|
||||||
domainName: domain,
|
domainName: domain,
|
||||||
provider: DnsProviderType.unknown,
|
provider: DnsProviderType.unknown,
|
||||||
zoneId: '',
|
|
||||||
);
|
);
|
||||||
final ServerRecoveryCapabilities recoveryCapabilities =
|
final ServerRecoveryCapabilities recoveryCapabilities =
|
||||||
await repository.getRecoveryCapabilities(serverDomain);
|
await repository.getRecoveryCapabilities(serverDomain);
|
||||||
|
@ -697,9 +696,9 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
if (serverDomain == null) {
|
if (serverDomain == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String? zoneId =
|
final isTokenValid =
|
||||||
await repository.getDomainId(token, serverDomain.domainName);
|
await repository.validateDnsToken(token, serverDomain.domainName);
|
||||||
if (zoneId == null) {
|
if (!isTokenValid) {
|
||||||
getIt<NavigationService>()
|
getIt<NavigationService>()
|
||||||
.showSnackBar('recovering.domain_not_available_on_token'.tr());
|
.showSnackBar('recovering.domain_not_available_on_token'.tr());
|
||||||
return;
|
return;
|
||||||
|
@ -711,16 +710,13 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
await repository.saveDomain(
|
await repository.saveDomain(
|
||||||
ServerDomain(
|
ServerDomain(
|
||||||
domainName: serverDomain.domainName,
|
domainName: serverDomain.domainName,
|
||||||
zoneId: zoneId,
|
|
||||||
provider: dnsProviderType,
|
provider: dnsProviderType,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
// await repository.setDnsApiToken(token);
|
|
||||||
emit(
|
emit(
|
||||||
dataState.copyWith(
|
dataState.copyWith(
|
||||||
serverDomain: ServerDomain(
|
serverDomain: ServerDomain(
|
||||||
domainName: serverDomain.domainName,
|
domainName: serverDomain.domainName,
|
||||||
zoneId: zoneId,
|
|
||||||
provider: dnsProviderType,
|
provider: dnsProviderType,
|
||||||
),
|
),
|
||||||
dnsApiToken: token,
|
dnsApiToken: token,
|
||||||
|
|
|
@ -193,17 +193,23 @@ class ServerInstallationRepository {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getDomainId(final String token, final String domain) async {
|
Future<bool> validateDnsToken(
|
||||||
|
final String token,
|
||||||
|
final String domain,
|
||||||
|
) async {
|
||||||
final result =
|
final result =
|
||||||
await ProvidersController.currentDnsProvider!.tryInitApiByToken(token);
|
await ProvidersController.currentDnsProvider!.tryInitApiByToken(token);
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
await setDnsApiToken(token);
|
await setDnsApiToken(token);
|
||||||
return (await ProvidersController.currentDnsProvider!.getZoneId(
|
final domainResult =
|
||||||
domain,
|
await ProvidersController.currentDnsProvider!.domainList();
|
||||||
))
|
if (!domainResult.success || domainResult.data.isEmpty) {
|
||||||
.data;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain == domainResult.data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, bool>> isDnsAddressesMatch(
|
Future<Map<String, bool>> isDnsAddressesMatch(
|
||||||
|
|
|
@ -7,21 +7,16 @@ part 'server_domain.g.dart';
|
||||||
class ServerDomain {
|
class ServerDomain {
|
||||||
ServerDomain({
|
ServerDomain({
|
||||||
required this.domainName,
|
required this.domainName,
|
||||||
required this.zoneId,
|
|
||||||
required this.provider,
|
required this.provider,
|
||||||
});
|
});
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
final String domainName;
|
final String domainName;
|
||||||
|
|
||||||
@HiveField(1)
|
// @HiveField(1)
|
||||||
final String zoneId;
|
|
||||||
|
|
||||||
@HiveField(2, defaultValue: DnsProviderType.cloudflare)
|
@HiveField(2, defaultValue: DnsProviderType.cloudflare)
|
||||||
final DnsProviderType provider;
|
final DnsProviderType provider;
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => '$domainName: $zoneId';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@HiveType(typeId: 100)
|
@HiveType(typeId: 100)
|
||||||
|
|
|
@ -18,7 +18,6 @@ class ServerDomainAdapter extends TypeAdapter<ServerDomain> {
|
||||||
};
|
};
|
||||||
return ServerDomain(
|
return ServerDomain(
|
||||||
domainName: fields[0] as String,
|
domainName: fields[0] as String,
|
||||||
zoneId: fields[1] as String,
|
|
||||||
provider: fields[2] == null
|
provider: fields[2] == null
|
||||||
? DnsProviderType.cloudflare
|
? DnsProviderType.cloudflare
|
||||||
: fields[2] as DnsProviderType,
|
: fields[2] as DnsProviderType,
|
||||||
|
@ -28,11 +27,9 @@ class ServerDomainAdapter extends TypeAdapter<ServerDomain> {
|
||||||
@override
|
@override
|
||||||
void write(BinaryWriter writer, ServerDomain obj) {
|
void write(BinaryWriter writer, ServerDomain obj) {
|
||||||
writer
|
writer
|
||||||
..writeByte(3)
|
..writeByte(2)
|
||||||
..writeByte(0)
|
..writeByte(0)
|
||||||
..write(obj.domainName)
|
..write(obj.domainName)
|
||||||
..writeByte(1)
|
|
||||||
..write(obj.zoneId)
|
|
||||||
..writeByte(2)
|
..writeByte(2)
|
||||||
..write(obj.provider);
|
..write(obj.provider);
|
||||||
}
|
}
|
||||||
|
|
86
lib/logic/models/json/cloudflare_dns_info.dart
Normal file
86
lib/logic/models/json/cloudflare_dns_info.dart
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'cloudflare_dns_info.g.dart';
|
||||||
|
|
||||||
|
/// https://developers.cloudflare.com/api/operations/zones-get
|
||||||
|
@JsonSerializable()
|
||||||
|
class CloudflareZone {
|
||||||
|
CloudflareZone({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Zone identifier
|
||||||
|
///
|
||||||
|
/// `<= 32 characters`
|
||||||
|
///
|
||||||
|
/// Example: 023e105f4ecef8ad9ca31a8372d0c353
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
/// The domain name
|
||||||
|
///
|
||||||
|
/// `<= 253 characters`
|
||||||
|
///
|
||||||
|
/// Example: example.com
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
static CloudflareZone fromJson(final Map<String, dynamic> json) =>
|
||||||
|
_$CloudflareZoneFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-list-dns-records
|
||||||
|
@JsonSerializable()
|
||||||
|
class CloudflareDnsRecord {
|
||||||
|
CloudflareDnsRecord({
|
||||||
|
required this.type,
|
||||||
|
required this.name,
|
||||||
|
required this.content,
|
||||||
|
required this.zoneName,
|
||||||
|
this.ttl = 3600,
|
||||||
|
this.priority = 10,
|
||||||
|
this.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Record identifier
|
||||||
|
///
|
||||||
|
/// `<= 32 characters`
|
||||||
|
/// Example: 023e105f4ecef8ad9ca31a8372d0c353
|
||||||
|
final String? id;
|
||||||
|
|
||||||
|
/// Record type.
|
||||||
|
///
|
||||||
|
/// Example: A
|
||||||
|
final String type;
|
||||||
|
|
||||||
|
/// DNS record name (or @ for the zone apex) in Punycode.
|
||||||
|
///
|
||||||
|
/// `<= 255 characters`
|
||||||
|
///
|
||||||
|
/// Example: example.com
|
||||||
|
final String? name;
|
||||||
|
|
||||||
|
/// Valid DNS Record string content.
|
||||||
|
///
|
||||||
|
/// Example: A valid IPv4 address "198.51.100.4"
|
||||||
|
final String? content;
|
||||||
|
|
||||||
|
/// The domain of the record.
|
||||||
|
///
|
||||||
|
/// Example: example.com
|
||||||
|
@JsonKey(name: 'zone_name')
|
||||||
|
final String zoneName;
|
||||||
|
|
||||||
|
/// Time To Live (TTL) of the DNS record in seconds. Setting to 1 means 'automatic'.
|
||||||
|
///
|
||||||
|
/// Value must be between 60 and 86400, with the minimum reduced to 30 for Enterprise zones.
|
||||||
|
final int ttl;
|
||||||
|
|
||||||
|
/// Required for MX, SRV and URI records; unused by other record types. Records with lower priorities are preferred.
|
||||||
|
///
|
||||||
|
/// `>= 0 <= 65535`
|
||||||
|
final int priority;
|
||||||
|
|
||||||
|
static CloudflareDnsRecord fromJson(final Map<String, dynamic> json) =>
|
||||||
|
_$CloudflareDnsRecordFromJson(json);
|
||||||
|
Map<String, dynamic> toJson() => _$CloudflareDnsRecordToJson(this);
|
||||||
|
}
|
42
lib/logic/models/json/cloudflare_dns_info.g.dart
Normal file
42
lib/logic/models/json/cloudflare_dns_info.g.dart
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'cloudflare_dns_info.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
CloudflareZone _$CloudflareZoneFromJson(Map<String, dynamic> json) =>
|
||||||
|
CloudflareZone(
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$CloudflareZoneToJson(CloudflareZone instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
CloudflareDnsRecord _$CloudflareDnsRecordFromJson(Map<String, dynamic> json) =>
|
||||||
|
CloudflareDnsRecord(
|
||||||
|
type: json['type'] as String,
|
||||||
|
name: json['name'] as String?,
|
||||||
|
content: json['content'] as String?,
|
||||||
|
zoneName: json['zone_name'] as String,
|
||||||
|
ttl: json['ttl'] as int? ?? 3600,
|
||||||
|
priority: json['priority'] as int? ?? 10,
|
||||||
|
id: json['id'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$CloudflareDnsRecordToJson(
|
||||||
|
CloudflareDnsRecord instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'type': instance.type,
|
||||||
|
'name': instance.name,
|
||||||
|
'content': instance.content,
|
||||||
|
'zone_name': instance.zoneName,
|
||||||
|
'ttl': instance.ttl,
|
||||||
|
'priority': instance.priority,
|
||||||
|
};
|
|
@ -1,12 +1,16 @@
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart';
|
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/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.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_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';
|
||||||
|
|
||||||
class ApiAdapter {
|
class ApiAdapter {
|
||||||
ApiAdapter({final bool isWithToken = true})
|
ApiAdapter({
|
||||||
: _api = CloudflareApi(
|
final bool isWithToken = true,
|
||||||
|
this.cachedDomain = '',
|
||||||
|
this.cachedZoneId = '',
|
||||||
|
}) : _api = CloudflareApi(
|
||||||
isWithToken: isWithToken,
|
isWithToken: isWithToken,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -17,6 +21,8 @@ class ApiAdapter {
|
||||||
);
|
);
|
||||||
|
|
||||||
final CloudflareApi _api;
|
final CloudflareApi _api;
|
||||||
|
final String cachedZoneId;
|
||||||
|
final String cachedDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CloudflareDnsProvider extends DnsProvider {
|
class CloudflareDnsProvider extends DnsProvider {
|
||||||
|
@ -47,7 +53,7 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<List<String>>> domainList() async {
|
Future<GenericResult<List<String>>> domainList() async {
|
||||||
List<String> domains = [];
|
List<String> domains = [];
|
||||||
final result = await _adapter.api().getDomains();
|
final result = await _adapter.api().getZones();
|
||||||
if (result.data.isEmpty || !result.success) {
|
if (result.data.isEmpty || !result.success) {
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
success: result.success,
|
success: result.success,
|
||||||
|
@ -59,10 +65,17 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
|
|
||||||
domains = result.data
|
domains = result.data
|
||||||
.map<String>(
|
.map<String>(
|
||||||
(final el) => el['name'] as String,
|
(final el) => el.name,
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
/// TODO: Remove when domain selection for more than one domain on account is implemented, move cachedZoneId writing to domain saving method
|
||||||
|
_adapter = ApiAdapter(
|
||||||
|
isWithToken: true,
|
||||||
|
cachedDomain: result.data[0].name,
|
||||||
|
cachedZoneId: result.data[0].id,
|
||||||
|
);
|
||||||
|
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
success: true,
|
success: true,
|
||||||
data: domains,
|
data: domains,
|
||||||
|
@ -73,11 +86,27 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
Future<GenericResult<void>> createDomainRecords({
|
Future<GenericResult<void>> createDomainRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
}) {
|
}) async {
|
||||||
|
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
||||||
|
if (!syncZoneIdResult.success) {
|
||||||
|
return syncZoneIdResult;
|
||||||
|
}
|
||||||
|
|
||||||
final records = getProjectDnsRecords(domain.domainName, ip4);
|
final records = getProjectDnsRecords(domain.domainName, ip4);
|
||||||
return _adapter.api().createMultipleDnsRecords(
|
return _adapter.api().createMultipleDnsRecords(
|
||||||
domain: domain,
|
zoneId: _adapter.cachedZoneId,
|
||||||
records: records,
|
records: records
|
||||||
|
.map<CloudflareDnsRecord>(
|
||||||
|
(final rec) => CloudflareDnsRecord(
|
||||||
|
content: rec.content,
|
||||||
|
name: rec.name,
|
||||||
|
type: rec.type,
|
||||||
|
zoneName: domain.domainName,
|
||||||
|
id: null,
|
||||||
|
ttl: rec.ttl,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +115,13 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
}) async {
|
}) async {
|
||||||
final result = await _adapter.api().getDnsRecords(domain: domain);
|
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) {
|
if (result.data.isEmpty || !result.success) {
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
success: result.success,
|
success: result.success,
|
||||||
|
@ -97,7 +132,7 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
return _adapter.api().removeSimilarRecords(
|
return _adapter.api().removeSimilarRecords(
|
||||||
domain: domain,
|
zoneId: _adapter.cachedZoneId,
|
||||||
records: result.data,
|
records: result.data,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -106,8 +141,19 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
Future<GenericResult<List<DnsRecord>>> getDnsRecords({
|
Future<GenericResult<List<DnsRecord>>> getDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
}) async {
|
}) async {
|
||||||
|
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
||||||
|
if (!syncZoneIdResult.success) {
|
||||||
|
return GenericResult(
|
||||||
|
success: syncZoneIdResult.success,
|
||||||
|
data: [],
|
||||||
|
code: syncZoneIdResult.code,
|
||||||
|
message: syncZoneIdResult.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final List<DnsRecord> records = [];
|
final List<DnsRecord> records = [];
|
||||||
final result = await _adapter.api().getDnsRecords(domain: domain);
|
final result =
|
||||||
|
await _adapter.api().getDnsRecords(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,
|
||||||
|
@ -120,11 +166,10 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
for (final rawRecord in result.data) {
|
for (final rawRecord in result.data) {
|
||||||
records.add(
|
records.add(
|
||||||
DnsRecord(
|
DnsRecord(
|
||||||
name: rawRecord['name'],
|
name: rawRecord.name,
|
||||||
type: rawRecord['type'],
|
type: rawRecord.type,
|
||||||
content: rawRecord['content'],
|
content: rawRecord.content,
|
||||||
ttl: rawRecord['ttl'],
|
ttl: rawRecord.ttl,
|
||||||
proxied: rawRecord['proxied'],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -139,11 +184,26 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
Future<GenericResult<void>> setDnsRecord(
|
Future<GenericResult<void>> setDnsRecord(
|
||||||
final DnsRecord record,
|
final DnsRecord record,
|
||||||
final ServerDomain domain,
|
final ServerDomain domain,
|
||||||
) async =>
|
) async {
|
||||||
_adapter.api().createMultipleDnsRecords(
|
final syncZoneIdResult = await syncZoneId(domain.domainName);
|
||||||
domain: domain,
|
if (!syncZoneIdResult.success) {
|
||||||
records: [record],
|
return syncZoneIdResult;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<List<DesiredDnsRecord>>> validateDnsRecords(
|
Future<GenericResult<List<DesiredDnsRecord>>> validateDnsRecords(
|
||||||
|
@ -336,10 +396,39 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
Future<GenericResult<void>> syncZoneId(final String domain) async {
|
||||||
|
if (domain == _adapter.cachedDomain && _adapter.cachedZoneId.isNotEmpty) {
|
||||||
|
return GenericResult(
|
||||||
|
success: true,
|
||||||
|
data: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final getZoneIdResult = await getZoneId(domain);
|
||||||
|
if (!getZoneIdResult.success || getZoneIdResult.data == null) {
|
||||||
|
return GenericResult(
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
code: getZoneIdResult.code,
|
||||||
|
message: getZoneIdResult.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_adapter = ApiAdapter(
|
||||||
|
isWithToken: true,
|
||||||
|
cachedDomain: domain,
|
||||||
|
cachedZoneId: getZoneIdResult.data!,
|
||||||
|
);
|
||||||
|
|
||||||
|
return GenericResult(
|
||||||
|
success: true,
|
||||||
|
data: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<GenericResult<String?>> getZoneId(final String domain) async {
|
Future<GenericResult<String?>> getZoneId(final String domain) async {
|
||||||
String? id;
|
String? id;
|
||||||
final result = await _adapter.api().getZones(domain);
|
final result = await _adapter.api().getZones();
|
||||||
if (result.data.isEmpty || !result.success) {
|
if (result.data.isEmpty || !result.success) {
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
success: result.success,
|
success: result.success,
|
||||||
|
@ -349,8 +438,12 @@ class CloudflareDnsProvider extends DnsProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
id = result.data[0]['id'];
|
for (final availableDomain in result.data) {
|
||||||
|
if (availableDomain.name == domain) {
|
||||||
|
id = availableDomain.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GenericResult(success: true, data: id);
|
return GenericResult(success: id != null, data: id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,11 +408,4 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<GenericResult<String?>> getZoneId(final String domain) async =>
|
|
||||||
GenericResult(
|
|
||||||
data: domain,
|
|
||||||
success: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -369,11 +369,4 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<GenericResult<String?>> getZoneId(final String domain) async =>
|
|
||||||
GenericResult(
|
|
||||||
data: domain,
|
|
||||||
success: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,4 @@ abstract class DnsProvider {
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
final String? dkimPublicKey,
|
final String? dkimPublicKey,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Tries to access zone of requested domain.
|
|
||||||
///
|
|
||||||
/// If a DNS provider doesn't support zones,
|
|
||||||
/// will return domain without any changes.
|
|
||||||
///
|
|
||||||
/// If success, returns an initializing string of zone id.
|
|
||||||
Future<GenericResult<String?>> getZoneId(final String domain);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue