diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2fc732c..cc45a00 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -681,5 +681,6 @@ "failedElements": "Failed elements", "processingLists": "Processing lists...", "enableDisableResult": "Enable or disable result", - "selectedListsEnabledDisabledSuccessfully": "All selected lists have been enabled or disabled successfully" + "selectedListsEnabledDisabledSuccessfully": "All selected lists have been enabled or disabled successfully", + "sslWarning": "If you are using an HTTPS connection with a self signed certificate, make sure to enable \"Don't check SSL certificate\" at Settings > Advanced settings." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 6f2d8d6..9676508 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -681,5 +681,6 @@ "failedElements": "Elementos fallidos", "processingLists": "Procesando listas...", "enableDisableResult": "Resultado de activar o desactivar", - "selectedListsEnabledDisabledSuccessfully": "Todas las listas seleccionadas se han activado o desactivado correctamente." + "selectedListsEnabledDisabledSuccessfully": "Todas las listas seleccionadas se han activado o desactivado correctamente.", + "sslWarning": "Si estás usando una conexión HTTPS con un certificado autofirmado, asegúrate de activar \"No comprobar el certificado SSL\" en Ajustes > Ajustes avanzados." } \ No newline at end of file diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart index 692739c..a957fc3 100644 --- a/lib/services/api_client.dart +++ b/lib/services/api_client.dart @@ -36,6 +36,19 @@ class ApiClientV2 { required this.server }); + Future getServerVersion() async { + final result = await HttpRequestClient.get(urlPath: '/status', server: server); + if (result.successful == true) { + return ApiResponse( + successful: true, + content: jsonDecode(result.body!)['version'] + ); + } + else { + return const ApiResponse(successful: false); + } + } + Future getServerStatus() async { final results = await Future.wait([ HttpRequestClient.get(urlPath: "/stats", server: server), diff --git a/lib/services/auth.dart b/lib/services/auth.dart new file mode 100644 index 0000000..a450348 --- /dev/null +++ b/lib/services/auth.dart @@ -0,0 +1,82 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:adguard_home_manager/classes/http_client.dart'; +import 'package:adguard_home_manager/models/server.dart'; + +enum AuthStatus { + success, + invalidCredentials, + manyAttepts, + serverError, + socketException, + timeoutException, + handshakeException, + unknown +} + +class ServerAuth { + static Future login(Server server) async { + try { + final body = { + "name": server.user, + "password": server.password + }; + final connectionString = "${server.connectionMethod}://${server.domain}${server.port != null ? ':${server.port}' : ""}${server.path ?? ""}/control/login"; + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.postUrl(Uri.parse(connectionString)); + request.headers.set('content-type', 'application/json'); + request.headers.contentLength = utf8.encode(jsonEncode(body)).length; + request.add(utf8.encode(json.encode(body))); + HttpClientResponse response = await request.close().timeout(const Duration(seconds: 10)); + httpClient.close(); + if (response.statusCode == 200) { + return AuthStatus.success; + } + else if (response.statusCode == 400 || response.statusCode == 401 || response.statusCode == 403) { + return AuthStatus.invalidCredentials; + } + else if (response.statusCode == 429) { + return AuthStatus.manyAttepts; + } + else if (response.statusCode == 500) { + return AuthStatus.serverError; + } + else { + return AuthStatus.unknown; + } + } on SocketException { + return AuthStatus.socketException; + } on TimeoutException { + return AuthStatus.timeoutException; + } on HandshakeException { + return AuthStatus.handshakeException; + } catch (e) { + return AuthStatus.unknown; + } + } + + static Future loginHA(Server server) async { + try { + final result = await HttpRequestClient.get(urlPath: "/status", server: server); + if (result.successful) { + return AuthStatus.success; + } + else if (result.statusCode == 401 || result.statusCode == 403) { + return AuthStatus.invalidCredentials; + } + else { + return AuthStatus.unknown; + } + } on SocketException { + return AuthStatus.socketException; + } on TimeoutException { + return AuthStatus.timeoutException; + } on HandshakeException { + return AuthStatus.handshakeException; + } catch (e) { + return AuthStatus.unknown; + } + } +} \ No newline at end of file diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index 509ed95..049bf7f 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -1,5 +1,4 @@ // ignore_for_file: use_build_context_synchronously - import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import 'package:segmented_button_slide/segmented_button_slide.dart'; @@ -11,6 +10,8 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/widgets/add_server/add_server_functions.dart'; +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/services/auth.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/api_client.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -19,7 +20,6 @@ import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/base64.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; @@ -32,11 +32,11 @@ class AddServerModal extends StatefulWidget { final void Function(String version) onUnsupportedVersion; const AddServerModal({ - Key? key, + super.key, this.server, required this.fullScreen, required this.onUnsupportedVersion - }) : super(key: key); + }); @override State createState() => _AddServerModalState(); @@ -119,11 +119,11 @@ class _AddServerModalState extends State { )); } - String getErrorMessage(String message) { - if (message == 'invalid_username_password') return AppLocalizations.of(context)!.invalidUsernamePassword; - if (message == 'many_attempts') return AppLocalizations.of(context)!.tooManyAttempts; - if (message == 'no_connection') return AppLocalizations.of(context)!.cantReachServer; - if (message == 'server_error') return AppLocalizations.of(context)!.serverError; + String getErrorMessage(AuthStatus status) { + if (status == AuthStatus.invalidCredentials) return AppLocalizations.of(context)!.invalidUsernamePassword; + if (status == AuthStatus.manyAttepts) return AppLocalizations.of(context)!.tooManyAttempts; + if (status == AuthStatus.socketException || status == AuthStatus.timeoutException) return AppLocalizations.of(context)!.cantReachServer; + if (status == AuthStatus.serverError) return AppLocalizations.of(context)!.serverError; return AppLocalizations.of(context)!.unknownError; } @@ -146,17 +146,16 @@ class _AddServerModalState extends State { ); final result = homeAssistant == true - ? await loginHA(serverObj) - : await login(serverObj); + ? await ServerAuth.loginHA(serverObj) + : await ServerAuth.login(serverObj); // If something goes wrong with the connection - if (result['result'] != 'success') { + if (result != AuthStatus.success) { cancelConnecting(); - appConfigProvider.addLog(result['log']); if (mounted) { showSnacbkar( appConfigProvider: appConfigProvider, - label: getErrorMessage(result['result']), + label: getErrorMessage(result), color: Colors.red ); } @@ -172,13 +171,6 @@ class _AddServerModalState extends State { // If something goes wrong when saving the connection on the db if (serverCreated != null) { if (mounted) setState(() => isConnecting = false); - appConfigProvider.addLog( - AppLog( - type: 'save_connection_db', - dateTime: DateTime.now(), - message: serverCreated.toString() - ) - ); if (mounted) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -190,27 +182,27 @@ class _AddServerModalState extends State { } statusProvider.setServerStatusLoad(LoadStatus.loading); - final ApiClient apiClient = ApiClient(server: serverObj); - final serverStatus = await apiClient.getServerStatus(); final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); - final serverStatus2 = await apiClient2.getServerStatus(); + final serverStatus = await apiClient2.getServerStatus(); // If something goes wrong when fetching server status - if (serverStatus2.successful == false) { + if (serverStatus.successful == false) { statusProvider.setServerStatusLoad(LoadStatus.error); Navigator.pop(context); return; } + final status = serverStatus.content as ServerStatus; + // If everything is successful statusProvider.setServerStatusData( - data: serverStatus['data'] + data: status ); - serversProvider.setApiClient(apiClient); + serversProvider.setApiClient2(apiClient2); statusProvider.setServerStatusLoad(LoadStatus.loaded); - if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { + if (status.serverVersion.contains('a') || status.serverVersion.contains('b')) { Navigator.pop(context); - widget.onUnsupportedVersion(serverStatus['data'].serverVersion); + widget.onUnsupportedVersion(status.serverVersion); } else { Navigator.pop(context); @@ -236,17 +228,16 @@ class _AddServerModalState extends State { ); final result = homeAssistant == true - ? await loginHA(serverObj) - : await login(serverObj); + ? await ServerAuth.loginHA(serverObj) + : await ServerAuth.login(serverObj); // If something goes wrong with the connection - if (result['result'] != 'success') { + if (result != AuthStatus.success) { cancelConnecting(); - appConfigProvider.addLog(result['log']); if (mounted) { showSnacbkar( appConfigProvider: appConfigProvider, - label: getErrorMessage(result['result']), + label: getErrorMessage(result), color: Colors.red ); } @@ -279,14 +270,14 @@ class _AddServerModalState extends State { } // If everything is successful - final ApiClient apiClient = ApiClient(server: serverObj); - final version = await apiClient.getServerVersion(); + final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); + final version = await apiClient2.getServerVersion(); if ( - version['result'] == 'success' && - (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta + version.successful == true && + (version.content.contains('a') || version.content.contains('b')) // alpha or beta ) { Navigator.pop(context); - widget.onUnsupportedVersion(version['data']); + widget.onUnsupportedVersion(version.content); } else { Navigator.pop(context);