diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index bf92857..755149f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -378,5 +378,11 @@ "leasesRestored": "Leases restored successfully", "leasesNotRestored": "The leases couldn't be restored", "dhcpLeases": "DHCP leases", - "noLeases": "No DHCP leases available" + "noLeases": "No DHCP leases available", + "dnsRewrites": "DNS rewrites", + "dnsRewritesDescription": "Configure custom DNS rules", + "loadingRewriteRules": "Loading rewrite rules...", + "rewriteRulesNotLoaded": "DNS rewrite rules could not be loaded.", + "noRewriteRules": "No DNS rewrite rules", + "answer": "Answer" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 9d6f6df..3067e32 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -378,5 +378,11 @@ "leasesRestored": "Asignaciones restauradas correctamente", "leasesNotRestored": "Las asignaciones no pudieron ser restauradas", "dhcpLeases": "Asignaciones DHCP", - "noLeases": "No hay asignaciones DHCP disponibles" + "noLeases": "No hay asignaciones DHCP disponibles", + "dnsRewrites": "Reescrituras DNS", + "dnsRewritesDescription": "Configurar reglas DNS personalizadas", + "loadingRewriteRules": "Cargando reescrituras DNS...", + "rewriteRulesNotLoaded": "No se han podido cargar las reescrituras DNS.", + "noRewriteRules": "No hay reescrituras DNS.", + "answer": "Respuesta" } \ No newline at end of file diff --git a/lib/models/rewrite_rules.dart b/lib/models/rewrite_rules.dart new file mode 100644 index 0000000..44bef8d --- /dev/null +++ b/lib/models/rewrite_rules.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +class RewriteRules { + int loadStatus = 0; + List? data; + + RewriteRules({ + required this.loadStatus, + this.data + }); +} + +List rewriteRulesDataFromJson(String str) => List.from(json.decode(str).map((x) => RewriteRulesData.fromJson(x))); + +String rewriteRulesDataToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); + +class RewriteRulesData { + final String domain; + final String answer; + + RewriteRulesData({ + required this.domain, + required this.answer, + }); + + factory RewriteRulesData.fromJson(Map json) => RewriteRulesData( + domain: json["domain"], + answer: json["answer"], + ); + + Map toJson() => { + "domain": domain, + "answer": answer, + }; +} diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 26fa5ea..23f0af4 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -3,6 +3,7 @@ import 'package:sqflite/sqflite.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/models/dhcp.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/clients.dart'; @@ -37,6 +38,11 @@ class ServersProvider with ChangeNotifier { data: null ); + final RewriteRules _rewriteRules = RewriteRules( + loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error + data: null + ); + FilteringStatus? _filteringStatus; List get serversList { @@ -71,6 +77,10 @@ class ServersProvider with ChangeNotifier { return _dhcp; } + RewriteRules get rewriteRules { + return _rewriteRules; + } + void setDbInstance(Database db) { _dbInstance = db; } @@ -156,6 +166,18 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } } + + void setRewriteRulesData(List data) { + _rewriteRules.data = data; + notifyListeners(); + } + + void setRewriteRulesLoadStatus(int status, bool notify) { + _rewriteRules.loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } Future createServer(Server server) async { final saved = await saveServerIntoDb(server); diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart new file mode 100644 index 0000000..203c604 --- /dev/null +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -0,0 +1,192 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.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 DnsRewrites extends StatelessWidget { + const DnsRewrites({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + + return DnsRewritesWidget( + serversProvider: serversProvider, + appConfigProvider: appConfigProvider, + ); + } +} + +class DnsRewritesWidget extends StatefulWidget { + final ServersProvider serversProvider; + final AppConfigProvider appConfigProvider; + + const DnsRewritesWidget({ + Key? key, + required this.serversProvider, + required this.appConfigProvider + }) : super(key: key); + + @override + State createState() => _DnsRewritesWidgetState(); +} + +class _DnsRewritesWidgetState extends State { + void fetchData() async { + widget.serversProvider.setRewriteRulesLoadStatus(0, false); + + final result = await getDnsRewriteRules(server: widget.serversProvider.selectedServer!); + + if (result['result'] == 'success') { + widget.serversProvider.setRewriteRulesData(result['data']); + widget.serversProvider.setRewriteRulesLoadStatus(1, true); + } + else { + widget.appConfigProvider.addLog(result['log']); + widget.serversProvider.setRewriteRulesLoadStatus(2, true); + } + } + + @override + void initState() { + fetchData(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final serversProvider = Provider.of(context); + + Widget generateBody() { + switch (serversProvider.rewriteRules.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)!.loadingRewriteRules, + style: const TextStyle( + fontSize: 22, + color: Colors.grey, + ), + ) + ], + ), + ); + + case 1: + if (serversProvider.rewriteRules.data!.isNotEmpty) { + return ListView.builder( + padding: const EdgeInsets.only(top: 0), + itemCount: serversProvider.rewriteRules.data!.length, + itemBuilder: (context, index) => Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade200 + ) + ) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.domain}: ", + style: const TextStyle( + fontWeight: FontWeight.w500 + ), + ), + Text( + serversProvider.rewriteRules.data![index].domain, + ), + ], + ), + const SizedBox(height: 3), + Row( + children: [ + Text( + "${AppLocalizations.of(context)!.answer}: ", + style: const TextStyle( + fontWeight: FontWeight.w500 + ), + ), + Text( + serversProvider.rewriteRules.data![index].answer, + ), + ], + ), + ], + ), + IconButton( + onPressed: () => {}, + icon: const Icon(Icons.delete) + ) + ], + ), + ) + ); + } + else { + return Center( + child: Text( + AppLocalizations.of(context)!.noRewriteRules, + style: const TextStyle( + fontSize: 22, + color: Colors.grey, + ), + ), + ); + } + + 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)!.rewriteRulesNotLoaded, + style: const TextStyle( + fontSize: 22, + color: Colors.grey, + ), + ) + ], + ), + ); + + default: + return const SizedBox(); + } + } + + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context)!.dnsRewrites), + ), + body: generateBody(), + ); + } +} \ No newline at end of file diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 2a6e916..e1ce544 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -10,6 +10,7 @@ import 'package:adguard_home_manager/screens/settings/server_info/server_info.da 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'; +import 'package:adguard_home_manager/screens/settings/dns_rewrites/dns_rewrites.dart'; import 'package:adguard_home_manager/screens/settings/appbar.dart'; import 'package:adguard_home_manager/screens/servers/servers.dart'; import 'package:adguard_home_manager/screens/settings/advanced_setings.dart'; @@ -112,6 +113,18 @@ class Settings extends StatelessWidget { ) }, ), + CustomListTile( + leadingIcon: Icons.route_rounded, + label: AppLocalizations.of(context)!.dnsRewrites, + description: AppLocalizations.of(context)!.dnsRewritesDescription, + onTap: () => { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const DnsRewrites() + ) + ) + }, + ), CustomListTile( leadingIcon: Icons.info_rounded, label: AppLocalizations.of(context)!.serverInformation, diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 4a4b3c4..7148975 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -9,6 +9,7 @@ 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'; import 'package:adguard_home_manager/models/app_log.dart'; +import 'package:adguard_home_manager/models/rewrite_rules.dart'; import 'package:adguard_home_manager/models/server_info.dart'; import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/clients.dart'; @@ -1354,4 +1355,43 @@ Future restoreAllLeases({ else { return result; } +} + +Future getDnsRewriteRules({ + required Server server, +}) async { + final result = await apiRequest( + urlPath: '/rewrite/list', + method: 'get', + server: server, + type: 'get_dns_rewrite_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + final List data = List.from( + jsonDecode(result['body']).map((item) => RewriteRulesData.fromJson(item)) + ); + + return { + 'result': 'success', + 'data': data + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dns_rewrite_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } \ No newline at end of file