From 87f7c2c29b95eb370f0eee82fc73f09b95c2138e Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Wed, 3 Nov 2021 18:56:53 -0700 Subject: [PATCH] server delete functionality and minor cleanups --- LIBCWTCH-GO.version | 2 +- lib/cwtch/cwtchNotifier.dart | 6 ++ lib/errorHandler.dart | 38 +++++++++++++ lib/l10n/intl_de.arb | 7 ++- lib/l10n/intl_en.arb | 7 ++- lib/l10n/intl_es.arb | 7 ++- lib/l10n/intl_fr.arb | 45 ++++++++------- lib/l10n/intl_it.arb | 7 ++- lib/l10n/intl_pl.arb | 7 ++- lib/l10n/intl_pt.arb | 7 ++- lib/models/servers.dart | 5 ++ lib/views/addeditservers.dart | 102 ++++++++++++++++++++++++++++------ lib/views/profilemgrview.dart | 1 + lib/widgets/profilerow.dart | 2 + lib/widgets/serverrow.dart | 3 + 15 files changed, 202 insertions(+), 44 deletions(-) diff --git a/LIBCWTCH-GO.version b/LIBCWTCH-GO.version index f6bca1aa..3fe724f0 100644 --- a/LIBCWTCH-GO.version +++ b/LIBCWTCH-GO.version @@ -1 +1 @@ -v1.3.1-23-gb47b270-2021-11-03-19-29 \ No newline at end of file +v1.3.1-25-g4adb501-2021-11-04-04-20 \ No newline at end of file diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index 44fdc8e0..9c69ca7d 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -104,6 +104,12 @@ class CwtchNotifier { // todo standarize error.handleUpdate("deleteprofile.success"); break; + case "ServerDeleted": + error.handleUpdate("deletedserver." + data["Status"]); + if (data["Status"] == "success") { + serverListState.delete(data["Identity"]); + } + break; case "DeleteContact": profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["RemotePeer"]); break; diff --git a/lib/errorHandler.dart b/lib/errorHandler.dart index 4feada1c..a54094c7 100644 --- a/lib/errorHandler.dart +++ b/lib/errorHandler.dart @@ -21,6 +21,27 @@ class ErrorHandler extends ChangeNotifier { bool deleteProfileError = false; bool deleteProfileSuccess = false; + static const String deletedServerErrorPrefix = "deletedserver"; + bool deletedServerError = false; + bool deletedServerSuccess = false; + + reset() { + invalidImportStringError = false; + contactAlreadyExistsError = false; + explicitAddContactSuccess = false; + + importBundleError = false; + importBundleSuccess = false; + + deleteProfileError = false; + deleteProfileSuccess = false; + + deletedServerError = false; + deletedServerSuccess = false; + + notifyListeners(); + } + /// Called by the event bus. handleUpdate(String error) { var parts = error.split("."); @@ -37,6 +58,8 @@ class ErrorHandler extends ChangeNotifier { case deleteProfileErrorPrefix: handleDeleteProfileError(errorType); break; + case deletedServerErrorPrefix: + handleDeletedServerError(errorType); } notifyListeners(); @@ -91,4 +114,19 @@ class ErrorHandler extends ChangeNotifier { break; } } + + handleDeletedServerError(String errorType) { + // reset + deletedServerError = false; + deletedServerSuccess = false; + + switch (errorType) { + case successErrorType: + deletedServerSuccess = true; + break; + default: + deletedServerError = true; + break; + } + } } diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index 575bbdb3..aa6b06eb 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -1,6 +1,11 @@ { "@@locale": "de", - "@@last_modified": "2021-11-02T23:03:43+01:00", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", "copyAddress": "Copy Address", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", "settingServers": "Hosting Servers", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index b6badee4..088c5b45 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,6 +1,11 @@ { "@@locale": "en", - "@@last_modified": "2021-11-02T23:03:43+01:00", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", "copyAddress": "Copy Address", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", "settingServers": "Hosting Servers", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 1892268e..bcc6aaeb 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -1,6 +1,11 @@ { "@@locale": "es", - "@@last_modified": "2021-11-02T23:03:43+01:00", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", "copyAddress": "Copy Address", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", "settingServers": "Hosting Servers", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 37865907..351be299 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -1,25 +1,30 @@ { "@@locale": "fr", - "@@last_modified": "2021-11-02T23:03:43+01:00", - "copyAddress": "Copy Address", - "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", - "settingServers": "Hosting Servers", - "enterServerPassword": "Enter password to unlock server", - "unlockProfileTip": "Please create or unlock a profile to begin!", - "unlockServerTip": "Please create or unlock a server to begin!", - "addServerTooltip": "Add new server", - "serversManagerTitleShort": "Servers", - "serversManagerTitleLong": "Servers You Host", - "saveServerButton": "Save Server", - "serverAutostartDescription": "Controls if the application will automatically launch the server on start", - "serverAutostartLabel": "Autostart", - "serverEnabledDescription": "Start or stop the server", - "serverEnabled": "Server Enabled", - "serverDescriptionDescription": "Your description of the server for personal management use only, will never be shared", - "serverDescriptionLabel": "Server Description", - "serverAddress": "Server Address", - "editServerTitle": "Edit Server", - "addServerTitle": "Add Server", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", + "copyAddress": "Copier l'adresse", + "settingServersDescription": "L'expérience des serveurs d'hébergement permet d'héberger et de gérer les serveurs Cwtch.", + "settingServers": "Serveurs d'hébergement", + "enterServerPassword": "Entrez le mot de passe pour déverrouiller le serveur", + "unlockProfileTip": "Veuillez créer ou déverrouiller un profil pour commencer !", + "unlockServerTip": "Veuillez créer ou déverrouiller un serveur pour commencer !", + "addServerTooltip": "Ajouter un nouveau serveur", + "serversManagerTitleShort": "Serveurs", + "serversManagerTitleLong": "Serveurs que vous hébergez", + "saveServerButton": "Enregistrer le serveur", + "serverAutostartDescription": "Contrôle si l'application lance automatiquement le serveur au démarrage.", + "serverAutostartLabel": "Démarrage automatique", + "serverEnabledDescription": "Démarrer ou arrêter le serveur", + "serverEnabled": "Serveur activé", + "serverDescriptionDescription": "Votre description du serveur est à des fins de gestion personnelle uniquement, elle ne sera jamais partagée.", + "serverDescriptionLabel": "Description du serveur", + "serverAddress": "Adresse du serveur", + "editServerTitle": "Modifier le serveur", + "addServerTitle": "Ajouter un serveur", "titleManageProfilesShort": "Profils", "descriptionStreamerMode": "Si elle est activée, cette option donne un rendu visuel plus privé à l'application pour la diffusion en direct ou la présentation, par exemple, en masquant profil et adresses de contacts.", "descriptionFileSharing": "L'expérience de partage de fichiers vous permet d'envoyer et de recevoir des fichiers à partir de contacts et de groupes Cwtch. Notez que si vous partagez un fichier avec un groupe, les membres de ce groupe se connecteront avec vous directement via Cwtch pour le télécharger.", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index 97a272ba..87e767bf 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -1,6 +1,11 @@ { "@@locale": "it", - "@@last_modified": "2021-11-02T23:03:43+01:00", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", "copyAddress": "Copy Address", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", "settingServers": "Hosting Servers", diff --git a/lib/l10n/intl_pl.arb b/lib/l10n/intl_pl.arb index 8905b0ea..542c0348 100644 --- a/lib/l10n/intl_pl.arb +++ b/lib/l10n/intl_pl.arb @@ -1,6 +1,11 @@ { "@@locale": "pl", - "@@last_modified": "2021-11-02T23:03:43+01:00", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", "copyAddress": "Copy Address", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", "settingServers": "Hosting Servers", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index 7000bec8..90eef948 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -1,6 +1,11 @@ { "@@locale": "pt", - "@@last_modified": "2021-11-02T23:03:43+01:00", + "@@last_modified": "2021-11-04T02:39:11+01:00", + "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", + "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", + "deleteServerConfirmBtn": "Really delete server", + "deleteServerSuccess": "Successfully deleted server", + "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", "copyAddress": "Copy Address", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", "settingServers": "Hosting Servers", diff --git a/lib/models/servers.dart b/lib/models/servers.dart index 2cafbe60..a2277e20 100644 --- a/lib/models/servers.dart +++ b/lib/models/servers.dart @@ -34,6 +34,11 @@ class ServerListState extends ChangeNotifier { notifyListeners(); } + void delete(String onion) { + _servers.removeWhere((element) => element.onion == onion); + notifyListeners(); + } + List get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier } diff --git a/lib/views/addeditservers.dart b/lib/views/addeditservers.dart index c4477659..c551ea4d 100644 --- a/lib/views/addeditservers.dart +++ b/lib/views/addeditservers.dart @@ -164,6 +164,7 @@ class _AddEditServerViewState extends State { // ***** Password ***** + // use password toggle Visibility( visible: serverInfoState.onion.isEmpty, child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -186,20 +187,19 @@ class _AddEditServerViewState extends State { Padding( padding: EdgeInsets.symmetric(horizontal: 24), child: Text( - usePassword ? AppLocalizations.of(context)!.encryptedProfileDescription : AppLocalizations.of(context)!.plainProfileDescription, + usePassword ? AppLocalizations.of(context)!.encryptedServerDescription : AppLocalizations.of(context)!.plainServerDescription, textAlign: TextAlign.center, - )) + )), + SizedBox( + height: 20, + ), ])), - SizedBox( - height: 20, - ), + + + // current password Visibility( - // Currently we don't support password change for servers so also gate this on Add server, when ready to support changing password remove the onion.isEmpty check - visible: serverInfoState.onion.isEmpty && usePassword, - child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Visibility( - visible: serverInfoState.onion.isNotEmpty && serverInfoState.isEncrypted, - child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + visible: serverInfoState.onion.isNotEmpty && serverInfoState.isEncrypted, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ CwtchLabel(label: AppLocalizations.of(context)!.currentPasswordLabel), SizedBox( height: 20, @@ -215,8 +215,8 @@ class _AddEditServerViewState extends State { usePassword) { return AppLocalizations.of(context)!.passwordErrorEmpty; } - if (Provider.of(context).deleteProfileError == true) { - return AppLocalizations.of(context)!.enterCurrentPasswordForDelete; + if (Provider.of(context).deletedServerError == true) { + return AppLocalizations.of(context)!.enterCurrentPasswordForDeleteServer; } return null; }, @@ -225,6 +225,12 @@ class _AddEditServerViewState extends State { height: 20, ), ])), + + // new passwords 1 & 2 + Visibility( + // Currently we don't support password change for servers so also gate this on Add server, when ready to support changing password remove the onion.isEmpty check + visible: serverInfoState.onion.isEmpty && usePassword, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ CwtchLabel(label: AppLocalizations.of(context)!.newPassword), SizedBox( height: 20, @@ -263,6 +269,7 @@ class _AddEditServerViewState extends State { }), ]), ), + SizedBox( height: 20, ), @@ -281,13 +288,25 @@ class _AddEditServerViewState extends State { ), ], ), + Visibility( + visible: serverInfoState.onion.isNotEmpty, + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [ + SizedBox( + height: 20, + ), + Tooltip( + message: AppLocalizations.of(context)!.enterCurrentPasswordForDeleteServer, + child: ElevatedButton.icon( + onPressed: () { + showAlertDialog(context); + }, + icon: Icon(Icons.delete_forever), + label: Text(AppLocalizations.of(context)!.deleteBtn), + )) + ])) // ***** END Password ***** - - - - ])))))); }); }); @@ -327,4 +346,53 @@ class _AddEditServerViewState extends State { } Navigator.of(context).pop(); } + + showAlertDialog(BuildContext context) { + // set up the buttons + Widget cancelButton = ElevatedButton( + child: Text(AppLocalizations.of(context)!.cancel), + onPressed: () { + Navigator.of(context).pop(); // dismiss dialog + }, + ); + Widget continueButton = ElevatedButton( + child: Text(AppLocalizations.of(context)!.deleteServerConfirmBtn), + onPressed: () { + var onion = Provider + .of(context, listen: false) + .onion; + Provider + .of(context, listen: false) + .cwtch + .DeleteServer(onion, Provider.of(context, listen: false).isEncrypted ? ctrlrOldPass.value.text : DefaultPassword); + Future.delayed( + const Duration(milliseconds: 500), + () { + if (globalErrorHandler.deletedServerSuccess) { + final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.deleteServerSuccess + ":" + onion)); + ScaffoldMessenger.of(context).showSnackBar(snackBar); + Navigator.of(context).popUntil((route) => route.settings.name == "servers"); // dismiss dialog + } else { + Navigator.of(context).pop(); + } + }, + ); + }); + // set up the AlertDialog + AlertDialog alert = AlertDialog( + title: Text(AppLocalizations.of(context)!.deleteServerConfirmBtn), + actions: [ + cancelButton, + continueButton, + ], + ); + + // show the dialog + showDialog( + context: context, + builder: (BuildContext context) { + return alert; + }, + ); + } } \ No newline at end of file diff --git a/lib/views/profilemgrview.dart b/lib/views/profilemgrview.dart index e33209c0..de7f65b5 100644 --- a/lib/views/profilemgrview.dart +++ b/lib/views/profilemgrview.dart @@ -129,6 +129,7 @@ class _ProfileMgrViewState extends State { void _pushServers() { Navigator.of(context).push(MaterialPageRoute( + settings: RouteSettings(name: "servers"), builder: (BuildContext context) { return MultiProvider( providers: [Provider.value(value: Provider.of(context))], diff --git a/lib/widgets/profilerow.dart b/lib/widgets/profilerow.dart index d2df0f66..39bce219 100644 --- a/lib/widgets/profilerow.dart +++ b/lib/widgets/profilerow.dart @@ -7,6 +7,7 @@ import 'package:cwtch/widgets/profileimage.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import '../errorHandler.dart'; import '../main.dart'; import '../model.dart'; import '../settings.dart'; @@ -101,6 +102,7 @@ class _ProfileRowState extends State { } void _pushEditProfile({onion: "", displayName: "", profileImage: "", encrypted: true}) { + Provider.of(context).reset(); Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) { return MultiProvider( diff --git a/lib/widgets/serverrow.dart b/lib/widgets/serverrow.dart index e20095be..8da87c65 100644 --- a/lib/widgets/serverrow.dart +++ b/lib/widgets/serverrow.dart @@ -8,6 +8,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import '../cwtch_icons_icons.dart'; +import '../errorHandler.dart'; import '../model.dart'; import '../settings.dart'; @@ -80,7 +81,9 @@ class _ServerRowState extends State { } void _pushEditServer(ServerInfoState server ) { + Provider.of(context).reset(); Navigator.of(context).push(MaterialPageRoute( + settings: RouteSettings(name: "serveraddedit"), builder: (BuildContext context) { return MultiProvider( providers: [ChangeNotifierProvider(