From 525facc538865b848c98cc3db8f72d4885ab728d Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 4 Oct 2023 19:20:43 +0200 Subject: [PATCH] Bug fixes --- lib/models/dhcp.dart | 4 +- lib/models/dns_info.dart | 2 +- lib/providers/servers_provider.dart | 14 +- lib/screens/home/home.dart | 2 +- lib/screens/home/management_modal.dart | 2 +- lib/screens/settings/dns/cache_config.dart | 2 +- lib/screens/top_items/top_items.dart | 2 +- lib/services/http_requests.dart | 258 ++++++++++++--------- lib/widgets/add_server_modal.dart | 6 + 9 files changed, 171 insertions(+), 121 deletions(-) diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index aaf4a42..c04ecc9 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -72,8 +72,8 @@ class DhcpStatus { factory DhcpStatus.fromJson(Map json) => DhcpStatus( interfaceName: json["interface_name"], - v4: IpVersion.fromJson(json["v4"]), - v6: IpVersion.fromJson(json["v6"]), + v4: json["v4"] != null ? IpVersion.fromJson(json["v4"]) : null, + v6: json["v6"] != null ? IpVersion.fromJson(json["v6"]) : null, leases: List.from(json["leases"].map((x) => Lease.fromJson(x))), staticLeases: List.from(json["static_leases"].map((x) => Lease.fromJson(x))), enabled: json["enabled"], diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 138efa3..5ab3cc2 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -12,7 +12,7 @@ class DnsInfo { int? cacheSize; int? cacheTtlMin; int? cacheTtlMax; - bool cacheOptimistic; + bool? cacheOptimistic; bool resolveClients; bool usePrivatePtrResolvers; List localPtrUpstreams; diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index c745260..601e149 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -169,12 +169,14 @@ class ServersProvider with ChangeNotifier { void checkServerUpdatesAvailable({ required Server server, + ApiClient? apiClient }) async { + final client = apiClient ?? _apiClient; setUpdateAvailableLoadStatus(LoadStatus.loading, true); - final result = await _apiClient!.checkServerUpdates(); + final result = await client!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await _apiClient!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await client!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult['result'] == 'success') { data.changelog = gitHubResult['body']; } @@ -186,11 +188,12 @@ class ServersProvider with ChangeNotifier { } } - Future initializateServer(Server server) async { + Future initializateServer(Server server, ApiClient apiClient) async { final serverStatus = await _apiClient!.getServerStatus(); if (serverStatus['result'] == 'success') { checkServerUpdatesAvailable( // Do not await server: server, + apiClient: apiClient ); } } @@ -222,8 +225,9 @@ class ServersProvider with ChangeNotifier { if (defaultServer != null) { _selectedServer = defaultServer; - _apiClient = ApiClient(server: defaultServer); - initializateServer(defaultServer); + final client = ApiClient(server: defaultServer); + _apiClient = client; + initializateServer(defaultServer, client); } } else { diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index a37eee7..7acfa63 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -304,7 +304,7 @@ class _HomeState extends State { displacement: 95, onRefresh: () async { final result = await statusProvider.getServerStatus(); - if (result == false) { + if (mounted && result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index aaeaab7..d23ddd4 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -80,7 +80,7 @@ class _ManagementModalState extends State with SingleTickerProv newStatus: value, time: time ); - if (result != null) { + if (mounted && result != null) { if (result != false) { appConfigProvider.addLog(result); } diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index cd2968b..eb5aad3 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -58,7 +58,7 @@ class _CacheConfigDnsScreenState extends State { cacheSizeController.text = dnsProvider.dnsInfo!.cacheSize.toString(); overrideMinTtlController.text = dnsProvider.dnsInfo!.cacheTtlMin.toString(); overrideMaxTtlController.text = dnsProvider.dnsInfo!.cacheTtlMax.toString(); - optimisticCache = dnsProvider.dnsInfo!.cacheOptimistic; + optimisticCache = dnsProvider.dnsInfo!.cacheOptimistic ?? false; validData = true; super.initState(); } diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 6e9af74..f536b47 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -130,7 +130,7 @@ class _TopItemsScreenState extends State { body: RefreshIndicator( onRefresh: () async { final result = await statusProvider.getServerStatus(); - if (result == false) { + if (mounted && result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 85de805..c2b2c59 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -20,6 +20,7 @@ import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; Future> apiRequest({ @@ -270,80 +271,107 @@ class ApiClient { }); Future getServerVersion() async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/status', - type: 'get_server_version' - ); + try { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/status', + type: 'get_server_version' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200 && result['body'] != null) { - return { - 'result': 'success', - 'data': jsonDecode(result['body'])['version'] - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200 && result['body'] != null) { + return { + 'result': 'success', + 'data': jsonDecode(result['body'])['version'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_version', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } - } - else { - return result; + } catch (e) { + Sentry.captureException(e); + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + resBody: e.toString() + ) + }; } } Future getServerStatus() async { - final result = await Future.wait([ - apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), - ]); + try { + final result = await Future.wait([ + apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), + ]); - if ( - result[0]['hasResponse'] == true && - result[1]['hasResponse'] == true && - result[2]['hasResponse'] == true && - result[3]['hasResponse'] == true && - result[4]['hasResponse'] == true && - result[5]['hasResponse'] == true && - result[6]['hasResponse'] == true - ) { if ( - result[0]['statusCode'] == 200 && - result[1]['statusCode'] == 200 && - result[2]['statusCode'] == 200 && - result[3]['statusCode'] == 200 && - result[4]['statusCode'] == 200 && - result[5]['statusCode'] == 200 && - result[6]['statusCode'] == 200 + result[0]['hasResponse'] == true && + result[1]['hasResponse'] == true && + result[2]['hasResponse'] == true && + result[3]['hasResponse'] == true && + result[4]['hasResponse'] == true && + result[5]['hasResponse'] == true && + result[6]['hasResponse'] == true ) { - final Map mappedData = { - 'stats': jsonDecode(result[0]['body']), - 'clients': jsonDecode(result[6]['body'])['clients'], - 'status': jsonDecode(result[1]['body']), - 'filtering': jsonDecode(result[2]['body']), - 'safeSearch': jsonDecode(result[3]['body']), - 'safeBrowsingEnabled': jsonDecode(result[4]['body']), - 'parentalControlEnabled': jsonDecode(result[5]['body']), - }; - return { - 'result': 'success', - 'data': ServerStatus.fromJson(mappedData) - }; + if ( + result[0]['statusCode'] == 200 && + result[1]['statusCode'] == 200 && + result[2]['statusCode'] == 200 && + result[3]['statusCode'] == 200 && + result[4]['statusCode'] == 200 && + result[5]['statusCode'] == 200 && + result[6]['statusCode'] == 200 + ) { + final Map mappedData = { + 'stats': jsonDecode(result[0]['body']), + 'clients': jsonDecode(result[6]['body'])['clients'], + 'status': jsonDecode(result[1]['body']), + 'filtering': jsonDecode(result[2]['body']), + 'safeSearch': jsonDecode(result[3]['body']), + 'safeBrowsingEnabled': jsonDecode(result[4]['body']), + 'parentalControlEnabled': jsonDecode(result[5]['body']), + }; + return { + 'result': 'success', + 'data': ServerStatus.fromJson(mappedData) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode']).toString(), + resBody: result.map((res) => res['body']).toString() + ) + }; + } } else { return { @@ -351,24 +379,23 @@ class ApiClient { 'log': AppLog( type: 'get_server_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result.map((res) => res['statusCode']).toString(), - resBody: result.map((res) => res['body']).toString() + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString() ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString() - ) - }; + 'result': 'error', + 'log': AppLog( + type: 'get_server_status', + dateTime: DateTime.now(), + message: 'no_response', + resBody: e.toString() + ) + }; } } @@ -2004,34 +2031,48 @@ class ApiClient { } Future checkServerUpdates() async { - final result = await Future.wait([ - apiRequest( - urlPath: '/version.json', - method: 'post', - server: server, - type: 'check_server_updates', - body: { - "recheck_now": true - } - ), - apiRequest( - urlPath: '/status', - method: 'get', - server: server, - type: 'check_server_updates', - ), - ]); + try { + final result = await Future.wait([ + apiRequest( + urlPath: '/version.json', + method: 'post', + server: server, + type: 'check_server_updates', + body: { + "recheck_now": true + } + ), + apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'check_server_updates', + ), + ]); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - final Map obj = { - ...jsonDecode(result[0]['body']), - 'current_version': ServerInfoData.fromJson(jsonDecode(result[1]['body'])).version - }; - return { - 'result': 'success', - 'data': obj - }; + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + final Map obj = { + ...jsonDecode(result[0]['body']), + 'current_version': ServerInfoData.fromJson(jsonDecode(result[1]['body'])).version + }; + return { + 'result': 'success', + 'data': obj + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -2039,22 +2080,21 @@ class ApiClient { 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } - } - else { + } catch (e) { + Sentry.captureException(e); return { 'result': 'error', 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), + resBody: e.toString(), ) }; } diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 362eee9..c7604a1 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -256,6 +256,8 @@ class _AddServerModalState extends State { ? await loginHA(serverObj) : await login(serverObj); + if (!mounted) return; + if (result['result'] == 'success') { if (serverObj.user != null && serverObj.password != null) { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); @@ -268,6 +270,8 @@ class _AddServerModalState extends State { final serverStatus = await apiClient.getServerStatus(); + if (!mounted) return; + if (serverStatus['result'] == 'success') { statusProvider.setServerStatusData( data: serverStatus['data'] @@ -380,12 +384,14 @@ class _AddServerModalState extends State { ? await loginHA(serverObj) : await login(serverObj); + if (!mounted) return; if (result['result'] == 'success') { if (serverObj.user != null && serverObj.password != null) { serverObj.authToken = encodeBase64UserPass(serverObj.user!, serverObj.password!); } final serverSaved = await serversProvider.editServer(serverObj); + if (!mounted) return; if (serverSaved == null) { final ApiClient apiClient = ApiClient(server: serverObj); final version = await apiClient.getServerVersion();