mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-05-14 05:52:51 +00:00
Added enable disable protections
This commit is contained in:
parent
3ccdff9e9f
commit
dc229716e0
6 changed files with 370 additions and 56 deletions
|
@ -11,13 +11,13 @@ class ServerStatus {
|
|||
}
|
||||
class ServerStatusData {
|
||||
final DnsStatistics stats;
|
||||
final bool generalEnabled;
|
||||
final bool filteringEnabled;
|
||||
final bool safeSearchEnabled;
|
||||
final bool safeBrowsingEnabled;
|
||||
final bool parentalControlEnabled;
|
||||
bool generalEnabled;
|
||||
bool filteringEnabled;
|
||||
bool safeSearchEnabled;
|
||||
bool safeBrowsingEnabled;
|
||||
bool parentalControlEnabled;
|
||||
|
||||
const ServerStatusData({
|
||||
ServerStatusData({
|
||||
required this.stats,
|
||||
required this.generalEnabled,
|
||||
required this.filteringEnabled,
|
||||
|
|
|
@ -133,6 +133,68 @@ class ServersProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
Future<bool> updateBlocking(Server server, String block, bool newStatus) async {
|
||||
switch (block) {
|
||||
case 'general':
|
||||
final result = await updateGeneralProtection(server, newStatus);
|
||||
if (result['result'] == 'success') {
|
||||
_serverStatus.data!.generalEnabled = newStatus;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
case 'filtering':
|
||||
final result = await updateFiltering(server, newStatus);
|
||||
if (result['result'] == 'success') {
|
||||
_serverStatus.data!.filteringEnabled = newStatus;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
case 'safeSearch':
|
||||
final result = await updateSafeSearch(server, newStatus);
|
||||
if (result['result'] == 'success') {
|
||||
_serverStatus.data!.safeSearchEnabled = newStatus;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
case 'safeBrowsing':
|
||||
final result = await updateSafeBrowsing(server, newStatus);
|
||||
if (result['result'] == 'success') {
|
||||
_serverStatus.data!.safeBrowsingEnabled = newStatus;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
case 'parentalControl':
|
||||
final result = await updateParentalControl(server, newStatus);
|
||||
if (result['result'] == 'success') {
|
||||
_serverStatus.data!.parentalControlEnabled = newStatus;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> saveServerIntoDb(Server server) async {
|
||||
try {
|
||||
return await _dbInstance!.transaction((txn) async {
|
||||
|
|
|
@ -1,16 +1,96 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'package:adguard_home_manager/providers/servers_provider.dart';
|
||||
|
||||
class ManagementModal extends StatelessWidget {
|
||||
class ManagementModal extends StatefulWidget {
|
||||
const ManagementModal({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ManagementModal> createState() => _ManagementModalState();
|
||||
}
|
||||
|
||||
class _ManagementModalState extends State<ManagementModal> {
|
||||
bool disableGeneralSwitch = false;
|
||||
bool disableFiltersSwitch = false;
|
||||
bool disableSafeBrowsingSwitch = false;
|
||||
bool disableParentalControlSwitch = false;
|
||||
bool disableSafeSearchSwitch = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serversProvider = Provider.of<ServersProvider>(context);
|
||||
|
||||
void updateBlocking(bool value, String filter) async {
|
||||
switch (filter) {
|
||||
case 'general':
|
||||
setState(() => disableGeneralSwitch = true);
|
||||
break;
|
||||
|
||||
case 'filtering':
|
||||
setState(() => disableFiltersSwitch = true);
|
||||
break;
|
||||
|
||||
case 'safeBrowsing':
|
||||
setState(() => disableSafeBrowsingSwitch = true);
|
||||
break;
|
||||
|
||||
case 'parentalControl':
|
||||
setState(() => disableParentalControlSwitch = true);
|
||||
break;
|
||||
|
||||
case 'safeSearch':
|
||||
setState(() => disableSafeSearchSwitch = true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
final result = await serversProvider.updateBlocking(
|
||||
serversProvider.selectedServer!,
|
||||
filter,
|
||||
value
|
||||
);
|
||||
|
||||
if (result == false) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.invalidUsernamePassword),
|
||||
backgroundColor: Colors.red,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
switch (filter) {
|
||||
case 'general':
|
||||
setState(() => disableGeneralSwitch = false);
|
||||
break;
|
||||
|
||||
case 'filtering':
|
||||
setState(() => disableFiltersSwitch = false);
|
||||
break;
|
||||
|
||||
case 'safeBrowsing':
|
||||
setState(() => disableSafeBrowsingSwitch = false);
|
||||
break;
|
||||
|
||||
case 'parentalControl':
|
||||
setState(() => disableParentalControlSwitch = false);
|
||||
break;
|
||||
|
||||
case 'safeSearch':
|
||||
setState(() => disableSafeSearchSwitch = false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Widget mainSwitch() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
|
@ -18,7 +98,9 @@ class ManagementModal extends StatelessWidget {
|
|||
color: Theme.of(context).primaryColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
child: InkWell(
|
||||
onTap: () => {},
|
||||
onTap: disableGeneralSwitch == false
|
||||
? () => updateBlocking(!serversProvider.serverStatus.data!.generalEnabled, 'general')
|
||||
: null,
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
@ -36,7 +118,9 @@ class ManagementModal extends StatelessWidget {
|
|||
),
|
||||
Switch(
|
||||
value: serversProvider.serverStatus.data!.generalEnabled,
|
||||
onChanged: (value) => {},
|
||||
onChanged: disableGeneralSwitch == false
|
||||
? (value) => updateBlocking(value, 'general')
|
||||
: null,
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
)
|
||||
],
|
||||
|
@ -47,11 +131,13 @@ class ManagementModal extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Widget smallSwitch(String label, bool value, Function(bool) onChange) {
|
||||
Widget smallSwitch(String label, IconData icon, bool value, Function(bool) onChange, bool disabled) {
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => {},
|
||||
onTap: disabled == false
|
||||
? () => onChange(!value)
|
||||
: null,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 35,
|
||||
|
@ -60,15 +146,26 @@ class ManagementModal extends StatelessWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Switch(
|
||||
value: value,
|
||||
onChanged: onChange,
|
||||
onChanged: disabled == false
|
||||
? onChange
|
||||
: null,
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
)
|
||||
],
|
||||
|
@ -95,7 +192,7 @@ class ManagementModal extends StatelessWidget {
|
|||
const Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Icon(
|
||||
Icons.shield,
|
||||
Icons.shield_rounded,
|
||||
size: 26,
|
||||
),
|
||||
),
|
||||
|
@ -112,23 +209,31 @@ class ManagementModal extends StatelessWidget {
|
|||
const SizedBox(height: 10),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.ruleFiltering,
|
||||
false,
|
||||
(p0) => null
|
||||
Icons.filter_list_rounded,
|
||||
serversProvider.serverStatus.data!.filteringEnabled,
|
||||
(value) => updateBlocking(value, 'filtering'),
|
||||
disableFiltersSwitch
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.safeBrowsing,
|
||||
false,
|
||||
(p0) => null
|
||||
Icons.vpn_lock_rounded,
|
||||
serversProvider.serverStatus.data!.safeBrowsingEnabled,
|
||||
(value) => updateBlocking(value, 'safeBrowsing'),
|
||||
disableSafeBrowsingSwitch
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.parentalFiltering,
|
||||
false,
|
||||
(p0) => null
|
||||
Icons.block,
|
||||
serversProvider.serverStatus.data!.parentalControlEnabled,
|
||||
(value) => updateBlocking(value, 'parentalControl'),
|
||||
disableParentalControlSwitch
|
||||
),
|
||||
smallSwitch(
|
||||
AppLocalizations.of(context)!.safeSearch,
|
||||
false,
|
||||
(p0) => null
|
||||
Icons.search_rounded,
|
||||
serversProvider.serverStatus.data!.safeSearchEnabled,
|
||||
(value) => updateBlocking(value, 'safeSearch'),
|
||||
disableSafeSearchSwitch
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -14,10 +14,12 @@ class StatusBox extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
return AnimatedContainer(
|
||||
padding: const EdgeInsets.all(12),
|
||||
width: double.maxFinite,
|
||||
height: double.maxFinite,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeInOut,
|
||||
decoration: BoxDecoration(
|
||||
color: isEnabled == true
|
||||
? Colors.green
|
||||
|
|
|
@ -11,29 +11,35 @@ class TopItems extends StatelessWidget {
|
|||
required this.data,
|
||||
}) : super(key: key);
|
||||
|
||||
Widget rowItem(Map<String, dynamic> item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 8
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.keys.toList()[0],
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500
|
||||
),
|
||||
),
|
||||
Text(item.values.toList()[0].toString())
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
|
||||
Widget rowItem(Map<String, dynamic> item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 8
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: width-100,
|
||||
child: Text(
|
||||
item.keys.toList()[0],
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(item.values.toList()[0].toString())
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return SizedBox(
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
|
@ -7,10 +7,12 @@ import 'dart:io';
|
|||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'package:adguard_home_manager/models/server_status.dart';
|
||||
import 'package:adguard_home_manager/models/dns_statistics.dart';
|
||||
import 'package:adguard_home_manager/models/server.dart';
|
||||
|
||||
Future<http.Response> getRequest(String urlPath, Server server) {
|
||||
Future<http.Response> getRequest({
|
||||
required String urlPath,
|
||||
required Server server
|
||||
}) {
|
||||
return http.get(
|
||||
Uri.parse("${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}/control$urlPath"),
|
||||
headers: {
|
||||
|
@ -19,6 +21,20 @@ Future<http.Response> getRequest(String urlPath, Server server) {
|
|||
);
|
||||
}
|
||||
|
||||
Future<http.Response> postRequest({
|
||||
required String urlPath,
|
||||
required Server server,
|
||||
Map<String, dynamic>? body
|
||||
}) {
|
||||
return http.post(
|
||||
Uri.parse("${server.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}/control$urlPath"),
|
||||
headers: {
|
||||
'Authorization': 'Basic ${server.authToken}'
|
||||
},
|
||||
body: jsonEncode(body)
|
||||
);
|
||||
}
|
||||
|
||||
Future login(Server server) async {
|
||||
try {
|
||||
final result = await http.post(
|
||||
|
@ -60,12 +76,12 @@ Future login(Server server) async {
|
|||
Future getServerStatus(Server server) async {
|
||||
try {
|
||||
final result = await Future.wait([
|
||||
getRequest('/stats', server),
|
||||
getRequest('/status', server),
|
||||
getRequest('/filtering/status', server),
|
||||
getRequest('/safesearch/status', server),
|
||||
getRequest('/safebrowsing/status', server),
|
||||
getRequest('/parental/status', server),
|
||||
getRequest(urlPath: '/stats', server: server),
|
||||
getRequest(urlPath: '/status', server: server),
|
||||
getRequest(urlPath: '/filtering/status', server: server),
|
||||
getRequest(urlPath: '/safesearch/status', server: server),
|
||||
getRequest(urlPath: '/safebrowsing/status', server: server),
|
||||
getRequest(urlPath: '/parental/status', server: server),
|
||||
]);
|
||||
|
||||
if (
|
||||
|
@ -102,4 +118,127 @@ Future getServerStatus(Server server) async {
|
|||
} catch (e) {
|
||||
return {'result': 'error'};
|
||||
}
|
||||
}
|
||||
|
||||
Future updateFiltering(Server server, bool enable) async {
|
||||
try {
|
||||
final result = await postRequest(
|
||||
urlPath: '/filtering/config',
|
||||
server: server,
|
||||
body: {
|
||||
'enabled': enable
|
||||
}
|
||||
);
|
||||
|
||||
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'};
|
||||
}
|
||||
}
|
||||
|
||||
Future updateSafeSearch(Server server, bool enable) async {
|
||||
try {
|
||||
final result = enable == true
|
||||
? await postRequest(urlPath: '/safesearch/enable', server: server)
|
||||
: await postRequest(urlPath: '/safesearch/disable', server: server);
|
||||
|
||||
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'};
|
||||
}
|
||||
}
|
||||
|
||||
Future updateSafeBrowsing(Server server, bool enable) async {
|
||||
try {
|
||||
final result = enable == true
|
||||
? await postRequest(urlPath: '/safebrowsing/enable', server: server)
|
||||
: await postRequest(urlPath: '/safebrowsing/disable', server: server);
|
||||
|
||||
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'};
|
||||
}
|
||||
}
|
||||
|
||||
Future updateParentalControl(Server server, bool enable) async {
|
||||
try {
|
||||
final result = enable == true
|
||||
? await postRequest(urlPath: '/parental/enable', server: server)
|
||||
: await postRequest(urlPath: '/parental/disable', server: server);
|
||||
|
||||
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'};
|
||||
}
|
||||
}
|
||||
|
||||
Future updateGeneralProtection(Server server, bool enable) async {
|
||||
try {
|
||||
final result = await postRequest(
|
||||
urlPath: '/dns_config',
|
||||
server: server,
|
||||
body: {
|
||||
'protection_enabled': enable
|
||||
}
|
||||
);
|
||||
|
||||
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'};
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue