3
0
Fork 0
trifid_mobile/lib/screens/siteConfig/CertificateDetailsScreen.dart

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

211 lines
7.2 KiB
Dart
Raw Permalink Normal View History

2020-07-27 20:43:58 +00:00
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
2021-05-03 20:16:00 +00:00
import 'package:mobile_nebula/components/FormPage.dart';
2020-07-27 20:43:58 +00:00
import 'package:mobile_nebula/components/config/ConfigItem.dart';
import 'package:mobile_nebula/components/config/ConfigSection.dart';
import 'package:mobile_nebula/models/Certificate.dart';
2021-05-03 20:16:00 +00:00
import 'package:mobile_nebula/screens/siteConfig/AddCertificateScreen.dart';
2020-07-27 20:43:58 +00:00
import 'package:mobile_nebula/services/utils.dart';
/// Displays the details of a CertificateInfo object. Respects incomplete objects (missing validity or rawCert)
class CertificateDetailsScreen extends StatefulWidget {
const CertificateDetailsScreen({
Key? key,
required this.certInfo,
this.onDelete,
this.onSave,
this.onReplace,
this.pubKey,
this.privKey,
required this.supportsQRScanning,
}) : super(key: key);
2020-07-27 20:43:58 +00:00
2021-05-03 20:16:00 +00:00
final CertificateInfo certInfo;
// onDelete is used to remove a CA cert
final Function? onDelete;
2020-07-27 20:43:58 +00:00
2021-05-03 20:16:00 +00:00
// onSave is used to install a new certificate
final Function? onSave;
2021-05-03 20:16:00 +00:00
// onReplace is used to install a new certificate over top of the old one
final ValueChanged<CertificateResult>? onReplace;
2021-05-03 20:16:00 +00:00
// pubKey and privKey should be set if onReplace is not null.
final String? pubKey;
final String? privKey;
final bool supportsQRScanning;
2020-07-27 20:43:58 +00:00
@override
_CertificateDetailsScreenState createState() => _CertificateDetailsScreenState();
}
class _CertificateDetailsScreenState extends State<CertificateDetailsScreen> {
2021-05-03 20:16:00 +00:00
bool changed = false;
CertificateResult? certResult;
late CertificateInfo certInfo;
2021-05-03 20:16:00 +00:00
ScrollController controller = ScrollController();
@override
void initState() {
certInfo = widget.certInfo;
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
2020-07-27 20:43:58 +00:00
@override
Widget build(BuildContext context) {
2021-05-03 20:16:00 +00:00
return FormPage(
2020-07-27 20:43:58 +00:00
title: 'Certificate Details',
2021-05-03 20:16:00 +00:00
scrollController: controller,
changed: widget.onSave != null || changed,
onSave: () {
if (widget.onSave != null) {
Navigator.pop(context);
widget.onSave!();
2021-05-03 20:16:00 +00:00
} else if (widget.onReplace != null) {
Navigator.pop(context);
widget.onReplace!(certResult!);
2021-05-03 20:16:00 +00:00
}
},
hideSave: widget.onSave == null && widget.onReplace == null,
2020-07-27 20:43:58 +00:00
child: Column(children: [
_buildID(),
_buildFilters(),
_buildValid(),
_buildAdvanced(),
2021-05-03 20:16:00 +00:00
_buildReplace(),
2020-07-27 20:43:58 +00:00
_buildDelete(),
]),
);
}
Widget _buildID() {
return ConfigSection(children: <Widget>[
ConfigItem(label: Text('Name'), content: SelectableText(certInfo.cert.details.name)),
2020-07-27 20:43:58 +00:00
ConfigItem(
2021-05-03 20:16:00 +00:00
label: Text('Type'), content: Text(certInfo.cert.details.isCa ? 'CA certificate' : 'Client certificate')),
2020-07-27 20:43:58 +00:00
]);
}
Widget _buildValid() {
var valid = Text('yes');
if (certInfo.validity != null && !certInfo.validity!.valid) {
valid = Text(certInfo.validity!.valid ? 'yes' : certInfo.validity!.reason,
2020-07-27 20:43:58 +00:00
style: TextStyle(color: CupertinoColors.systemRed.resolveFrom(context)));
}
return ConfigSection(
label: 'VALIDITY',
children: <Widget>[
ConfigItem(label: Text('Valid?'), content: valid),
ConfigItem(
2022-07-27 16:38:02 +00:00
label: Text('Created'), content: SelectableText(certInfo.cert.details.notBefore.toLocal().toString())),
2020-07-27 20:43:58 +00:00
ConfigItem(
2022-07-27 16:38:02 +00:00
label: Text('Expires'), content: SelectableText(certInfo.cert.details.notAfter.toLocal().toString())),
2020-07-27 20:43:58 +00:00
],
);
}
Widget _buildFilters() {
List<Widget> items = [];
2021-05-03 20:16:00 +00:00
if (certInfo.cert.details.groups.length > 0) {
2022-07-27 16:38:02 +00:00
items.add(ConfigItem(label: Text('Groups'), content: SelectableText(certInfo.cert.details.groups.join(', '))));
2020-07-27 20:43:58 +00:00
}
2021-05-03 20:16:00 +00:00
if (certInfo.cert.details.ips.length > 0) {
items.add(ConfigItem(label: Text('IPs'), content: SelectableText(certInfo.cert.details.ips.join(', '))));
2020-07-27 20:43:58 +00:00
}
2021-05-03 20:16:00 +00:00
if (certInfo.cert.details.subnets.length > 0) {
2022-07-27 16:38:02 +00:00
items.add(ConfigItem(label: Text('Subnets'), content: SelectableText(certInfo.cert.details.subnets.join(', '))));
2020-07-27 20:43:58 +00:00
}
return items.length > 0
2021-05-03 20:16:00 +00:00
? ConfigSection(label: certInfo.cert.details.isCa ? 'FILTERS' : 'DETAILS', children: items)
2020-07-27 20:43:58 +00:00
: Container();
}
Widget _buildAdvanced() {
return ConfigSection(
children: <Widget>[
ConfigItem(
label: Text('Fingerprint'),
2022-07-27 16:38:02 +00:00
content:
SelectableText(certInfo.cert.fingerprint, style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14)),
2020-07-27 20:43:58 +00:00
crossAxisAlignment: CrossAxisAlignment.start),
ConfigItem(
label: Text('Public Key'),
content: SelectableText(certInfo.cert.details.publicKey,
2020-07-27 20:43:58 +00:00
style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14)),
crossAxisAlignment: CrossAxisAlignment.start),
2021-05-03 20:16:00 +00:00
certInfo.rawCert != null
2020-07-27 20:43:58 +00:00
? ConfigItem(
label: Text('PEM Format'),
content: SelectableText(certInfo.rawCert!, style: TextStyle(fontFamily: 'RobotoMono', fontSize: 14)),
2020-07-27 20:43:58 +00:00
crossAxisAlignment: CrossAxisAlignment.start)
: Container(),
],
);
}
2021-05-03 20:16:00 +00:00
Widget _buildReplace() {
if (widget.onReplace == null || widget.pubKey == null || widget.privKey == null) {
2021-05-03 20:16:00 +00:00
return Container();
}
return Padding(
padding: EdgeInsets.only(top: 50, bottom: 10, left: 10, right: 10),
child: SizedBox(
width: double.infinity,
2022-07-27 16:38:02 +00:00
child: PlatformElevatedButton(
2021-05-03 20:16:00 +00:00
child: Text('Replace certificate'),
color: CupertinoColors.systemRed.resolveFrom(context),
onPressed: () {
Utils.openPage(context, (context) {
return AddCertificateScreen(
onReplace: (result) {
setState(() {
changed = true;
certResult = result;
certInfo = result.certInfo;
});
// Slam the page back to the top
controller.animateTo(0,
duration: const Duration(milliseconds: 10), curve: Curves.linearToEaseOut);
},
pubKey: widget.pubKey!,
privKey: widget.privKey!,
supportsQRScanning: widget.supportsQRScanning,
);
2021-05-03 20:16:00 +00:00
});
})));
}
2020-07-27 20:43:58 +00:00
Widget _buildDelete() {
if (widget.onDelete == null) {
return Container();
}
2021-05-03 20:16:00 +00:00
var title = certInfo.cert.details.isCa ? 'Delete CA?' : 'Delete cert?';
2020-07-27 20:43:58 +00:00
return Padding(
padding: EdgeInsets.only(top: 50, bottom: 10, left: 10, right: 10),
child: SizedBox(
width: double.infinity,
2022-07-27 16:38:02 +00:00
child: PlatformElevatedButton(
2020-07-27 20:43:58 +00:00
child: Text('Delete'),
color: CupertinoColors.systemRed.resolveFrom(context),
onPressed: () => Utils.confirmDelete(context, title, () async {
Navigator.pop(context);
widget.onDelete!();
2020-07-27 20:43:58 +00:00
}))));
}
}