mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-04-24 07:46:06 +00:00
Added auth token to server modal and dns statistics request
This commit is contained in:
parent
360b6865be
commit
97e4fea015
9 changed files with 171 additions and 15 deletions
7
lib/functions/encode_base64.dart
Normal file
7
lib/functions/encode_base64.dart
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
String encodeBase64UserPass(String user, String pass) {
|
||||||
|
String credentials = "$user:$pass";
|
||||||
|
Codec<String, String> stringToBase64 = utf8.fuse(base64);
|
||||||
|
return stringToBase64.encode(credentials);
|
||||||
|
}
|
73
lib/models/dns_statistics.dart
Normal file
73
lib/models/dns_statistics.dart
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
DnsStatistics dnsStatisticsFromJson(String str) => DnsStatistics.fromJson(json.decode(str));
|
||||||
|
|
||||||
|
String dnsStatisticsToJson(DnsStatistics data) => json.encode(data.toJson());
|
||||||
|
|
||||||
|
class DnsStatistics {
|
||||||
|
final String timeUnits;
|
||||||
|
final List<Map<String, int>> topQueriedDomains;
|
||||||
|
final List<Map<String, int>> topClients;
|
||||||
|
final List<Map<String, int>> topBlockedDomains;
|
||||||
|
final List<int> dnsQueries;
|
||||||
|
final List<int> blockedFiltering;
|
||||||
|
final List<int> replacedSafebrowsing;
|
||||||
|
final List<int> replacedParental;
|
||||||
|
final int numDnsQueries;
|
||||||
|
final int numBlockedFiltering;
|
||||||
|
final int numReplacedSafebrowsing;
|
||||||
|
final int numReplacedSafesearch;
|
||||||
|
final int numReplacedParental;
|
||||||
|
final double avgProcessingTime;
|
||||||
|
|
||||||
|
DnsStatistics({
|
||||||
|
required this.timeUnits,
|
||||||
|
required this.topQueriedDomains,
|
||||||
|
required this.topClients,
|
||||||
|
required this.topBlockedDomains,
|
||||||
|
required this.dnsQueries,
|
||||||
|
required this.blockedFiltering,
|
||||||
|
required this.replacedSafebrowsing,
|
||||||
|
required this.replacedParental,
|
||||||
|
required this.numDnsQueries,
|
||||||
|
required this.numBlockedFiltering,
|
||||||
|
required this.numReplacedSafebrowsing,
|
||||||
|
required this.numReplacedSafesearch,
|
||||||
|
required this.numReplacedParental,
|
||||||
|
required this.avgProcessingTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory DnsStatistics.fromJson(Map<String, dynamic> json) => DnsStatistics(
|
||||||
|
timeUnits: json["time_units"],
|
||||||
|
topQueriedDomains: List<Map<String, int>>.from(json["top_queried_domains"].map((x) => Map.from(x).map((k, v) => MapEntry<String, int>(k, v)))),
|
||||||
|
topClients: List<Map<String, int>>.from(json["top_clients"].map((x) => Map.from(x).map((k, v) => MapEntry<String, int>(k, v)))),
|
||||||
|
topBlockedDomains: List<Map<String, int>>.from(json["top_blocked_domains"].map((x) => Map.from(x).map((k, v) => MapEntry<String, int>(k, v)))),
|
||||||
|
dnsQueries: List<int>.from(json["dns_queries"].map((x) => x)),
|
||||||
|
blockedFiltering: List<int>.from(json["blocked_filtering"].map((x) => x)),
|
||||||
|
replacedSafebrowsing: List<int>.from(json["replaced_safebrowsing"].map((x) => x)),
|
||||||
|
replacedParental: List<int>.from(json["replaced_parental"].map((x) => x)),
|
||||||
|
numDnsQueries: json["num_dns_queries"],
|
||||||
|
numBlockedFiltering: json["num_blocked_filtering"],
|
||||||
|
numReplacedSafebrowsing: json["num_replaced_safebrowsing"],
|
||||||
|
numReplacedSafesearch: json["num_replaced_safesearch"],
|
||||||
|
numReplacedParental: json["num_replaced_parental"],
|
||||||
|
avgProcessingTime: json["avg_processing_time"].toDouble(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"time_units": timeUnits,
|
||||||
|
"top_queried_domains": List<dynamic>.from(topQueriedDomains.map((x) => Map.from(x).map((k, v) => MapEntry<String, dynamic>(k, v)))),
|
||||||
|
"top_clients": List<dynamic>.from(topClients.map((x) => Map.from(x).map((k, v) => MapEntry<String, dynamic>(k, v)))),
|
||||||
|
"top_blocked_domains": List<dynamic>.from(topBlockedDomains.map((x) => Map.from(x).map((k, v) => MapEntry<String, dynamic>(k, v)))),
|
||||||
|
"dns_queries": List<dynamic>.from(dnsQueries.map((x) => x)),
|
||||||
|
"blocked_filtering": List<dynamic>.from(blockedFiltering.map((x) => x)),
|
||||||
|
"replaced_safebrowsing": List<dynamic>.from(replacedSafebrowsing.map((x) => x)),
|
||||||
|
"replaced_parental": List<dynamic>.from(replacedParental.map((x) => x)),
|
||||||
|
"num_dns_queries": numDnsQueries,
|
||||||
|
"num_blocked_filtering": numBlockedFiltering,
|
||||||
|
"num_replaced_safebrowsing": numReplacedSafebrowsing,
|
||||||
|
"num_replaced_safesearch": numReplacedSafesearch,
|
||||||
|
"num_replaced_parental": numReplacedParental,
|
||||||
|
"avg_processing_time": avgProcessingTime,
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ class Server {
|
||||||
String user;
|
String user;
|
||||||
String password;
|
String password;
|
||||||
bool defaultServer;
|
bool defaultServer;
|
||||||
|
String authToken;
|
||||||
|
|
||||||
Server({
|
Server({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
@ -18,6 +19,7 @@ class Server {
|
||||||
this.port,
|
this.port,
|
||||||
required this.user,
|
required this.user,
|
||||||
required this.password,
|
required this.password,
|
||||||
required this.defaultServer
|
required this.defaultServer,
|
||||||
|
required this.authToken
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:adguard_home_manager/models/dns_statistics.dart';
|
||||||
|
import 'package:adguard_home_manager/services/http_requests.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sqflite/sqflite.dart';
|
import 'package:sqflite/sqflite.dart';
|
||||||
|
|
||||||
|
@ -10,6 +12,7 @@ class ServersProvider with ChangeNotifier {
|
||||||
List<Server> _serversList = [];
|
List<Server> _serversList = [];
|
||||||
Server? _selectedServer;
|
Server? _selectedServer;
|
||||||
bool? _isServerConnected;
|
bool? _isServerConnected;
|
||||||
|
DnsStatistics? _dnsStatistics;
|
||||||
|
|
||||||
List<Server> get serversList {
|
List<Server> get serversList {
|
||||||
return _serversList;
|
return _serversList;
|
||||||
|
@ -23,6 +26,10 @@ class ServersProvider with ChangeNotifier {
|
||||||
return _isServerConnected;
|
return _isServerConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DnsStatistics? get dnsStatistics {
|
||||||
|
return _dnsStatistics;
|
||||||
|
}
|
||||||
|
|
||||||
void setDbInstance(Database db) {
|
void setDbInstance(Database db) {
|
||||||
_dbInstance = db;
|
_dbInstance = db;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +49,11 @@ class ServersProvider with ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setDnsStatistics(DnsStatistics data) {
|
||||||
|
_dnsStatistics = data;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> createServer(Server server) async {
|
Future<bool> createServer(Server server) async {
|
||||||
final saved = await saveServerIntoDb(server);
|
final saved = await saveServerIntoDb(server);
|
||||||
if (saved == true) {
|
if (saved == true) {
|
||||||
|
@ -127,7 +139,7 @@ class ServersProvider with ChangeNotifier {
|
||||||
try {
|
try {
|
||||||
return await _dbInstance!.transaction((txn) async {
|
return await _dbInstance!.transaction((txn) async {
|
||||||
await txn.rawInsert(
|
await txn.rawInsert(
|
||||||
'INSERT INTO servers (id, name, connectionMethod, domain, path, port, user, password, defaultServer) VALUES ("${server.id}", "${server.name}", "${server.connectionMethod}", "${server.domain}", ${server.path != null ? "${server.path}" : null}, ${server.port}, "${server.user}", "${server.password}", 0)',
|
'INSERT INTO servers (id, name, connectionMethod, domain, path, port, user, password, defaultServer, authToken) VALUES ("${server.id}", "${server.name}", "${server.connectionMethod}", "${server.domain}", ${server.path != null ? "${server.path}" : null}, ${server.port}, "${server.user}", "${server.password}", 0, "${server.authToken}")',
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -140,7 +152,7 @@ class ServersProvider with ChangeNotifier {
|
||||||
try {
|
try {
|
||||||
return await _dbInstance!.transaction((txn) async {
|
return await _dbInstance!.transaction((txn) async {
|
||||||
await txn.rawUpdate(
|
await txn.rawUpdate(
|
||||||
'UPDATE servers SET name = "${server.name}", connectionMethod = "${server.connectionMethod}", domain = "${server.domain}", path = ${server.path != null ? "${server.path}" : null}, port = ${server.port}, user = "${server.user}", password = "${server.password}" WHERE id = "${server.id}"',
|
'UPDATE servers SET name = "${server.name}", connectionMethod = "${server.connectionMethod}", domain = "${server.domain}", path = ${server.path != null ? "${server.path}" : null}, port = ${server.port}, user = "${server.user}", password = "${server.password}", authToken = "${server.authToken}" WHERE id = "${server.id}"',
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -191,10 +203,19 @@ class ServersProvider with ChangeNotifier {
|
||||||
user: server['user'],
|
user: server['user'],
|
||||||
password: server['password'],
|
password: server['password'],
|
||||||
defaultServer: convertFromIntToBool(server['defaultServer'])!,
|
defaultServer: convertFromIntToBool(server['defaultServer'])!,
|
||||||
|
authToken: server['authToken']
|
||||||
);
|
);
|
||||||
_serversList.add(serverObj);
|
_serversList.add(serverObj);
|
||||||
if (convertFromIntToBool(server['defaultServer']) == true) {
|
if (convertFromIntToBool(server['defaultServer']) == true) {
|
||||||
_selectedServer = serverObj;
|
_selectedServer = serverObj;
|
||||||
|
final dnsStatistics = await getDnsStatistics(serverObj);
|
||||||
|
if (dnsStatistics['result'] == 'success') {
|
||||||
|
_dnsStatistics = dnsStatistics['data'];
|
||||||
|
_isServerConnected = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_isServerConnected = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||||
|
|
||||||
class Home extends StatelessWidget {
|
class Home extends StatelessWidget {
|
||||||
const Home({Key? key}) : super(key: key);
|
const Home({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final serversProvider = Provider.of<ServersProvider>(context);
|
||||||
|
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ Future<Map<String, dynamic>> loadDb() async {
|
||||||
'adguard_home_manager.db',
|
'adguard_home_manager.db',
|
||||||
version: 1,
|
version: 1,
|
||||||
onCreate: (Database db, int version) async {
|
onCreate: (Database db, int version) async {
|
||||||
await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER)");
|
await db.execute("CREATE TABLE servers (id TEXT PRIMARY KEY, name TEXT, connectionMethod TEXT, domain TEXT, path TEXT, port INTEGER, user TEXT, password TEXT, defaultServer INTEGER, authToken TEXT)");
|
||||||
},
|
},
|
||||||
onUpgrade: (Database db, int oldVersion, int newVersion) async {
|
onUpgrade: (Database db, int oldVersion, int newVersion) async {
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/models/dns_statistics.dart';
|
||||||
import 'package:adguard_home_manager/models/server.dart';
|
import 'package:adguard_home_manager/models/server.dart';
|
||||||
|
|
||||||
Future login(Server server) async {
|
Future login(Server server) async {
|
||||||
|
@ -45,3 +46,31 @@ Future login(Server server) async {
|
||||||
return {'result': 'error'};
|
return {'result': 'error'};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future getDnsStatistics(Server server) async {
|
||||||
|
try {
|
||||||
|
final result = await http.get(
|
||||||
|
Uri.parse("${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}/control/stats"),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Basic ${server.authToken}'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (result.statusCode == 200) {
|
||||||
|
return {
|
||||||
|
'result': 'success',
|
||||||
|
'data': DnsStatistics.fromJson(jsonDecode(result.body))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
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'};
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'package:adguard_home_manager/functions/encode_base64.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
@ -206,7 +207,7 @@ class _AddServerModalState extends State<AddServerModal> {
|
||||||
final mediaQuery = MediaQuery.of(context);
|
final mediaQuery = MediaQuery.of(context);
|
||||||
|
|
||||||
void connect() async {
|
void connect() async {
|
||||||
final Server serverObj = Server(
|
Server serverObj = Server(
|
||||||
id: uuid.v4(),
|
id: uuid.v4(),
|
||||||
name: nameController.text,
|
name: nameController.text,
|
||||||
connectionMethod: connectionType,
|
connectionMethod: connectionType,
|
||||||
|
@ -214,14 +215,24 @@ class _AddServerModalState extends State<AddServerModal> {
|
||||||
port: int.parse(portController.text),
|
port: int.parse(portController.text),
|
||||||
user: userController.text,
|
user: userController.text,
|
||||||
password: passwordController.text,
|
password: passwordController.text,
|
||||||
defaultServer: defaultServer
|
defaultServer: defaultServer,
|
||||||
|
authToken: ''
|
||||||
);
|
);
|
||||||
setState(() => isConnecting = true);
|
setState(() => isConnecting = true);
|
||||||
final result = await login(serverObj);
|
final result = await login(serverObj);
|
||||||
setState(() => isConnecting = false);
|
setState(() => isConnecting = false);
|
||||||
if (result['result'] == 'success') {
|
if (result['result'] == 'success') {
|
||||||
|
serverObj.authToken = encodeBase64UserPass(serverObj.user, serverObj.password);
|
||||||
final serverCreated = await serversProvider.createServer(serverObj);
|
final serverCreated = await serversProvider.createServer(serverObj);
|
||||||
if (serverCreated == true) {
|
if (serverCreated == true) {
|
||||||
|
final dnsStatistics = await getDnsStatistics(serverObj);
|
||||||
|
if (dnsStatistics['result'] == 'success') {
|
||||||
|
serversProvider.setDnsStatistics(dnsStatistics['data']);
|
||||||
|
serversProvider.setIsServerConnected(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
serversProvider.setIsServerConnected(false);
|
||||||
|
}
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -284,10 +295,12 @@ class _AddServerModalState extends State<AddServerModal> {
|
||||||
port: int.parse(portController.text),
|
port: int.parse(portController.text),
|
||||||
user: userController.text,
|
user: userController.text,
|
||||||
password: passwordController.text,
|
password: passwordController.text,
|
||||||
defaultServer: defaultServer
|
defaultServer: defaultServer,
|
||||||
|
authToken: ''
|
||||||
);
|
);
|
||||||
final result = await login(serverObj);
|
final result = await login(serverObj);
|
||||||
if (result['result'] == 'success') {
|
if (result['result'] == 'success') {
|
||||||
|
serverObj.authToken = encodeBase64UserPass(serverObj.user, serverObj.password);
|
||||||
final serverSaved = await serversProvider.editServer(serverObj);
|
final serverSaved = await serversProvider.editServer(serverObj);
|
||||||
if (serverSaved == true) {
|
if (serverSaved == true) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
import 'package:adguard_home_manager/widgets/add_server_modal.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:expandable/expandable.dart';
|
import 'package:expandable/expandable.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/widgets/servers_list/delete_modal.dart';
|
import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart';
|
||||||
|
import 'package:adguard_home_manager/widgets/add_server_modal.dart';
|
||||||
|
|
||||||
import 'package:adguard_home_manager/classes/process_modal.dart';
|
import 'package:adguard_home_manager/classes/process_modal.dart';
|
||||||
import 'package:adguard_home_manager/models/server.dart';
|
import 'package:adguard_home_manager/models/server.dart';
|
||||||
|
@ -54,21 +54,27 @@ class ServersList extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
void connectToServer(Server server) async {
|
void connectToServer(Server server) async {
|
||||||
Future connectSuccess(result) async {
|
|
||||||
serversProvider.setSelectedServer(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ProcessModal process = ProcessModal(context: context);
|
final ProcessModal process = ProcessModal(context: context);
|
||||||
process.open(AppLocalizations.of(context)!.connecting);
|
process.open(AppLocalizations.of(context)!.connecting);
|
||||||
|
|
||||||
final result = await login(server);
|
final result = await login(server);
|
||||||
|
|
||||||
process.close();
|
|
||||||
|
|
||||||
if (result['result'] == 'success') {
|
if (result['result'] == 'success') {
|
||||||
await connectSuccess(result);
|
serversProvider.setSelectedServer(server);
|
||||||
|
|
||||||
|
final dnsStatistics = await getDnsStatistics(server);
|
||||||
|
if (dnsStatistics['result'] == 'success') {
|
||||||
|
serversProvider.setDnsStatistics(dnsStatistics['data']);
|
||||||
|
serversProvider.setIsServerConnected(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
serversProvider.setIsServerConnected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
process.close();
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(AppLocalizations.of(context)!.cannotConnect),
|
content: Text(AppLocalizations.of(context)!.cannotConnect),
|
||||||
|
|
Loading…
Add table
Reference in a new issue