From 137a976a36561bedc41263f29340213f7a3a7b56 Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Sat, 22 Oct 2022 23:06:27 +0200 Subject: [PATCH] Created config encryption UI --- lib/l10n/app_en.arb | 27 +- lib/l10n/app_es.arb | 27 +- lib/models/encryption.dart | 108 +++++ lib/providers/servers_provider.dart | 26 +- .../settings/encryption/encryption.dart | 452 ++++++++++++++++++ lib/screens/settings/settings.dart | 16 +- lib/services/http_requests.dart | 36 ++ 7 files changed, 687 insertions(+), 5 deletions(-) create mode 100644 lib/models/encryption.dart create mode 100644 lib/screens/settings/encryption/encryption.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 0ad60e7..a7cd559 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -490,5 +490,30 @@ "dnsCacheConfigDescription": "Configure how the server should manage the DNS cache", "comment": "Comment", "address": "Address", - "commentsDescription": "Comments are always preceded by #. You don't have to add it, it will be added automatically." + "commentsDescription": "Comments are always preceded by #. You don't have to add it, it will be added automatically.", + "encryptionSettings": "Encryption settings", + "encryptionSettingsDescription": "Encryption (HTTPS/QUIC/TLS) support", + "loadingEncryptionSettings": "Loading encryption settings...", + "encryptionSettingsNotLoaded": "Encryption settings couldn't be loaded.", + "enableEncryption": "Enable encryption", + "enableEncryptionTypes": "HTTPS, DNS-over-HTTPS, and DNS-over-TLS", + "enableEncryptionDescription": "If encryption is enabled, AdGuard Home admin interface will work over HTTPS, and the DNS server will listen for requests over DNS-over-HTTPS and DNS-over-TLS.", + "serverConfiguration": "Server configuration", + "domainName": "Domain name", + "domainNameDescription": "If set, AdGuard Home detects ClientIDs, responds to DDR queries, and performs additional connection validations. If not set, these features are disabled. Must match one of the DNS Names in the certificate.", + "redirectHttps": "Redirect to HTTPS automatically", + "httpsPort": "HTTPS port", + "tlsPort": "DNS-over-TLS port", + "dnsOverQuicPort": "DNS-over-QUIC port", + "certificates": "Certificates", + "certificatesDescription": "In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.", + "certificateFilePath": "Set a certificates file path", + "pasteCertificateContent": "Paste the certificates contents", + "certificatePath": "Certificate path", + "certificateContent": "Certificate content", + "privateKey": "Private key", + "privateKeyFile": "Set a private key file", + "pastePrivateKey": "Paste the private key contents", + "usePreviousKey": "Use the previously saved key", + "privateKeyPath": "Private key path" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2b1b55d..431b608 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -490,5 +490,30 @@ "dnsCacheConfigDescription": "Configura cómo el servidor debe manejar la caché del DNS", "comment": "Comentario", "address": "Dirección", - "commentsDescription": "Los comentarios siempre van precedidos por #. No necesitas añadirlo. Se añadirá automáticamente." + "commentsDescription": "Los comentarios siempre van precedidos por #. No necesitas añadirlo. Se añadirá automáticamente.", + "encryptionSettings": "Configuración de cifrado", + "encryptionSettingsDescription": "Soporte de cifrado (HTTPS/QUIC/TLS)", + "loadingEncryptionSettings": "Cargando configuración de cifrado...", + "encryptionSettingsNotLoaded": "No se ha podido cargar la configuración de cifrado.", + "enableEncryption": "Habilitar cifrado", + "enableEncryptionTypes": "HTTPS, DNS mediante HTTPS y DNS mediante TLS", + "enableEncryptionDescription": "Si el cifrado está habilitado, la interfaz de administración de AdGuard Home funcionará a través de HTTPS, y el servidor DNS escuchará las peticiones DNS mediante HTTPS y DNS mediante TLS.", + "serverConfiguration": "Configuración del servidor", + "domainName": "Nombre de dominio", + "domainNameDescription": "Si se configura, AdGuard Home detecta los ID de clientes, responde a las consultas DDR y realiza validaciones de conexión adicionales. Si no se configura, estas funciones se deshabilitarán. Debe coincidir con uno de los nombres DNS del certificado.", + "redirectHttps": "Redireccionar automáticamente a HTTPS", + "httpsPort": "Puerto HTTPS", + "tlsPort": "Puerto DNS sobre TLS", + "dnsOverQuicPort": "Puerto DNS sobre QUIC", + "certificates": "Certificados", + "certificatesDescription": "Para utilizar el cifrado, debes proporcionar una cadena de certificado SSL válida para tu dominio. Puedes obtener un certificado gratuito en letsencrypt.org o puedes comprarlo en una de las autoridades de certificación de confianza.", + "certificateFilePath": "Establecer una ruta para el archivo de certificado", + "pasteCertificateContent": "Pegar el contenido del certificado", + "certificatePath": "Ruta de acceso al certificado", + "certificateContent": "Contenido del certificado", + "privateKey": "Clave privada", + "privateKeyFile": "Establecer un archivo de clave privada", + "pastePrivateKey": "Pegar el contenido de la clave privada", + "usePreviousKey": "Usar la clave privada guardada previamente", + "privateKeyPath": "Ruta de la clave privada" } \ No newline at end of file diff --git a/lib/models/encryption.dart b/lib/models/encryption.dart new file mode 100644 index 0000000..9f90757 --- /dev/null +++ b/lib/models/encryption.dart @@ -0,0 +1,108 @@ +import 'dart:convert'; + +class Encryption { + int loadStatus = 0; + EncryptionData? data; + + Encryption({ + required this.loadStatus, + this.data + }); +} + +EncryptionData encryptionDataFromJson(String str) => EncryptionData.fromJson(json.decode(str)); + +String encryptionDataToJson(EncryptionData data) => json.encode(data.toJson()); + +class EncryptionData { + final bool validCert; + final bool validChain; + final DateTime notBefore; + final DateTime notAfter; + final dynamic dnsNames; + final bool validKey; + final bool validPair; + final bool enabled; + final bool forceHttps; + final int portHttps; + final int portDnsOverTls; + final int portDnsOverQuic; + final int portDnscrypt; + final String dnscryptConfigFile; + final bool allowUnencryptedDoh; + final String certificateChain; + final String privateKey; + final String certificatePath; + final String privateKeyPath; + final bool privateKeySaved; + + EncryptionData({ + required this.validCert, + required this.validChain, + required this.notBefore, + required this.notAfter, + required this.dnsNames, + required this.validKey, + required this.validPair, + required this.enabled, + required this.forceHttps, + required this.portHttps, + required this.portDnsOverTls, + required this.portDnsOverQuic, + required this.portDnscrypt, + required this.dnscryptConfigFile, + required this.allowUnencryptedDoh, + required this.certificateChain, + required this.privateKey, + required this.certificatePath, + required this.privateKeyPath, + required this.privateKeySaved, + }); + + + factory EncryptionData.fromJson(Map json) => EncryptionData( + validCert: json["valid_cert"], + validChain: json["valid_chain"], + notBefore: DateTime.parse(json["not_before"]), + notAfter: DateTime.parse(json["not_after"]), + dnsNames: json["dns_names"], + validKey: json["valid_key"], + validPair: json["valid_pair"], + enabled: json["enabled"], + forceHttps: json["force_https"], + portHttps: json["port_https"], + portDnsOverTls: json["port_dns_over_tls"], + portDnsOverQuic: json["port_dns_over_quic"], + portDnscrypt: json["port_dnscrypt"], + dnscryptConfigFile: json["dnscrypt_config_file"], + allowUnencryptedDoh: json["allow_unencrypted_doh"], + certificateChain: json["certificate_chain"], + privateKey: json["private_key"], + certificatePath: json["certificate_path"], + privateKeyPath: json["private_key_path"], + privateKeySaved: json["private_key_saved"], + ); + + Map toJson() => { + "valid_cert": validCert, + "valid_chain": validChain, + "not_before": notBefore.toIso8601String(), + "not_after": notAfter.toIso8601String(), + "dns_names": dnsNames, + "valid_key": validKey, + "valid_pair": validPair, + "enabled": enabled, + "force_https": forceHttps, + "port_https": portHttps, + "port_dns_over_tls": portDnsOverTls, + "port_dns_over_quic": portDnsOverQuic, + "port_dnscrypt": portDnscrypt, + "dnscrypt_config_file": dnscryptConfigFile, + "allow_unencrypted_doh": allowUnencryptedDoh, + "certificate_chain": certificateChain, + "private_key": privateKey, + "certificate_path": certificatePath, + "private_key_path": privateKeyPath, + "private_key_saved": privateKeySaved, + }; +} diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 9ec86c0..63dbccb 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -7,11 +7,12 @@ import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; +import 'package:adguard_home_manager/models/encryption.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/models/server.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/functions/conversions.dart'; class ServersProvider with ChangeNotifier { Database? _dbInstance; @@ -49,6 +50,11 @@ class ServersProvider with ChangeNotifier { data: null ); + final Encryption _encryptionSettings = Encryption( + loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error, + data: null + ); + FilteringStatus? _filteringStatus; List get serversList { @@ -91,6 +97,10 @@ class ServersProvider with ChangeNotifier { return _dnsInfo; } + Encryption get encryptionSettings { + return _encryptionSettings; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -201,6 +211,18 @@ class ServersProvider with ChangeNotifier { } } + void setEncryptionSettings(EncryptionData data) { + _encryptionSettings.data = data; + notifyListeners(); + } + + void setEncryptionSettingsLoadStatus(int status, bool notify) { + _encryptionSettings.loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + Future createServer(Server server) async { final saved = await saveServerIntoDb(server); if (saved == true) { diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart new file mode 100644 index 0000000..75f5855 --- /dev/null +++ b/lib/screens/settings/encryption/encryption.dart @@ -0,0 +1,452 @@ +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_switch_list_tile.dart'; + +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; + +class EncryptionSettings extends StatelessWidget { + const EncryptionSettings({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + return EncryptionSettingsWidget( + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + ); + } +} + +class EncryptionSettingsWidget extends StatefulWidget { + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + + const EncryptionSettingsWidget({ + Key? key, + required this.serversProvider, + required this.appConfigProvider, + }) : super(key: key); + + @override + State createState() => _EncryptionSettingsWidgetState(); +} + +class _EncryptionSettingsWidgetState extends State { + bool enabled = false; + + final TextEditingController domainNameController = TextEditingController(); + String? domainError; + + bool redirectHttps = false; + + final TextEditingController httpsPortController = TextEditingController(); + String? httpsPortError; + + final TextEditingController tlsPortController = TextEditingController(); + String? tlsPortError; + + final TextEditingController dnsOverQuicPortController = TextEditingController(); + String? dnsOverQuicPortError; + + int certificateOption = 0; + + final TextEditingController certificatePathController = TextEditingController(); + String? certificatePathError; + + final TextEditingController certificateContentController = TextEditingController(); + String? certificateContentError; + + int privateKeyOption = 0; + + bool usePreviouslySavedKey = false; + + final TextEditingController privateKeyPathController = TextEditingController(); + String? privateKeyPathError; + + final TextEditingController pastePrivateKeyController = TextEditingController(); + String? pastePrivateKeyError; + + + void fetchData({bool? showRefreshIndicator}) async { + widget.serversProvider.setEncryptionSettingsLoadStatus(0, showRefreshIndicator ?? false); + + final result = await getEncryptionSettings(server: widget.serversProvider.selectedServer!); + + if (mounted) { + if (result['result'] == 'success') { + widget.serversProvider.setEncryptionSettings(result['data']); + widget.serversProvider.setEncryptionSettingsLoadStatus(1, true); + } + else { + widget.appConfigProvider.addLog(result['log']); + widget.serversProvider.setEncryptionSettingsLoadStatus(2, true); + } + } + } + + @override + void initState() { + fetchData(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + Widget generateBody() { + switch (widget.serversProvider.encryptionSettings.loadStatus) { + case 0: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator(), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.loadingEncryptionSettings, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 22, + color: Colors.grey, + ), + ) + ], + ) + ); + + case 1: + return ListView( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + left: 12, + right: 12 + ), + child: Material( + color: Theme.of(context).primaryColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(28), + child: InkWell( + onTap: () => setState(() => enabled = !enabled), + borderRadius: BorderRadius.circular(28), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.enableEncryption, + style: const TextStyle( + fontSize: 18, + ), + ), + const SizedBox(height: 3), + Text( + AppLocalizations.of(context)!.enableEncryptionTypes, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).listTileTheme.iconColor, + ), + ) + ], + ), + ), + Switch( + value: enabled, + onChanged: (value) => setState(() => enabled = value), + activeColor: Theme.of(context).primaryColor, + ), + ], + ), + ), + ), + ), + ), + SectionLabel(label: AppLocalizations.of(context)!.serverConfiguration), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: domainNameController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.link_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: domainError, + labelText: AppLocalizations.of(context)!.domainName, + helperText: AppLocalizations.of(context)!.domainNameDescription, + helperMaxLines: 10 + ), + ), + ), + const SizedBox(height: 10), + CustomSwitchListTile( + value: redirectHttps, + onChanged: (value) => setState(() => redirectHttps = value), + title: AppLocalizations.of(context)!.redirectHttps, + ), + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: httpsPortController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.numbers_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: httpsPortError, + labelText: AppLocalizations.of(context)!.httpsPort, + ), + keyboardType: TextInputType.number, + ), + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: tlsPortController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.numbers_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: tlsPortError, + labelText: AppLocalizations.of(context)!.tlsPort, + ), + keyboardType: TextInputType.number, + ), + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: dnsOverQuicPortController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.numbers_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: dnsOverQuicPortError, + labelText: AppLocalizations.of(context)!.dnsOverQuicPort, + ), + keyboardType: TextInputType.number, + ), + ), + SectionLabel(label: AppLocalizations.of(context)!.certificates), + Card( + margin: const EdgeInsets.symmetric(horizontal: 20), + child: Padding( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + const Icon(Icons.info_rounded), + const SizedBox(width: 20), + Flexible( + child: Text(AppLocalizations.of(context)!.certificatesDescription) + ) + ], + ), + ), + ), + const SizedBox(height: 20), + RadioListTile( + value: 0, + groupValue: certificateOption, + onChanged: (value) => setState(() => certificateOption = value!), + title: Text( + AppLocalizations.of(context)!.certificateFilePath, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + RadioListTile( + value: 1, + groupValue: certificateOption, + onChanged: (value) => setState(() => certificateOption = value!), + title: Text( + AppLocalizations.of(context)!.pasteCertificateContent, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + const SizedBox(height: 10), + if (certificateOption == 0) Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: certificatePathController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.description_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: certificatePathError, + labelText: AppLocalizations.of(context)!.certificatePath, + ), + ), + ), + if (certificateOption == 1) Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: certificateContentController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.description_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: certificateContentError, + labelText: AppLocalizations.of(context)!.certificateContent, + ), + keyboardType: TextInputType.multiline, + maxLines: null, + ), + ), + SectionLabel(label: AppLocalizations.of(context)!.privateKey), + RadioListTile( + value: 0, + groupValue: privateKeyOption, + onChanged: (value) => setState(() => privateKeyOption = value!), + title: Text( + AppLocalizations.of(context)!.privateKeyFile, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + RadioListTile( + value: 1, + groupValue: privateKeyOption, + onChanged: (value) => setState(() => privateKeyOption = value!), + title: Text( + AppLocalizations.of(context)!.pastePrivateKey, + style: const TextStyle( + fontWeight: FontWeight.normal + ), + ), + ), + if (privateKeyOption == 0) const SizedBox(height: 10), + if (privateKeyOption == 1) ...[ + CustomSwitchListTile( + value: usePreviouslySavedKey, + onChanged: (value) => setState(() => usePreviouslySavedKey = value), + title: AppLocalizations.of(context)!.usePreviousKey, + ), + const SizedBox(height: 10) + ], + if (privateKeyOption == 0) Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + controller: privateKeyPathController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.description_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: privateKeyPathError, + labelText: AppLocalizations.of(context)!.privateKeyPath, + ), + ), + ), + if (privateKeyOption == 1) Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: TextFormField( + enabled: !usePreviouslySavedKey, + controller: pastePrivateKeyController, + // onChanged: + decoration: InputDecoration( + prefixIcon: const Icon(Icons.description_rounded), + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(10) + ) + ), + errorText: pastePrivateKeyError, + labelText: AppLocalizations.of(context)!.pastePrivateKey, + ), + keyboardType: TextInputType.multiline, + maxLines: null, + ), + ), + const SizedBox(height: 20), + ], + ); + + case 2: + return SizedBox( + width: double.maxFinite, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon( + Icons.error, + color: Colors.red, + size: 50, + ), + const SizedBox(height: 30), + Text( + AppLocalizations.of(context)!.encryptionSettingsNotLoaded, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 22, + color: Colors.grey, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.encryptionSettings), + ), + body: generateBody(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 6105209..a7d7863 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -6,7 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/theme_modal.dart'; import 'package:adguard_home_manager/screens/settings/server_info/server_info.dart'; -import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/screens/settings/encryption/encryption.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/access_settings.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/dhcp.dart'; import 'package:adguard_home_manager/screens/settings/section_label.dart'; @@ -17,6 +17,8 @@ import 'package:adguard_home_manager/screens/servers/servers.dart'; import 'package:adguard_home_manager/screens/settings/advanced_setings.dart'; import 'package:adguard_home_manager/screens/settings/general_settings.dart'; +import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; + import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -126,6 +128,18 @@ class Settings extends StatelessWidget { ) }, ), + CustomListTile( + icon: Icons.security_rounded, + title: AppLocalizations.of(context)!.encryptionSettings, + subtitle: AppLocalizations.of(context)!.encryptionSettingsDescription, + onTap: () => { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const EncryptionSettings() + ) + ) + }, + ), CustomListTile( icon: Icons.route_rounded, title: AppLocalizations.of(context)!.dnsRewrites, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 6286dce..fb2aa10 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -6,6 +6,7 @@ import 'dart:io'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/models/dns_info.dart'; +import 'package:adguard_home_manager/models/encryption.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; @@ -1704,4 +1705,39 @@ Future setDnsConfig({ else { return result; } +} + +Future getEncryptionSettings({ + required Server server, +}) async { + final result = await apiRequest( + urlPath: '/tls/status', + method: 'get', + server: server, + type: 'get_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': EncryptionData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } \ No newline at end of file