From 9f248d18a1c37823d73f62039603ad7f09a19c8e Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Thu, 29 Sep 2022 21:26:18 +0200 Subject: [PATCH] Changed allowed and blocked lists and added remove client --- lib/l10n/app_en.arb | 8 +- lib/l10n/app_es.arb | 8 +- lib/models/clients_allowed_blocked.dart | 14 +-- lib/providers/servers_provider.dart | 6 + lib/screens/clients/blocked_allowed_list.dart | 108 ++++++++++++++++++ lib/screens/clients/clients.dart | 44 ++++--- lib/screens/clients/remove_domain_modal.dart | 41 +++++++ lib/services/http_requests.dart | 25 ++++ 8 files changed, 227 insertions(+), 27 deletions(-) create mode 100644 lib/screens/clients/blocked_allowed_list.dart create mode 100644 lib/screens/clients/remove_domain_modal.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5361391..8c909eb 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -81,5 +81,11 @@ "clients": "Clients", "allowed": "Allowed", "blocked": "Blocked", - "noClientsList": "There are no clients on this list" + "noClientsList": "There are no clients on this list", + "activeClients": "Active", + "removeClient": "Remove client", + "removeClientMessage": "Are you sure you want to remove this client from the list?", + "confirm": "Confirm", + "removingClient": "Removing client...", + "clientNotRemoved": "Client could not be removed from the list" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2897262..30b9403 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -81,5 +81,11 @@ "clients": "Clientes", "allowed": "Permitidos", "blocked": "Bloqueados", - "noClientsList": "No hay clientes en esta lista" + "noClientsList": "No hay clientes en esta lista", + "activeClients": "Activos", + "removeClient": "Eliminar cliente", + "removeClientMessage": "Estás seguro que deseas eliminar este cliente de la lista?", + "confirm": "Confirmar", + "removingClient": "Eliminando cliente...", + "clientNotRemoved": "El cliente no pudo ser eliminado de la lista" } \ No newline at end of file diff --git a/lib/models/clients_allowed_blocked.dart b/lib/models/clients_allowed_blocked.dart index 2efcee4..14e9e8d 100644 --- a/lib/models/clients_allowed_blocked.dart +++ b/lib/models/clients_allowed_blocked.dart @@ -5,20 +5,20 @@ ClientsAllowedBlocked allowedBlockedFromJson(String str) => ClientsAllowedBlocke String allowedBlockedToJson(ClientsAllowedBlocked data) => json.encode(data.toJson()); class ClientsAllowedBlocked { + List allowedClients; + List disallowedClients; + List blockedHosts; + ClientsAllowedBlocked({ required this.allowedClients, required this.disallowedClients, required this.blockedHosts, }); - final List allowedClients; - final List disallowedClients; - final List blockedHosts; - factory ClientsAllowedBlocked.fromJson(Map json) => ClientsAllowedBlocked( - allowedClients: List.from(json["allowed_clients"].map((x) => x)), - disallowedClients: List.from(json["disallowed_clients"].map((x) => x)), - blockedHosts: List.from(json["blocked_hosts"].map((x) => x)), + allowedClients: json["allowed_clients"] != null ? List.from(json["allowed_clients"].map((x) => x)) : [], + disallowedClients: json["disallowed_clients"] != null ? List.from(json["disallowed_clients"].map((x) => x)) : [], + blockedHosts: json["blocked_hosts"] != null ? List.from(json["blocked_hosts"].map((x) => x)) : [], ); Map toJson() => { diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index e5771fc..6f43528 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; +import 'package:adguard_home_manager/models/clients_allowed_blocked.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'; @@ -78,6 +79,11 @@ class ServersProvider with ChangeNotifier { _clients.data = data; notifyListeners(); } + + void setAllowedDisallowedClientsBlockedDomains(ClientsAllowedBlocked data) { + _clients.data?.clientsAllowedBlocked = data; + notifyListeners(); + } Future createServer(Server server) async { final saved = await saveServerIntoDb(server); diff --git a/lib/screens/clients/blocked_allowed_list.dart b/lib/screens/clients/blocked_allowed_list.dart new file mode 100644 index 0000000..23857bb --- /dev/null +++ b/lib/screens/clients/blocked_allowed_list.dart @@ -0,0 +1,108 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; +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/clients/remove_domain_modal.dart'; + +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; + +class BlockedAllowedList extends StatelessWidget { + final String type; + final List data; + + const BlockedAllowedList({ + Key? key, + required this.type, + required this.data + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + + void confirmRemoveDomain(String domain) async { + Map> body = {}; + + if (type == 'allowed') { + body = { + "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients.where((client) => client != domain).toList() ?? [], + "disallowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": serversProvider.clients.data!.clientsAllowedBlocked?.blockedHosts ?? [], + }; + } + else if (type == 'blocked') { + body = { + "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.disallowedClients.where((client) => client != domain).toList() ?? [], + "blocked_hosts": serversProvider.clients.data!.clientsAllowedBlocked?.blockedHosts ?? [], + }; + } + + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.removingClient); + + final result = await requestAllowedBlockedClientsHosts(serversProvider.selectedServer!, body); + + processModal.close(); + + if (result['result'] == 'success') { + serversProvider.setAllowedDisallowedClientsBlockedDomains( + ClientsAllowedBlocked( + allowedClients: body['allowed_clients'] ?? [], + disallowedClients: body['disallowed_clients'] ?? [], + blockedHosts: body['blocked_hosts'] ?? [], + ) + ); + } + else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context)!.clientNotRemoved), + backgroundColor: Colors.red, + ) + ); + } + } + + if (data.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.only(top: 0), + itemCount: data.length, + itemBuilder: (context, index) => ListTile( + title: Text(data[index]), + trailing: IconButton( + onPressed: () => { + showDialog( + context: context, + builder: (context) => RemoveDomainModal( + onConfirm: () => confirmRemoveDomain(data[index]), + ) + ) + }, + icon: const Icon(Icons.delete_rounded) + ), + ) + ); + } + else { + return SizedBox( + width: double.maxFinite, + child: Center( + child: Text( + AppLocalizations.of(context)!.noClientsList, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 24, + color: Colors.grey + ), + ), + ), + ); + } + } +} \ No newline at end of file diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 54a81b0..caf68ac 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; +import 'package:adguard_home_manager/screens/clients/blocked_allowed_list.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -105,7 +106,7 @@ class _ClientsWidgetState extends State { tabs: [ Tab( icon: const Icon(Icons.devices), - text: AppLocalizations.of(context)!.clients, + text: AppLocalizations.of(context)!.activeClients, ), Tab( icon: const Icon(Icons.check), @@ -120,24 +121,31 @@ class _ClientsWidgetState extends State { ) ]; }), - body: TabBarView( - children: [ - ClientsList( - data: serversProvider.clients.data!.autoClientsData, - ), - ClientsList( - data: generateClientsList( - serversProvider.clients.data!.autoClientsData, - serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients, + body: Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: Theme.of(context).brightness == Brightness.light + ? const Color.fromRGBO(220, 220, 220, 1) + : const Color.fromRGBO(50, 50, 50, 1) ) - ), - ClientsList( - data: generateClientsList( - serversProvider.clients.data!.autoClientsData, - serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients, - ) - ), - ], + ) + ), + child: TabBarView( + children: [ + ClientsList( + data: serversProvider.clients.data!.autoClientsData, + ), + BlockedAllowedList( + type: 'allowed', + data: serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients, + ), + BlockedAllowedList( + type: 'blocked', + data: serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients, + ), + ], + ), ) ) ); diff --git a/lib/screens/clients/remove_domain_modal.dart b/lib/screens/clients/remove_domain_modal.dart new file mode 100644 index 0000000..31373a5 --- /dev/null +++ b/lib/screens/clients/remove_domain_modal.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +class RemoveDomainModal extends StatelessWidget { + final void Function() onConfirm; + + const RemoveDomainModal({ + Key? key, + required this.onConfirm + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Column( + children: [ + const Icon( + Icons.delete_rounded, + size: 26, + ), + const SizedBox(height: 20), + Text(AppLocalizations.of(context)!.removeClient) + ], + ), + content: Text(AppLocalizations.of(context)!.removeClientMessage), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(AppLocalizations.of(context)!.cancel) + ), + TextButton( + onPressed: () { + onConfirm(); + Navigator.pop(context); + }, + child: Text(AppLocalizations.of(context)!.confirm) + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 1389e7f..fe251be 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -272,4 +272,29 @@ Future getClients(Server server) async { } catch (e) { return {'result': 'error'}; } +} + +Future requestAllowedBlockedClientsHosts(Server server, Map?> body) async { + try { + final result = await postRequest( + urlPath: '/access/set', + server: server, + body: body + ); + + if (result.statusCode == 200) { + return {'result': 'success'}; + } + else { + return {'result': 'error'}; + } + } on SocketException { + return {'result': 'no_connection'}; + } on TimeoutException { + return {'result': 'no_connection'}; + } on HandshakeException { + return {'result': 'ssl_error'}; + } catch (e) { + return {'result': 'error'}; + } } \ No newline at end of file