2022-10-23 04:50:12 +02:00
|
|
|
// ignore_for_file: use_build_context_synchronously
|
|
|
|
|
2022-10-22 23:06:27 +02:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
|
|
|
2022-10-25 21:12:00 +02:00
|
|
|
import 'package:adguard_home_manager/widgets/section_label.dart';
|
2022-10-27 22:29:23 +02:00
|
|
|
import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart';
|
2022-10-23 04:50:12 +02:00
|
|
|
import 'package:adguard_home_manager/screens/settings/encryption/config_error_modal.dart';
|
2022-10-27 22:29:23 +02:00
|
|
|
import 'package:adguard_home_manager/screens/settings/encryption/status.dart';
|
2022-10-23 19:27:23 +02:00
|
|
|
import 'package:adguard_home_manager/screens/settings/encryption/custom_text_field.dart';
|
|
|
|
import 'package:adguard_home_manager/screens/settings/encryption/master_switch.dart';
|
|
|
|
import 'package:adguard_home_manager/screens/settings/encryption/encryption_functions.dart';
|
2022-10-22 23:06:27 +02:00
|
|
|
|
2022-10-23 04:50:12 +02:00
|
|
|
import 'package:adguard_home_manager/classes/process_modal.dart';
|
2022-10-27 22:29:23 +02:00
|
|
|
import 'package:adguard_home_manager/functions/encode_base64.dart';
|
2022-10-23 04:50:12 +02:00
|
|
|
import 'package:adguard_home_manager/functions/snackbar.dart';
|
2022-10-22 23:06:27 +02:00
|
|
|
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 EncryptionSettings extends StatelessWidget {
|
|
|
|
const EncryptionSettings({Key? key}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final serversProvider = Provider.of<ServersProvider>(context);
|
|
|
|
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
|
|
|
|
|
|
|
return EncryptionSettingsWidget(
|
|
|
|
serversProvider: serversProvider,
|
|
|
|
appConfigProvider: appConfigProvider,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class EncryptionSettingsWidget extends StatefulWidget {
|
|
|
|
final ServersProvider serversProvider;
|
|
|
|
final AppConfigProvider appConfigProvider;
|
|
|
|
|
|
|
|
const EncryptionSettingsWidget({
|
|
|
|
Key? key,
|
|
|
|
required this.serversProvider,
|
|
|
|
required this.appConfigProvider,
|
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<EncryptionSettingsWidget> createState() => _EncryptionSettingsWidgetState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _EncryptionSettingsWidgetState extends State<EncryptionSettingsWidget> {
|
2022-10-23 19:27:23 +02:00
|
|
|
int loadStatus = 0;
|
|
|
|
|
2022-10-22 23:06:27 +02:00
|
|
|
bool enabled = false;
|
|
|
|
|
|
|
|
final TextEditingController domainNameController = TextEditingController();
|
|
|
|
String? domainError;
|
|
|
|
|
|
|
|
bool redirectHttps = false;
|
|
|
|
|
|
|
|
final TextEditingController httpsPortController = TextEditingController();
|
|
|
|
String? httpsPortError;
|
|
|
|
|
|
|
|
final TextEditingController tlsPortController = TextEditingController();
|
|
|
|
String? tlsPortError;
|
|
|
|
|
|
|
|
final TextEditingController dnsOverQuicPortController = TextEditingController();
|
|
|
|
String? dnsOverQuicPortError;
|
|
|
|
|
|
|
|
int certificateOption = 0;
|
|
|
|
|
|
|
|
final TextEditingController certificatePathController = TextEditingController();
|
|
|
|
String? certificatePathError;
|
|
|
|
|
|
|
|
final TextEditingController certificateContentController = TextEditingController();
|
|
|
|
String? certificateContentError;
|
|
|
|
|
|
|
|
int privateKeyOption = 0;
|
|
|
|
|
|
|
|
bool usePreviouslySavedKey = false;
|
|
|
|
|
|
|
|
final TextEditingController privateKeyPathController = TextEditingController();
|
|
|
|
String? privateKeyPathError;
|
|
|
|
|
|
|
|
final TextEditingController pastePrivateKeyController = TextEditingController();
|
|
|
|
String? pastePrivateKeyError;
|
|
|
|
|
2022-10-23 19:27:23 +02:00
|
|
|
bool localValidationValid = false;
|
2022-10-23 04:50:12 +02:00
|
|
|
String? validDataError;
|
2022-10-28 01:32:48 +02:00
|
|
|
int certKeyValidApi = 0;
|
2022-10-22 23:06:27 +02:00
|
|
|
|
2022-10-28 01:32:48 +02:00
|
|
|
Map<String, dynamic>? certKeyValid;
|
|
|
|
|
|
|
|
bool formEdited = false;
|
2022-10-27 22:29:23 +02:00
|
|
|
|
2022-10-22 23:06:27 +02:00
|
|
|
void fetchData({bool? showRefreshIndicator}) async {
|
2022-10-23 19:27:23 +02:00
|
|
|
setState(() => loadStatus = 0);
|
2022-10-22 23:06:27 +02:00
|
|
|
|
|
|
|
final result = await getEncryptionSettings(server: widget.serversProvider.selectedServer!);
|
|
|
|
|
|
|
|
if (mounted) {
|
|
|
|
if (result['result'] == 'success') {
|
2022-10-23 15:41:25 +02:00
|
|
|
await checkValidDataApi(data: result['data'].toJson());
|
|
|
|
|
2022-10-23 04:50:12 +02:00
|
|
|
setState(() {
|
|
|
|
enabled = result['data'].enabled;
|
|
|
|
domainNameController.text = result['data'].serverName ?? '';
|
|
|
|
redirectHttps = result['data'].forceHttps;
|
|
|
|
httpsPortController.text = result['data'].portHttps != null ? result['data'].portHttps.toString() : '';
|
|
|
|
tlsPortController.text = result['data'].portDnsOverTls != null ? result['data'].portDnsOverTls.toString() : '';
|
|
|
|
dnsOverQuicPortController.text = result['data'].portDnsOverQuic != null ? result['data'].portDnsOverQuic.toString() : '';
|
|
|
|
if (result['data'].certificateChain != '' && result['data'].certificatePath == '') {
|
|
|
|
certificateOption = 1;
|
2022-10-28 01:32:48 +02:00
|
|
|
certificateContentController.text = "-----BEGIN CERTIFICATE-----\n${result['data'].certificateChain}\n-----END CERTIFICATE-----";
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
else if (result['data'].certificateChain == '' && result['data'].certificatePath != '') {
|
|
|
|
certificateOption = 0;
|
|
|
|
certificatePathController.text = result['data'].certificatePath;
|
|
|
|
}
|
|
|
|
if (result['data'].privateKey != '' && result['data'].privateKeyPath == '') {
|
|
|
|
privateKeyOption = 1;
|
2022-10-28 01:32:48 +02:00
|
|
|
pastePrivateKeyController.text = "-----BEGIN PRIVATE KEY-----\n${result['data'].privateKey}\n-----END PRIVATE KEY-----";
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
else if (result['data'].privateKey == '' && result['data'].privateKeyPath != '') {
|
|
|
|
privateKeyOption = 0;
|
|
|
|
privateKeyPathController.text = result['data'].privateKeyPath;
|
|
|
|
}
|
|
|
|
usePreviouslySavedKey = result['data'].privateKeySaved;
|
|
|
|
|
2022-10-23 19:27:23 +02:00
|
|
|
loadStatus = 1;
|
|
|
|
});
|
2022-10-22 23:06:27 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
widget.appConfigProvider.addLog(result['log']);
|
2022-10-23 19:27:23 +02:00
|
|
|
setState(() => loadStatus = 2);
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-23 15:41:25 +02:00
|
|
|
Future checkValidDataApi({Map<String, dynamic>? data}) async {
|
2022-10-28 01:32:48 +02:00
|
|
|
setState(() => certKeyValidApi = 0);
|
2022-10-23 04:50:12 +02:00
|
|
|
|
2022-10-23 15:41:25 +02:00
|
|
|
final result = await checkEncryptionSettings(server: widget.serversProvider.selectedServer!, data: data ?? {
|
2022-10-23 04:50:12 +02:00
|
|
|
"enabled": enabled,
|
|
|
|
"server_name": domainNameController.text,
|
|
|
|
"force_https": redirectHttps,
|
|
|
|
"port_https": httpsPortController.text != '' ? int.parse(httpsPortController.text) : null,
|
|
|
|
"port_dns_over_tls": tlsPortController.text != '' ? int.parse(tlsPortController.text) : null,
|
|
|
|
"port_dns_over_quic": dnsOverQuicPortController.text != '' ? int.parse(dnsOverQuicPortController.text) : null,
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certificateOption == 1) "certificate_chain": encodeBase64(certificateContentController.text),
|
|
|
|
if (privateKeyOption == 1 && usePreviouslySavedKey == false) "private_key": encodeBase64(pastePrivateKeyController.text),
|
2022-10-23 04:50:12 +02:00
|
|
|
"private_key_saved": usePreviouslySavedKey,
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certificateOption == 0) "certificate_path": certificatePathController.text,
|
|
|
|
if (privateKeyOption == 0) "private_key_path": privateKeyPathController.text,
|
2022-10-23 04:50:12 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
if (result['result'] == 'success') {
|
|
|
|
setState(() {
|
|
|
|
if (result['data']['warning_validation'] != null && result['data']['warning_validation'] != '') {
|
2022-10-28 01:32:48 +02:00
|
|
|
certKeyValidApi = 2;
|
2022-10-23 04:50:12 +02:00
|
|
|
validDataError = result['data']['warning_validation'];
|
|
|
|
}
|
|
|
|
else {
|
2022-10-28 01:32:48 +02:00
|
|
|
certKeyValidApi = 1;
|
2022-10-23 04:50:12 +02:00
|
|
|
validDataError = null;
|
|
|
|
}
|
2022-10-28 01:32:48 +02:00
|
|
|
print(result['data']['server_name']);
|
|
|
|
certKeyValid = result['data'];
|
2022-10-23 04:50:12 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (result['log'].resBody != null) {
|
|
|
|
setState(() => validDataError = result['log'].resBody);
|
|
|
|
}
|
2022-10-28 01:32:48 +02:00
|
|
|
setState(() => certKeyValidApi = 2);
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-28 01:32:48 +02:00
|
|
|
bool checkcertKeyValid() {
|
2022-10-23 04:50:12 +02:00
|
|
|
if (
|
|
|
|
domainNameController.text != '' &&
|
|
|
|
domainError == null &&
|
|
|
|
httpsPortController.text != '' &&
|
|
|
|
httpsPortError == null &&
|
|
|
|
tlsPortController.text != '' &&
|
|
|
|
tlsPortError == null &&
|
|
|
|
dnsOverQuicPortController.text != '' &&
|
|
|
|
dnsOverQuicPortError == null &&
|
|
|
|
((
|
|
|
|
certificateOption == 0 &&
|
|
|
|
certificatePathController.text != '' &&
|
|
|
|
certificatePathError == null
|
|
|
|
) || (
|
|
|
|
certificateOption == 1 &&
|
|
|
|
certificateContentController.text != '' &&
|
|
|
|
certificateContentError == null
|
|
|
|
)) &&
|
|
|
|
((
|
|
|
|
privateKeyOption == 0 &&
|
|
|
|
privateKeyPathController.text != '' &&
|
|
|
|
privateKeyPathError == null
|
|
|
|
) || (
|
|
|
|
privateKeyOption == 1 &&
|
|
|
|
pastePrivateKeyController.text != '' &&
|
|
|
|
pastePrivateKeyError == null
|
|
|
|
))
|
|
|
|
) {
|
2022-10-23 19:27:23 +02:00
|
|
|
setState(() => localValidationValid = true);
|
2022-10-28 01:32:48 +02:00
|
|
|
return true;
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
else {
|
2022-10-23 19:27:23 +02:00
|
|
|
setState(() => localValidationValid = false);
|
2022-10-28 01:32:48 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void onEditValidate() {
|
|
|
|
setState(() => formEdited = true);
|
|
|
|
final res = checkcertKeyValid();
|
|
|
|
if (res == true) {
|
|
|
|
checkValidDataApi();
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 23:06:27 +02:00
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
fetchData();
|
2022-10-23 04:50:12 +02:00
|
|
|
|
2022-10-22 23:06:27 +02:00
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final serversProvider = Provider.of<ServersProvider>(context);
|
|
|
|
final appConfigProvider = Provider.of<AppConfigProvider>(context);
|
|
|
|
|
2022-10-23 04:50:12 +02:00
|
|
|
void saveData() async {
|
|
|
|
ProcessModal processModal = ProcessModal(context: context);
|
|
|
|
processModal.open(AppLocalizations.of(context)!.savingConfig);
|
|
|
|
|
|
|
|
final result = await saveEncryptionSettings(server: serversProvider.selectedServer!, data: {
|
|
|
|
"enabled": enabled,
|
|
|
|
"server_name": domainNameController.text,
|
|
|
|
"force_https": redirectHttps,
|
|
|
|
"port_https": int.parse(httpsPortController.text),
|
|
|
|
"port_dns_over_tls": int.parse(tlsPortController.text),
|
|
|
|
"port_dns_over_quic": int.parse(dnsOverQuicPortController.text),
|
|
|
|
"certificate_chain": certificateContentController.text,
|
|
|
|
"private_key": pastePrivateKeyController.text,
|
|
|
|
"private_key_saved": usePreviouslySavedKey,
|
|
|
|
"certificate_path": certificatePathController.text,
|
|
|
|
"private_key_path": privateKeyPathController.text,
|
|
|
|
});
|
|
|
|
|
|
|
|
processModal.close();
|
|
|
|
|
|
|
|
if (result['result'] == 'success') {
|
|
|
|
showSnacbkar(
|
|
|
|
context: context,
|
|
|
|
appConfigProvider: appConfigProvider,
|
|
|
|
label: AppLocalizations.of(context)!.encryptionConfigSaved,
|
|
|
|
color: Colors.green
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
appConfigProvider.addLog(result['log']);
|
|
|
|
|
|
|
|
showSnacbkar(
|
|
|
|
context: context,
|
|
|
|
appConfigProvider: appConfigProvider,
|
|
|
|
label: AppLocalizations.of(context)!.encryptionConfigNotSaved,
|
|
|
|
color: Colors.red
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 23:06:27 +02:00
|
|
|
Widget generateBody() {
|
2022-10-23 19:27:23 +02:00
|
|
|
switch (loadStatus) {
|
2022-10-22 23:06:27 +02:00
|
|
|
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)!.loadingEncryptionSettings,
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
style: const TextStyle(
|
|
|
|
fontSize: 22,
|
|
|
|
color: Colors.grey,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
return ListView(
|
|
|
|
children: [
|
2022-10-23 19:27:23 +02:00
|
|
|
EncryptionMasterSwitch(
|
|
|
|
value: enabled,
|
|
|
|
onChange: (value) {
|
|
|
|
setState(() => enabled = value);
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
}
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
SectionLabel(label: AppLocalizations.of(context)!.serverConfiguration),
|
2022-10-23 19:27:23 +02:00
|
|
|
EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: domainNameController,
|
|
|
|
icon: Icons.link_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => domainError = validateDomain(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
errorText: domainError,
|
|
|
|
label: AppLocalizations.of(context)!.domainName,
|
|
|
|
helperText: AppLocalizations.of(context)!.domainNameDescription,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
CustomSwitchListTile(
|
|
|
|
value: redirectHttps,
|
2022-10-23 04:50:12 +02:00
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => redirectHttps = value);
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 04:50:12 +02:00
|
|
|
},
|
2022-10-22 23:06:27 +02:00
|
|
|
title: AppLocalizations.of(context)!.redirectHttps,
|
2022-10-23 04:50:12 +02:00
|
|
|
disabled: !enabled,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
2022-10-23 19:27:23 +02:00
|
|
|
EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: httpsPortController,
|
|
|
|
icon: Icons.numbers_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => httpsPortError = validatePort(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
errorText: httpsPortError,
|
|
|
|
label: AppLocalizations.of(context)!.httpsPort,
|
|
|
|
keyboardType: TextInputType.number,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 30),
|
2022-10-23 19:27:23 +02:00
|
|
|
EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: tlsPortController,
|
|
|
|
icon: Icons.numbers_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => tlsPortError = validatePort(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
errorText: tlsPortError,
|
|
|
|
label: AppLocalizations.of(context)!.tlsPort,
|
|
|
|
keyboardType: TextInputType.number,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 30),
|
2022-10-23 19:27:23 +02:00
|
|
|
EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: dnsOverQuicPortController,
|
|
|
|
icon: Icons.numbers_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => dnsOverQuicPortError = validatePort(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
errorText: dnsOverQuicPortError,
|
|
|
|
label: AppLocalizations.of(context)!.dnsOverQuicPort,
|
|
|
|
keyboardType: TextInputType.number,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
SectionLabel(label: AppLocalizations.of(context)!.certificates),
|
|
|
|
Card(
|
|
|
|
margin: const EdgeInsets.symmetric(horizontal: 20),
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.all(20),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
const Icon(Icons.info_rounded),
|
|
|
|
const SizedBox(width: 20),
|
|
|
|
Flexible(
|
|
|
|
child: Text(AppLocalizations.of(context)!.certificatesDescription)
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
const SizedBox(height: 20),
|
|
|
|
RadioListTile(
|
|
|
|
value: 0,
|
|
|
|
groupValue: certificateOption,
|
2022-10-23 04:50:12 +02:00
|
|
|
onChanged: enabled == true
|
|
|
|
? (value) {
|
|
|
|
setState(() => certificateOption = int.parse(value.toString()));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
: null,
|
2022-10-22 23:06:27 +02:00
|
|
|
title: Text(
|
|
|
|
AppLocalizations.of(context)!.certificateFilePath,
|
|
|
|
style: const TextStyle(
|
|
|
|
fontWeight: FontWeight.normal
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
RadioListTile(
|
|
|
|
value: 1,
|
|
|
|
groupValue: certificateOption,
|
2022-10-23 04:50:12 +02:00
|
|
|
onChanged: enabled == true
|
|
|
|
? (value) {
|
|
|
|
setState(() => certificateOption = int.parse(value.toString()));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
: null,
|
2022-10-22 23:06:27 +02:00
|
|
|
title: Text(
|
|
|
|
AppLocalizations.of(context)!.pasteCertificateContent,
|
|
|
|
style: const TextStyle(
|
|
|
|
fontWeight: FontWeight.normal
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
2022-10-23 19:27:23 +02:00
|
|
|
if (certificateOption == 0) EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: certificatePathController,
|
|
|
|
icon: Icons.description_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => certificatePathError = validatePath(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
label: AppLocalizations.of(context)!.certificatePath,
|
|
|
|
errorText: certificatePathError,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
2022-10-23 19:27:23 +02:00
|
|
|
if (certificateOption == 1) EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: certificateContentController,
|
|
|
|
icon: Icons.description_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => certificateContentError = validateCertificate(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
label: AppLocalizations.of(context)!.certificateContent,
|
|
|
|
errorText: certificateContentError,
|
|
|
|
multiline: true,
|
|
|
|
keyboardType: TextInputType.multiline,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid != null && certificateContentController.text != '' && certificateContentError == null) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
const SizedBox(height: 20),
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid!['valid_chain'] != null) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
Status(
|
2022-10-28 01:32:48 +02:00
|
|
|
valid: certKeyValid!['valid_chain'],
|
|
|
|
label: certKeyValid!['valid_chain'] == true
|
2022-10-27 22:29:23 +02:00
|
|
|
? AppLocalizations.of(context)!.validCertificateChain
|
|
|
|
: AppLocalizations.of(context)!.invalidCertificateChain,
|
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
],
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid!['subject'] != null) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
Status(
|
|
|
|
valid: true,
|
2022-10-28 01:32:48 +02:00
|
|
|
label: "${AppLocalizations.of(context)!.subject}: ${certKeyValid!['subject']}"
|
2022-10-27 22:29:23 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
],
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid!['issuer'] != null) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
Status(
|
|
|
|
valid: true,
|
2022-10-28 01:32:48 +02:00
|
|
|
label: "${AppLocalizations.of(context)!.issuer}: ${certKeyValid!['issuer']}"
|
2022-10-27 22:29:23 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
],
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid!['not_after'] != null) ...[
|
|
|
|
Status(
|
|
|
|
valid: true,
|
|
|
|
label: "${AppLocalizations.of(context)!.expirationDate}: ${certKeyValid!['not_after']}"
|
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
],
|
|
|
|
if (certKeyValid!['dns_names'] != null) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
Status(
|
|
|
|
valid: true,
|
2022-10-28 01:32:48 +02:00
|
|
|
label: "${AppLocalizations.of(context)!.hostNames}: ${certKeyValid!['dns_names'].join(', ')}"
|
2022-10-27 22:29:23 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
]
|
|
|
|
],
|
2022-10-22 23:06:27 +02:00
|
|
|
SectionLabel(label: AppLocalizations.of(context)!.privateKey),
|
|
|
|
RadioListTile(
|
|
|
|
value: 0,
|
|
|
|
groupValue: privateKeyOption,
|
2022-10-23 04:50:12 +02:00
|
|
|
onChanged: enabled == true
|
|
|
|
? (value) {
|
|
|
|
setState(() => privateKeyOption = int.parse(value.toString()));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
: null,
|
2022-10-22 23:06:27 +02:00
|
|
|
title: Text(
|
|
|
|
AppLocalizations.of(context)!.privateKeyFile,
|
|
|
|
style: const TextStyle(
|
|
|
|
fontWeight: FontWeight.normal
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
RadioListTile(
|
|
|
|
value: 1,
|
|
|
|
groupValue: privateKeyOption,
|
2022-10-23 04:50:12 +02:00
|
|
|
onChanged: enabled == true
|
|
|
|
? (value) {
|
|
|
|
setState(() => privateKeyOption = int.parse(value.toString()));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 04:50:12 +02:00
|
|
|
}
|
|
|
|
: null,
|
2022-10-22 23:06:27 +02:00
|
|
|
title: Text(
|
|
|
|
AppLocalizations.of(context)!.pastePrivateKey,
|
|
|
|
style: const TextStyle(
|
|
|
|
fontWeight: FontWeight.normal
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
if (privateKeyOption == 0) const SizedBox(height: 10),
|
|
|
|
if (privateKeyOption == 1) ...[
|
|
|
|
CustomSwitchListTile(
|
|
|
|
value: usePreviouslySavedKey,
|
|
|
|
onChanged: (value) => setState(() => usePreviouslySavedKey = value),
|
|
|
|
title: AppLocalizations.of(context)!.usePreviousKey,
|
|
|
|
),
|
|
|
|
const SizedBox(height: 10)
|
|
|
|
],
|
2022-10-23 19:27:23 +02:00
|
|
|
if (privateKeyOption == 0) EncryptionTextField(
|
|
|
|
enabled: enabled,
|
|
|
|
controller: privateKeyPathController,
|
|
|
|
icon: Icons.description_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => privateKeyPathError = validatePath(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
label: AppLocalizations.of(context)!.privateKeyPath,
|
|
|
|
errorText: privateKeyPathError,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
2022-10-23 19:27:23 +02:00
|
|
|
if (privateKeyOption == 1) EncryptionTextField(
|
|
|
|
enabled: enabled == true
|
|
|
|
? !usePreviouslySavedKey
|
|
|
|
: false,
|
|
|
|
controller: pastePrivateKeyController,
|
|
|
|
icon: Icons.description_rounded,
|
|
|
|
onChanged: (value) {
|
|
|
|
setState(() => pastePrivateKeyError = validatePrivateKey(context, value));
|
2022-10-28 01:32:48 +02:00
|
|
|
onEditValidate();
|
2022-10-23 19:27:23 +02:00
|
|
|
},
|
|
|
|
label: AppLocalizations.of(context)!.pastePrivateKey,
|
|
|
|
errorText: pastePrivateKeyError,
|
|
|
|
keyboardType: TextInputType.multiline,
|
|
|
|
multiline: true,
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
const SizedBox(height: 20),
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid != null && pastePrivateKeyController.text != '' && pastePrivateKeyError == null) ...[
|
|
|
|
if (certKeyValid!['valid_key'] != null) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
Status(
|
2022-10-28 01:32:48 +02:00
|
|
|
valid: certKeyValid!['valid_key'],
|
|
|
|
label: certKeyValid!['valid_key'] == true
|
2022-10-27 22:29:23 +02:00
|
|
|
? AppLocalizations.of(context)!.validPrivateKey
|
|
|
|
: AppLocalizations.of(context)!.invalidPrivateKey,
|
|
|
|
),
|
|
|
|
const SizedBox(height: 10)
|
|
|
|
],
|
2022-10-28 01:32:48 +02:00
|
|
|
if (certKeyValid!['valid_pair'] != null && certKeyValid!['valid_pair'] == false) ...[
|
2022-10-27 22:29:23 +02:00
|
|
|
Status(
|
|
|
|
valid: false,
|
|
|
|
label: AppLocalizations.of(context)!.keysNotMatch,
|
|
|
|
),
|
|
|
|
const SizedBox(height: 10)
|
|
|
|
],
|
|
|
|
const SizedBox(height: 10)
|
|
|
|
]
|
2022-10-22 23:06:27 +02:00
|
|
|
],
|
|
|
|
);
|
|
|
|
|
|
|
|
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)!.encryptionSettingsNotLoaded,
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
style: const TextStyle(
|
|
|
|
fontSize: 22,
|
|
|
|
color: Colors.grey,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
default:
|
|
|
|
return const SizedBox();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Scaffold(
|
|
|
|
appBar: AppBar(
|
|
|
|
title: Text(AppLocalizations.of(context)!.encryptionSettings),
|
2022-10-23 04:50:12 +02:00
|
|
|
actions: [
|
|
|
|
IconButton(
|
2022-10-28 01:32:48 +02:00
|
|
|
onPressed: certKeyValidApi == 2 && validDataError != null
|
2022-10-23 04:50:12 +02:00
|
|
|
? () => {
|
|
|
|
showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) => EncryptionErrorModal(error: validDataError!)
|
|
|
|
)
|
|
|
|
} : null,
|
2022-10-28 01:32:48 +02:00
|
|
|
icon: generateStatus(context, appConfigProvider, localValidationValid, certKeyValidApi, formEdited),
|
|
|
|
tooltip: generateStatusString(context, localValidationValid, certKeyValidApi)
|
2022-10-23 04:50:12 +02:00
|
|
|
),
|
|
|
|
IconButton(
|
2022-10-28 01:32:48 +02:00
|
|
|
onPressed: localValidationValid == true && certKeyValidApi == 1
|
2022-10-23 04:50:12 +02:00
|
|
|
? () => saveData()
|
|
|
|
: null,
|
|
|
|
icon: const Icon(Icons.save),
|
|
|
|
tooltip: AppLocalizations.of(context)!.save,
|
|
|
|
),
|
|
|
|
const SizedBox(width: 10),
|
|
|
|
],
|
2022-10-22 23:06:27 +02:00
|
|
|
),
|
|
|
|
body: generateBody(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|