diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 6ae74fe..c1b4c23 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -469,5 +469,9 @@ "blockingIpv4Description": "IP address to be returned for a blocked A request", "blockingIpv6": "Blocking IPv6", "blockingIpv6Description": "IP address to be returned for a blocked AAAA request", - "invalidIp": "Invalid IP address" + "invalidIp": "Invalid IP address", + "dnsConfigSaved": "DNS server configuration saved successfully", + "dnsConfigNotSaved": "The DNS server configuration could not be saved", + "savingConfig": "Saving configuration...", + "someValueNotValid": "Some value is not valid" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 0f1d772..4e9d722 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -469,5 +469,9 @@ "blockingIpv4Description": "Dirección IP devolverá una petición A bloqueada", "blockingIpv6": "Bloqueo de IPv6", "blockingIpv6Description": "Dirección IP devolverá una petición AAAA bloqueada", - "invalidIp": "Dirección IP no válida" + "invalidIp": "Dirección IP no válida", + "dnsConfigSaved": "La configuración del servidor DNS se ha guardado correctamente", + "dnsConfigNotSaved": "La configuración del servidor DNS no ha podido ser guardada", + "savingConfig": "Guardando configuración...", + "someValueNotValid": "Algún valor no es válido" } \ No newline at end of file diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index 99efa1b..5187177 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -1,7 +1,15 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; class BootstrapDnsScreen extends StatefulWidget { final ServersProvider serversProvider; @@ -60,13 +68,60 @@ class _BootstrapDnsScreenState extends State { @override Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void saveData() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingConfig); + + final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + "bootstrap_dns": bootstrapControllers.map((e) => e['controller'].text).toList(), + }); + + processModal.close(); + + if (result['result'] == 'success') { + DnsInfoData data = serversProvider.dnsInfo.data!; + data.bootstrapDns = List.from(bootstrapControllers.map((e) => e['controller'].text)); + serversProvider.setDnsInfoData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigSaved, + color: Colors.green + ); + } + else if (result['log'] != null && result['log'].statusCode == '400') { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.someValueNotValid, + color: Colors.red + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigNotSaved, + color: Colors.red + ); + } + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.bootstrapDns), actions: [ IconButton( onPressed: validValues == true - ? () => {} + ? () => saveData() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, @@ -164,6 +219,7 @@ class _BootstrapDnsScreenState extends State { ), ], ), + const SizedBox(height: 20) ], ), ); diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 8c007b2..b355f2a 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -1,10 +1,19 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; + class CacheConfigDnsScreen extends StatefulWidget { final ServersProvider serversProvider; @@ -59,7 +68,58 @@ class _CacheConfigDnsScreenState extends State { @override Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + void saveData() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingConfig); + + final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + "cache_size": int.parse(cacheSizeController.text), + "cache_ttl_min": int.parse(overrideMinTtlController.text), + "cache_ttl_max": int.parse(overrideMaxTtlController.text), + "cache_optimistic": optimisticCache + }); + + processModal.close(); + + if (result['result'] == 'success') { + DnsInfoData data = serversProvider.dnsInfo.data!; + data.cacheSize = int.parse(cacheSizeController.text); + data.cacheTtlMin = int.parse(overrideMinTtlController.text); + data.cacheTtlMax = int.parse(overrideMaxTtlController.text); + data.cacheOptimistic = optimisticCache; + serversProvider.setDnsInfoData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigSaved, + color: Colors.green + ); + } + else if (result['log'] != null && result['log'].statusCode == '400') { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.someValueNotValid, + color: Colors.red + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigNotSaved, + color: Colors.red + ); + } + } Widget numericField({ required TextEditingController controller, required String label, @@ -95,7 +155,7 @@ class _CacheConfigDnsScreenState extends State { actions: [ IconButton( onPressed: validData == true - ? () => {} + ? () => saveData() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index dbedc11..394e57a 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -1,4 +1,7 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; @@ -6,6 +9,11 @@ import 'package:adguard_home_manager/screens/settings/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; class DnsServerSettingsScreen extends StatefulWidget { final ServersProvider serversProvider; @@ -94,6 +102,62 @@ class _DnsServerSettingsScreenState extends State { @override Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void saveData() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingConfig); + + final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + "ratelimit": int.parse(limitRequestsController.text), + "edns_cs_enabled": enableEdns, + "dnssec_enabled": enableDnssec, + "disable_ipv6": disableIpv6Resolving, + "blocking_mode": blockingMode + }); + + processModal.close(); + + if (result['result'] == 'success') { + DnsInfoData data = serversProvider.dnsInfo.data!; + data.ratelimit = int.parse(limitRequestsController.text); + data.ednsCsEnabled = enableEdns; + data.dnssecEnabled = enableDnssec; + data.disableIpv6 = disableIpv6Resolving; + data.blockingMode = blockingMode; + data.blockingIpv4 = ipv4controller.text; + data.blockingIpv6 = ipv6controller.text; + serversProvider.setDnsInfoData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigSaved, + color: Colors.green + ); + } + else if (result['log'] != null && result['log'].statusCode == '400') { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.someValueNotValid, + color: Colors.red + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigNotSaved, + color: Colors.red + ); + } + } void updateBlockingMode(String mode) { if (mode != 'custom_ip') { @@ -112,7 +176,7 @@ class _DnsServerSettingsScreenState extends State { actions: [ IconButton( onPressed: isDataValid == true - ? () => {} + ? () => saveData() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index d772592..28965e3 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -1,9 +1,17 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; class PrivateReverseDnsServersScreen extends StatefulWidget { final ServersProvider serversProvider; @@ -48,7 +56,6 @@ class _PrivateReverseDnsServersScreenState extends State element['controller'].text != '') && reverseResolversControllers.every((element) => element['error'] == null) ) == true @@ -68,10 +75,10 @@ class _PrivateReverseDnsServersScreenState extends State(context); + final appConfigProvider = Provider.of(context); + + void saveData() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingConfig); + + final result = await setDnsConfig(server: serversProvider.selectedServer!, data: editReverseResolvers == true + ? { + "local_ptr_upstreams": List.from(reverseResolversControllers.map((e) => e['controller'].text)), + "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, + "resolve_clients": enableReverseResolve + } : { + "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, + "resolve_clients": enableReverseResolve + }); + + processModal.close(); + + if (result['result'] == 'success') { + DnsInfoData data = serversProvider.dnsInfo.data!; + if (editReverseResolvers == true) { + data.localPtrUpstreams = List.from(reverseResolversControllers.map((e) => e['controller'].text)); + } + data.usePrivatePtrResolvers = usePrivateReverseDnsResolvers; + data.resolveClients = enableReverseResolve; + serversProvider.setDnsInfoData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigSaved, + color: Colors.green + ); + } + else if (result['log'] != null && result['log'].statusCode == '400') { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.someValueNotValid, + color: Colors.red + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigNotSaved, + color: Colors.red + ); + } + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.privateReverseDnsServers), actions: [ IconButton( onPressed: validValues == true - ? () => {} + ? () => saveData() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 8b416f3..1f3b2eb 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -1,9 +1,17 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class UpstreamDnsScreen extends StatefulWidget { @@ -51,13 +59,62 @@ class _UpstreamDnsScreenState extends State { @override Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + void saveData() async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.savingConfig); + + final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + "upstream_dns": upstreamControllers.map((e) => e.text).toList(), + "upstream_mode": upstreamMode + }); + + processModal.close(); + + if (result['result'] == 'success') { + DnsInfoData data = serversProvider.dnsInfo.data!; + data.upstreamDns = upstreamControllers.map((e) => e.text).toList(); + data.upstreamMode = upstreamMode; + serversProvider.setDnsInfoData(data); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigSaved, + color: Colors.green + ); + } + else if (result['log'] != null && result['log'].statusCode == '400') { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.someValueNotValid, + color: Colors.red + ); + } + else { + appConfigProvider.addLog(result['log']); + + showSnacbkar( + context: context, + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.dnsConfigNotSaved, + color: Colors.red + ); + } + } + return Scaffold( appBar: AppBar( title: Text(AppLocalizations.of(context)!.upstreamDns), actions: [ IconButton( onPressed: validValues == true - ? () => {} + ? () => saveData() : null, icon: const Icon(Icons.save_rounded), tooltip: AppLocalizations.of(context)!.save, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 50a0dd2..a7a943b 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -1654,4 +1654,50 @@ Future getDnsInfo({ else { return result; } +} + +Future setDnsConfig({ + required Server server, + required Map data, +}) async { + final result = await apiRequest( + urlPath: '/dns_config', + method: 'post', + server: server, + body: data, + type: 'set_dns_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + if (result['statusCode'] == 400) { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_dns_config', + dateTime: DateTime.now(), + message: 'data_not_valid', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_dns_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } \ No newline at end of file