mirror of
https://github.com/JGeek00/adguard-home-manager.git
synced 2025-05-04 20:30:35 +00:00
Added ipv4 and ipv6 subnet prefix length fields
This commit is contained in:
parent
5f448f0af0
commit
8df0781da6
5 changed files with 148 additions and 88 deletions
|
@ -758,5 +758,7 @@
|
|||
"invalidTime": "Invalid time",
|
||||
"removeDomain": "Remove domain",
|
||||
"addDomain": "Add domain",
|
||||
"notLess1Hour": "Time cannot be less than 1 hour"
|
||||
"notLess1Hour": "Time cannot be less than 1 hour",
|
||||
"subnetPrefixLengthIpv4": "Subnet prefix length for IPv4",
|
||||
"subnetPrefixLengthIpv6": "Subnet prefix length for IPv6"
|
||||
}
|
|
@ -758,5 +758,7 @@
|
|||
"invalidTime": "Tiempo no válido",
|
||||
"removeDomain": "Eliminar dominio",
|
||||
"addDomain": "Añadir dominio",
|
||||
"notLess1Hour": "El tiempo no puede ser inferior a 1 hora"
|
||||
"notLess1Hour": "El tiempo no puede ser inferior a 1 hora",
|
||||
"subnetPrefixLengthIpv4": "Longitud del prefijo de subred para IPv4",
|
||||
"subnetPrefixLengthIpv6": "Longitud del prefijo de subred para IPv6"
|
||||
}
|
|
@ -23,6 +23,8 @@ class DnsInfo {
|
|||
String blockingIpv6;
|
||||
List<String> defaultLocalPtrUpstreams;
|
||||
int? blockedResponseTtl;
|
||||
int? ratelimitSubnetLenIpv4;
|
||||
int? ratelimitSubnetLenIpv6;
|
||||
|
||||
DnsInfo({
|
||||
required this.upstreamDns,
|
||||
|
@ -49,6 +51,8 @@ class DnsInfo {
|
|||
required this.blockingIpv6,
|
||||
required this.defaultLocalPtrUpstreams,
|
||||
required this.blockedResponseTtl,
|
||||
required this.ratelimitSubnetLenIpv4,
|
||||
required this.ratelimitSubnetLenIpv6,
|
||||
});
|
||||
|
||||
factory DnsInfo.fromJson(Map<String, dynamic> json) => DnsInfo(
|
||||
|
@ -75,7 +79,9 @@ class DnsInfo {
|
|||
blockingIpv4: json["blocking_ipv4"],
|
||||
blockingIpv6: json["blocking_ipv6"],
|
||||
defaultLocalPtrUpstreams: json["default_local_ptr_upstreams"] != null ? List<String>.from(json["default_local_ptr_upstreams"].map((x) => x)) : [],
|
||||
blockedResponseTtl: json["blocked_response_ttl"]
|
||||
blockedResponseTtl: json["blocked_response_ttl"],
|
||||
ratelimitSubnetLenIpv4: json["ratelimit_subnet_len_ipv4"],
|
||||
ratelimitSubnetLenIpv6: json["ratelimit_subnet_len_ipv6"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
@ -102,6 +108,8 @@ class DnsInfo {
|
|||
"blocking_ipv4": blockingIpv4,
|
||||
"blocking_ipv6": blockingIpv6,
|
||||
"default_local_ptr_upstreams": List<dynamic>.from(defaultLocalPtrUpstreams.map((x) => x)),
|
||||
"blocked_response_ttl": blockedResponseTtl
|
||||
"blocked_response_ttl": blockedResponseTtl,
|
||||
"ratelimit_subnet_len_ipv4": ratelimitSubnetLenIpv4,
|
||||
"ratelimit_subnet_len_ipv6": ratelimitSubnetLenIpv6,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -162,6 +162,8 @@ class DnsProvider with ChangeNotifier {
|
|||
data.blockingIpv4 = value['blocking_ipv4'];
|
||||
data.blockingIpv6 = value['blocking_ipv6'];
|
||||
data.blockedResponseTtl = value['blocked_response_ttl'];
|
||||
data.ratelimitSubnetLenIpv4 = value['ratelimit_subnet_len_ipv4'];
|
||||
data.ratelimitSubnetLenIpv6 = value['ratelimit_subnet_len_ipv6'];
|
||||
setDnsInfoData(data);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -23,49 +23,49 @@ class DnsServerSettingsScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
||||
final TextEditingController limitRequestsController = TextEditingController();
|
||||
String? limitRequestsError;
|
||||
final _limitRequestsController = TextEditingController();
|
||||
final _ipv4PrefixSubnetController = TextEditingController();
|
||||
String? _ipv4PrefixSubnetError;
|
||||
final _ipv6PrefixSubnetController = TextEditingController();
|
||||
String? _ipv6PrefixSubnetError;
|
||||
String? _limitRequestsError;
|
||||
final _expandableCustomEdns = ExpandableController();
|
||||
final _expandableEdnsIp = ExpandableController();
|
||||
bool enableEdns = false;
|
||||
bool useCustomIpEdns = false;
|
||||
bool _enableEdns = false;
|
||||
bool _useCustomIpEdns = false;
|
||||
final _customIpEdnsController = TextEditingController();
|
||||
String? ednsIpError;
|
||||
bool enableDnssec = false;
|
||||
bool disableIpv6Resolving = false;
|
||||
String? _ednsIpError;
|
||||
bool _enableDnssec = false;
|
||||
bool _disableIpv6Resolving = false;
|
||||
|
||||
String blockingMode = "default";
|
||||
|
||||
final TextEditingController ipv4controller = TextEditingController();
|
||||
String? ipv4error;
|
||||
final TextEditingController ipv6controller = TextEditingController();
|
||||
final _ipv4controller = TextEditingController();
|
||||
String? _ipv4error;
|
||||
final _ipv6controller = TextEditingController();
|
||||
String? ipv6error;
|
||||
|
||||
final _ttlController = TextEditingController();
|
||||
String? _ttlError;
|
||||
|
||||
bool isDataValid = false;
|
||||
|
||||
void validateIpv4(String value) {
|
||||
RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$');
|
||||
if (ipAddress.hasMatch(value) == true) {
|
||||
setState(() => ipv4error = null);
|
||||
setState(() => _ipv4error = null);
|
||||
}
|
||||
else {
|
||||
setState(() => ipv4error = AppLocalizations.of(context)!.invalidIp);
|
||||
setState(() => _ipv4error = AppLocalizations.of(context)!.invalidIp);
|
||||
}
|
||||
validateData();
|
||||
}
|
||||
|
||||
void validateEdns(String value) {
|
||||
RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$');
|
||||
if (ipAddress.hasMatch(value) == true) {
|
||||
setState(() => ednsIpError = null);
|
||||
setState(() => _ednsIpError = null);
|
||||
}
|
||||
else {
|
||||
setState(() => ednsIpError = AppLocalizations.of(context)!.ipNotValid);
|
||||
setState(() => _ednsIpError = AppLocalizations.of(context)!.ipNotValid);
|
||||
}
|
||||
validateData();
|
||||
}
|
||||
|
||||
void validateIpv6(String value) {
|
||||
|
@ -76,63 +76,77 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
else {
|
||||
setState(() => ipv6error = AppLocalizations.of(context)!.invalidIp);
|
||||
}
|
||||
validateData();
|
||||
}
|
||||
|
||||
void validateData() {
|
||||
bool validateData() {
|
||||
if (
|
||||
limitRequestsController.text != '' &&
|
||||
limitRequestsError == null &&
|
||||
(_limitRequestsController.text == "" || (_limitRequestsController.text != "" && _limitRequestsError == null)) &&
|
||||
(
|
||||
blockingMode != 'custom_ip' ||
|
||||
(
|
||||
blockingMode == 'custom_ip' &&
|
||||
ipv4controller.text != '' &&
|
||||
ipv4error == null &&
|
||||
ipv6controller.text != '' &&
|
||||
_ipv4controller.text != '' &&
|
||||
_ipv4error == null &&
|
||||
_ipv6controller.text != '' &&
|
||||
ipv6error == null
|
||||
)
|
||||
) == true &&
|
||||
ednsIpError == null &&
|
||||
_ttlError == null
|
||||
_ednsIpError == null &&
|
||||
_ttlController.text != "" && _ttlError == null &&
|
||||
(_ipv4PrefixSubnetController.text == "" || (_ipv4PrefixSubnetController.text != "" && _ipv4PrefixSubnetError == null)) &&
|
||||
(_ipv6PrefixSubnetController.text == "" || (_ipv6PrefixSubnetController.text != "" && _ipv6PrefixSubnetError == null))
|
||||
) {
|
||||
setState(() => isDataValid = true);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
setState(() => isDataValid = false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void validateNumber(String value) {
|
||||
final regex = RegExp(r'^(\d)+$');
|
||||
if (regex.hasMatch(value) == true) {
|
||||
setState(() => _ttlError = null);
|
||||
String? validateTtl(String value) {
|
||||
if (value == "") return AppLocalizations.of(context)!.valueNotNumber;
|
||||
if (int.tryParse(value) != null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
setState(() => _ttlError = AppLocalizations.of(context)!.invalidValue);
|
||||
return AppLocalizations.of(context)!.valueNotNumber;
|
||||
}
|
||||
}
|
||||
|
||||
String? validateNumber(String value) {
|
||||
if (value == "") return null;
|
||||
if (int.tryParse(value) != null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return AppLocalizations.of(context)!.valueNotNumber;
|
||||
}
|
||||
validateData();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
final dnsProvider = Provider.of<DnsProvider>(context, listen: false);
|
||||
|
||||
limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString();
|
||||
enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled;
|
||||
useCustomIpEdns = dnsProvider.dnsInfo!.ednsCsUseCustom ?? false;
|
||||
_limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString();
|
||||
_enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled;
|
||||
_useCustomIpEdns = dnsProvider.dnsInfo!.ednsCsUseCustom ?? false;
|
||||
_customIpEdnsController.text = dnsProvider.dnsInfo!.ednsCsCustomIp ?? "";
|
||||
if (dnsProvider.dnsInfo!.ednsCsEnabled == true) _expandableCustomEdns.toggle();
|
||||
if (dnsProvider.dnsInfo!.ednsCsUseCustom == true) _expandableEdnsIp.toggle();
|
||||
enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled;
|
||||
disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6;
|
||||
_enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled;
|
||||
_disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6;
|
||||
blockingMode = dnsProvider.dnsInfo!.blockingMode;
|
||||
ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4;
|
||||
ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6;
|
||||
isDataValid = true;
|
||||
_ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4;
|
||||
_ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6;
|
||||
_ttlController.text = dnsProvider.dnsInfo!.blockedResponseTtl != null
|
||||
? dnsProvider.dnsInfo!.blockedResponseTtl.toString()
|
||||
: "";
|
||||
_ipv4PrefixSubnetController.text = dnsProvider.dnsInfo!.ratelimitSubnetLenIpv4 != null
|
||||
? dnsProvider.dnsInfo!.ratelimitSubnetLenIpv4.toString()
|
||||
: "";
|
||||
_ipv6PrefixSubnetController.text = dnsProvider.dnsInfo!.ratelimitSubnetLenIpv6 != null
|
||||
? dnsProvider.dnsInfo!.ratelimitSubnetLenIpv6.toString()
|
||||
: "";
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -147,16 +161,18 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
processModal.open(AppLocalizations.of(context)!.savingConfig);
|
||||
|
||||
final result = await dnsProvider.saveDnsServerConfig({
|
||||
"ratelimit": int.parse(limitRequestsController.text),
|
||||
"edns_cs_enabled": enableEdns,
|
||||
"edns_cs_use_custom": useCustomIpEdns,
|
||||
"ratelimit": int.parse(_limitRequestsController.text),
|
||||
"edns_cs_enabled": _enableEdns,
|
||||
"edns_cs_use_custom": _useCustomIpEdns,
|
||||
"edns_cs_custom_ip": _customIpEdnsController.text,
|
||||
"dnssec_enabled": enableDnssec,
|
||||
"disable_ipv6": disableIpv6Resolving,
|
||||
"dnssec_enabled": _enableDnssec,
|
||||
"disable_ipv6": _disableIpv6Resolving,
|
||||
"blocking_mode": blockingMode,
|
||||
"blocking_ipv4": ipv4controller.text,
|
||||
"blocking_ipv6": ipv6controller.text,
|
||||
"blocked_response_ttl": int.tryParse(_ttlController.text)
|
||||
"blocking_ipv4": _ipv4controller.text,
|
||||
"blocking_ipv6": _ipv6controller.text,
|
||||
"blocked_response_ttl": int.tryParse(_ttlController.text),
|
||||
"ratelimit_subnet_len_ipv4": int.tryParse(_ipv4PrefixSubnetController.text),
|
||||
"ratelimit_subnet_len_ipv6": int.tryParse(_ipv6PrefixSubnetController.text),
|
||||
});
|
||||
|
||||
processModal.close();
|
||||
|
@ -186,22 +202,24 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
|
||||
void updateBlockingMode(String mode) {
|
||||
if (mode != 'custom_ip') {
|
||||
ipv4controller.text = '';
|
||||
ipv4error = null;
|
||||
ipv6controller.text = '';
|
||||
_ipv4controller.text = '';
|
||||
_ipv4error = null;
|
||||
_ipv6controller.text = '';
|
||||
ipv6error = null;
|
||||
}
|
||||
setState(() => blockingMode = mode);
|
||||
validateData();
|
||||
}
|
||||
|
||||
final dataValid = validateData();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context)!.dnsServerSettings),
|
||||
surfaceTintColor: isDesktop(width) ? Colors.transparent : null,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: isDataValid == true
|
||||
onPressed: dataValid == true
|
||||
? () => saveData()
|
||||
: null,
|
||||
icon: const Icon(Icons.save_rounded),
|
||||
|
@ -217,16 +235,8 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: TextFormField(
|
||||
controller: limitRequestsController,
|
||||
onChanged: (value) {
|
||||
if (int.tryParse(value) != null) {
|
||||
setState(() => limitRequestsError = null);
|
||||
}
|
||||
else {
|
||||
setState(() => limitRequestsError = AppLocalizations.of(context)!.valueNotNumber);
|
||||
}
|
||||
validateData();
|
||||
},
|
||||
controller: _limitRequestsController,
|
||||
onChanged: (v) => setState(() => _limitRequestsError = validateNumber(v)),
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.looks_one_rounded),
|
||||
border: const OutlineInputBorder(
|
||||
|
@ -235,22 +245,58 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
)
|
||||
),
|
||||
labelText: AppLocalizations.of(context)!.limitRequestsSecond,
|
||||
errorText: limitRequestsError
|
||||
errorText: _limitRequestsError
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||
child: TextFormField(
|
||||
controller: _ipv4PrefixSubnetController,
|
||||
onChanged: (v) => setState(() => _ipv4PrefixSubnetError = validateNumber(v)),
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.skip_previous_rounded),
|
||||
border: const OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10)
|
||||
)
|
||||
),
|
||||
labelText: AppLocalizations.of(context)!.subnetPrefixLengthIpv4,
|
||||
errorText: _ipv4PrefixSubnetError
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: TextFormField(
|
||||
controller: _ipv6PrefixSubnetController,
|
||||
onChanged: (v) => setState(() => _ipv6PrefixSubnetError = validateNumber(v)),
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.skip_previous_rounded),
|
||||
border: const OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(10)
|
||||
)
|
||||
),
|
||||
labelText: AppLocalizations.of(context)!.subnetPrefixLengthIpv6,
|
||||
errorText: _ipv6PrefixSubnetError
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
CustomSwitchListTile(
|
||||
value: enableEdns,
|
||||
value: _enableEdns,
|
||||
onChanged: (value) => setState(() {
|
||||
enableEdns = value;
|
||||
_enableEdns = value;
|
||||
_expandableCustomEdns.toggle();
|
||||
if (value == false) {
|
||||
useCustomIpEdns = false;
|
||||
_useCustomIpEdns = false;
|
||||
if (_expandableEdnsIp.expanded == true) _expandableEdnsIp.toggle();
|
||||
_customIpEdnsController.text = "";
|
||||
ednsIpError = null;
|
||||
_ednsIpError = null;
|
||||
}
|
||||
validateData();
|
||||
}),
|
||||
|
@ -270,13 +316,13 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
bottom: 12,
|
||||
right: 16
|
||||
),
|
||||
value: useCustomIpEdns,
|
||||
value: _useCustomIpEdns,
|
||||
onChanged: (value) => setState(() {
|
||||
useCustomIpEdns = value;
|
||||
_useCustomIpEdns = value;
|
||||
_expandableEdnsIp.toggle();
|
||||
if (useCustomIpEdns == false) {
|
||||
if (_useCustomIpEdns == false) {
|
||||
_customIpEdnsController.text = "";
|
||||
ednsIpError = null;
|
||||
_ednsIpError = null;
|
||||
}
|
||||
validateData();
|
||||
}),
|
||||
|
@ -304,7 +350,7 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
Radius.circular(10)
|
||||
)
|
||||
),
|
||||
errorText: ednsIpError,
|
||||
errorText: _ednsIpError,
|
||||
labelText: AppLocalizations.of(context)!.ipAddress,
|
||||
),
|
||||
),
|
||||
|
@ -316,14 +362,14 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
)
|
||||
),
|
||||
CustomSwitchListTile(
|
||||
value: enableDnssec,
|
||||
onChanged: (value) => setState(() => enableDnssec = value),
|
||||
value: _enableDnssec,
|
||||
onChanged: (value) => setState(() => _enableDnssec = value),
|
||||
title: AppLocalizations.of(context)!.enableDnssec,
|
||||
subtitle: AppLocalizations.of(context)!.enableDnssecDescription,
|
||||
),
|
||||
CustomSwitchListTile(
|
||||
value: disableIpv6Resolving,
|
||||
onChanged: (value) => setState(() => disableIpv6Resolving = value),
|
||||
value: _disableIpv6Resolving,
|
||||
onChanged: (value) => setState(() => _disableIpv6Resolving = value),
|
||||
title: AppLocalizations.of(context)!.disableResolvingIpv6,
|
||||
subtitle: AppLocalizations.of(context)!.disableResolvingIpv6Description,
|
||||
),
|
||||
|
@ -373,7 +419,7 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: TextFormField(
|
||||
controller: ipv4controller,
|
||||
controller: _ipv4controller,
|
||||
onChanged: validateIpv4,
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.link_rounded),
|
||||
|
@ -382,7 +428,7 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
Radius.circular(10)
|
||||
)
|
||||
),
|
||||
errorText: ipv4error,
|
||||
errorText: _ipv4error,
|
||||
helperText: AppLocalizations.of(context)!.blockingIpv4Description,
|
||||
helperMaxLines: 10,
|
||||
labelText: AppLocalizations.of(context)!.blockingIpv4,
|
||||
|
@ -394,7 +440,7 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: TextFormField(
|
||||
controller: ipv6controller,
|
||||
controller: _ipv6controller,
|
||||
onChanged: validateIpv6,
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.link_rounded),
|
||||
|
@ -417,7 +463,7 @@ class _DnsServerSettingsScreenState extends State<DnsServerSettingsScreen> {
|
|||
padding: const EdgeInsets.all(16),
|
||||
child: TextFormField(
|
||||
controller: _ttlController,
|
||||
onChanged: validateNumber,
|
||||
onChanged: (v) => setState(() => _ttlError = validateTtl(v)),
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.timer_rounded),
|
||||
border: const OutlineInputBorder(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue