Added logs config

This commit is contained in:
Juan Gilsanz Polo 2022-10-15 23:08:01 +02:00
parent 2e4872a6c5
commit d56307592e
7 changed files with 403 additions and 161 deletions

View file

@ -401,5 +401,12 @@
"days30": "30 days", "days30": "30 days",
"days90": "90 days", "days90": "90 days",
"retentionTime": "Retention time", "retentionTime": "Retention time",
"selectOneItem": "Select one item" "selectOneItem": "Select one item",
"logSettingsNotLoaded": "Log settings couldn't be loaded.",
"updatingSettings": "Updating settings...",
"logsConfigUpdated": "Logs settings updated successfully",
"logsConfigNotUpdated": "Logs settings couldn't be updated",
"deletingLogs": "Clearing logs...",
"logsCleared": "Logs cleared successfully",
"logsNotCleared": "Logs could not be cleared"
} }

View file

@ -401,5 +401,12 @@
"days30": "30 días", "days30": "30 días",
"days90": "90 días", "days90": "90 días",
"retentionTime": "Tiempo de retención", "retentionTime": "Tiempo de retención",
"selectOneItem": "Selecciona un elemento" "selectOneItem": "Selecciona un elemento",
"logSettingsNotLoaded": "Los ajustes de registros no han podido ser cargados.",
"updatingSettings": "Actualizando ajustes...",
"logsConfigUpdated": "Configuración de registros actualizada correctamente",
"logsConfigNotUpdated": "La configuración de registros no ha podido ser actualizada",
"deletingLogs": "Borrando registros...",
"logsCleared": "Registros borrados correctamente",
"logsNotCleared": "No se han podido borrar los registros"
} }

View file

@ -38,7 +38,7 @@ class Log {
final bool answerDnssec; final bool answerDnssec;
final bool cached; final bool cached;
final String client; final String client;
final ClientInfo clientInfo; final ClientInfo? clientInfo;
final String clientProto; final String clientProto;
final String elapsedMs; final String elapsedMs;
final Question question; final Question question;
@ -56,7 +56,7 @@ class Log {
required this.answerDnssec, required this.answerDnssec,
required this.cached, required this.cached,
required this.client, required this.client,
required this.clientInfo, this.clientInfo,
required this.clientProto, required this.clientProto,
required this.elapsedMs, required this.elapsedMs,
required this.question, required this.question,
@ -75,7 +75,7 @@ class Log {
answerDnssec: json["answer_dnssec"], answerDnssec: json["answer_dnssec"],
cached: json["cached"], cached: json["cached"],
client: json["client"], client: json["client"],
clientInfo: ClientInfo.fromJson(json["client_info"]), clientInfo: json["client_info"] != null ? ClientInfo.fromJson(json["client_info"]) : null,
clientProto: json["client_proto"], clientProto: json["client_proto"],
elapsedMs: json["elapsedMs"], elapsedMs: json["elapsedMs"],
question: Question.fromJson(json["question"]), question: Question.fromJson(json["question"]),
@ -94,7 +94,7 @@ class Log {
"answer_dnssec": answerDnssec, "answer_dnssec": answerDnssec,
"cached": cached, "cached": cached,
"client": client, "client": client,
"client_info": clientInfo.toJson(), "client_info": clientInfo?.toJson(),
"client_proto": clientProto, "client_proto": clientProto,
"elapsedMs": elapsedMs, "elapsedMs": elapsedMs,
"question": question.toJson(), "question": question.toJson(),

View file

@ -173,10 +173,10 @@ class LogDetailsModal extends StatelessWidget {
title: AppLocalizations.of(context)!.deviceIp, title: AppLocalizations.of(context)!.deviceIp,
subtitle: log.client subtitle: log.client
), ),
if (log.clientInfo.name != '') LogListTile( if (log.clientInfo != null && log.clientInfo!.name != '') LogListTile(
icon: Icons.abc_rounded, icon: Icons.abc_rounded,
title: AppLocalizations.of(context)!.deviceName, title: AppLocalizations.of(context)!.deviceName,
subtitle: log.clientInfo.name subtitle: log.clientInfo!.name
), ),
], ],
) )

View file

@ -8,6 +8,8 @@ import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart';
import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart'; import 'package:adguard_home_manager/screens/logs/logs_config_modal.dart';
import 'package:adguard_home_manager/screens/logs/log_tile.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart';
import 'package:adguard_home_manager/functions/snackbar.dart';
import 'package:adguard_home_manager/classes/process_modal.dart';
import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/models/applied_filters.dart';
import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart';
@ -135,8 +137,67 @@ class _LogsWidgetState extends State<LogsWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serversProvider = Provider.of<ServersProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
final logsProvider = Provider.of<LogsProvider>(context); final logsProvider = Provider.of<LogsProvider>(context);
void updateConfig(Map<String, dynamic> data) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.updatingSettings);
final result = await updateQueryLogParameters(server: serversProvider.selectedServer!, data: data);
processModal.close();
if (result['result'] == 'success') {
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.logsConfigUpdated,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.logsConfigNotUpdated,
color: Colors.red
);
}
}
void clearQueries() async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.updatingSettings);
final result = await clearLogs(server: serversProvider.selectedServer!);
processModal.close();
if (result['result'] == 'success') {
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.logsCleared,
color: Colors.green
);
}
else {
appConfigProvider.addLog(result['log']);
showSnacbkar(
context: context,
appConfigProvider: appConfigProvider,
label: AppLocalizations.of(context)!.logsNotCleared,
color: Colors.red
);
}
}
void openFilersModal() { void openFilersModal() {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
@ -269,14 +330,6 @@ class _LogsWidgetState extends State<LogsWidget> {
} }
} }
void updateConfig(Map<String, dynamic> data) async {
}
void clearQueries() async {
}
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(AppLocalizations.of(context)!.logs), title: Text(AppLocalizations.of(context)!.logs),

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.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/app_config_provider.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart';
@ -57,6 +58,26 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
List<Map<String, dynamic>> retentionItems = []; List<Map<String, dynamic>> retentionItems = [];
int loadStatus = 0;
void loadData() async {
final result = await getQueryLogInfo(server: widget.serversProvider.selectedServer!);
if (mounted) {
if (result['result'] == 'success') {
setState(() {
generalSwitch = result['data']['enabled'];
anonymizeClientIp = result['data']['anonymize_client_ip'];
retentionTime = result['data']['interval'].toString();
loadStatus = 1;
});
}
else {
setState(() => loadStatus = 2);
}
}
}
@override @override
void initState() { void initState() {
retentionItems = [ retentionItems = [
@ -82,21 +103,22 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
}, },
]; ];
loadData();
super.initState(); super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container(
height: 450, Widget generateBody() {
decoration: BoxDecoration( switch (loadStatus) {
borderRadius: const BorderRadius.only( case 0:
topLeft: Radius.circular(28), return const Center(
topRight: Radius.circular(28) child: CircularProgressIndicator(),
), );
color: Theme.of(context).dialogBackgroundColor
), case 1:
child: Column( return Column(
children: [ children: [
const Padding( const Padding(
padding: EdgeInsets.only(top: 28), padding: EdgeInsets.only(top: 28),
@ -182,6 +204,7 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
child: Text(item['label']), child: Text(item['label']),
); );
}).toList(), }).toList(),
value: retentionTime,
onChanged: (value) => setState(() => retentionTime = value), onChanged: (value) => setState(() => retentionTime = value),
decoration: InputDecoration( decoration: InputDecoration(
border: const OutlineInputBorder( border: const OutlineInputBorder(
@ -203,7 +226,10 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
TextButton( TextButton(
onPressed: widget.onClear, onPressed: () {
Navigator.pop(context);
widget.onClear();
},
child: Text(AppLocalizations.of(context)!.clearLogs) child: Text(AppLocalizations.of(context)!.clearLogs)
), ),
Row( Row(
@ -215,11 +241,14 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
const SizedBox(width: 20), const SizedBox(width: 20),
TextButton( TextButton(
onPressed: retentionTime != '' onPressed: retentionTime != ''
? () => widget.onConfirm({ ? () {
Navigator.pop(context);
widget.onConfirm({
"enabled": generalSwitch, "enabled": generalSwitch,
"interval": double.parse(retentionTime!), "interval": double.parse(retentionTime!),
"anonymize_client_ip": anonymizeClientIp "anonymize_client_ip": anonymizeClientIp
}) });
}
: null, : null,
child: Text( child: Text(
AppLocalizations.of(context)!.confirm, AppLocalizations.of(context)!.confirm,
@ -239,7 +268,51 @@ class _LogsConfigModalWidgetState extends State<LogsConfigModalWidget> {
), ),
) )
], ],
);
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),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Text(
AppLocalizations.of(context)!.logSettingsNotLoaded,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 22,
color: Colors.grey,
),
),
)
],
),
);
default:
return const SizedBox();
}
}
return Container(
height: 450,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(28),
topRight: Radius.circular(28)
),
color: Theme.of(context).dialogBackgroundColor
),
child: generateBody()
); );
} }
} }

View file

@ -1463,3 +1463,105 @@ Future addDnsRewriteRule({
return result; return result;
} }
} }
Future getQueryLogInfo({
required Server server,
}) async {
final result = await apiRequest(
urlPath: '/querylog_info',
method: 'get',
server: server,
type: 'get_query_log_info'
);
if (result['hasResponse'] == true) {
if (result['statusCode'] == 200) {
return {
'result': 'success',
'data': jsonDecode(result['body'])
};
}
else {
return {
'result': 'error',
'log': AppLog(
type: 'get_query_log_info',
dateTime: DateTime.now(),
message: 'error_code_not_expected',
statusCode: result['statusCode'].toString(),
resBody: result['body'],
)
};
}
}
else {
return result;
}
}
Future updateQueryLogParameters({
required Server server,
required Map<String, dynamic> data,
}) async {
final result = await apiRequest(
urlPath: '/querylog_config',
method: 'post',
server: server,
body: data,
type: 'update_query_log_config'
);
if (result['hasResponse'] == true) {
if (result['statusCode'] == 200) {
return { 'result': 'success' };
}
else {
return {
'result': 'error',
'log': AppLog(
type: 'update_query_log_config',
dateTime: DateTime.now(),
message: 'error_code_not_expected',
statusCode: result['statusCode'].toString(),
resBody: result['body'],
)
};
}
}
else {
return result;
}
}
Future clearLogs({
required Server server,
}) async {
final result = await apiRequest(
urlPath: '/querylog_clear',
method: 'post',
server: server,
body: {},
type: 'clear_query_logs'
);
if (result['hasResponse'] == true) {
if (result['statusCode'] == 200) {
return { 'result': 'success' };
}
else {
return {
'result': 'error',
'log': AppLog(
type: 'clear_query_logs',
dateTime: DateTime.now(),
message: 'error_code_not_expected',
statusCode: result['statusCode'].toString(),
resBody: result['body'],
)
};
}
}
else {
return result;
}
}