Browse Source

Better show different states of E2E

Co-authored-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Signed-off-by: Tobias Kaminsky <tobias@nextcloud.com>
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tobiasKaminsky 2 years ago
parent
commit
5b4aba11f5

BIN
app/screenshots/gplay/debug/com.nextcloud.client.SettingsActivityIT_open.png


BIN
app/screenshots/gplay/debug/com.nextcloud.client.SettingsActivityIT_showMnemonic_Error.png


+ 3 - 0
app/src/main/AndroidManifest.xml

@@ -194,6 +194,9 @@
             android:name=".ui.activity.TextEditorWebView"
             android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
             android:exported="false" />
+        <activity
+            android:name=".ui.activity.SetupEncryptionActivity"
+            android:exported="false" />
         <activity
             android:name=".ui.activity.ContactsPreferenceActivity"
             android:exported="false"

+ 1 - 3
app/src/main/java/com/nextcloud/client/jobs/AccountRemovalWork.kt

@@ -114,9 +114,7 @@ class AccountRemovalWork(
         uploadsStorageManager.removeUserUploads(user)
 
         // delete stored E2E keys and mnemonic
-        arbitraryDataProvider.deleteKeyForAccount(user.accountName, EncryptionUtils.PRIVATE_KEY)
-        arbitraryDataProvider.deleteKeyForAccount(user.accountName, EncryptionUtils.PUBLIC_KEY)
-        arbitraryDataProvider.deleteKeyForAccount(user.accountName, EncryptionUtils.MNEMONIC)
+        EncryptionUtils.removeE2E(arbitraryDataProvider, user)
 
         // unset default account, if needed
         if (preferences.currentAccountName.equals(user.accountName)) {

+ 60 - 1
app/src/main/java/com/owncloud/android/ui/activity/SettingsActivity.java

@@ -72,6 +72,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.providers.DocumentsStorageProvider;
 import com.owncloud.android.ui.ThemeableSwitchPreference;
 import com.owncloud.android.ui.asynctasks.LoadingVersionNumberTask;
+import com.owncloud.android.ui.helpers.FileOperationsHelper;
+import com.owncloud.android.utils.ClipboardUtil;
 import com.owncloud.android.utils.DeviceCredentialUtils;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.EncryptionUtils;
@@ -98,7 +100,8 @@ import androidx.core.content.res.ResourcesCompat;
  * It proxies the necessary calls via {@link androidx.appcompat.app.AppCompatDelegate} to be used with AppCompat.
  */
 public class SettingsActivity extends PreferenceActivity
-    implements StorageMigration.StorageMigrationProgressListener, LoadingVersionNumberTask.VersionDevInterface,
+    implements StorageMigration.StorageMigrationProgressListener,
+    LoadingVersionNumberTask.VersionDevInterface,
     Injectable {
 
     private static final String TAG = SettingsActivity.class.getSimpleName();
@@ -323,8 +326,12 @@ public class SettingsActivity extends PreferenceActivity
 
         setupBackupPreference();
 
+        setupE2EPreference(preferenceCategoryMore);
+
         setupE2EMnemonicPreference(preferenceCategoryMore);
 
+        removeE2E(preferenceCategoryMore);
+
         setupHelpPreference(preferenceCategoryMore);
 
         setupRecommendPreference(preferenceCategoryMore);
@@ -411,6 +418,25 @@ public class SettingsActivity extends PreferenceActivity
         }
     }
 
+    private void setupE2EPreference(PreferenceCategory preferenceCategoryMore) {
+        Preference preference = findPreference("setup_e2e");
+
+        if (preference != null) {
+            if (FileOperationsHelper.isEndToEndEncryptionSetup(this, user)) {
+                preferenceCategoryMore.removePreference(preference);
+            } else {
+                preference.setOnPreferenceClickListener(p -> {
+                    Intent i = new Intent(MainApp.getAppContext(), SetupEncryptionActivity.class);
+                    i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+                    i.putExtra("EXTRA_USER", user);
+                    startActivityForResult(i, ACTION_SHOW_MNEMONIC);
+
+                    return true;
+                });
+            }
+        }
+    }
+
     private void setupE2EMnemonicPreference(PreferenceCategory preferenceCategoryMore) {
         String mnemonic = arbitraryDataProvider.getValue(user.getAccountName(), EncryptionUtils.MNEMONIC);
 
@@ -436,6 +462,36 @@ public class SettingsActivity extends PreferenceActivity
         }
     }
 
+    private void removeE2E(PreferenceCategory preferenceCategoryMore) {
+        Preference preference = findPreference("remove_e2e");
+
+        if (preference != null) {
+            if (!FileOperationsHelper.isEndToEndEncryptionSetup(this, user)) {
+                preferenceCategoryMore.removePreference(preference);
+            } else {
+                preference.setOnPreferenceClickListener(p -> {
+                    AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.FallbackTheming_Dialog);
+                    AlertDialog alertDialog = builder.setTitle(R.string.prefs_e2e_mnemonic)
+                        .setMessage(getString(R.string.remove_e2e_message))
+                        .setCancelable(true)
+                        .setNegativeButton(R.string.common_cancel, ((dialog, i) -> dialog.dismiss()))
+                        .setPositiveButton(R.string.confirm_removal, (dialog, which) -> {
+                            // do something
+                            EncryptionUtils.removeE2E(arbitraryDataProvider, user);
+                            preferenceCategoryMore.removePreference(preference);
+
+                            dialog.dismiss();
+                        })
+                        .create();
+
+                    alertDialog.show();
+
+                    return true;
+                });
+            }
+        }
+    }
+
     private void setupHelpPreference(PreferenceCategory preferenceCategoryMore) {
         boolean helpEnabled = getResources().getBoolean(R.bool.help_enabled);
         Preference pHelp = findPreference("help");
@@ -879,6 +935,9 @@ public class SettingsActivity extends PreferenceActivity
                 AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.FallbackTheming_Dialog);
                 AlertDialog alertDialog = builder.setTitle(R.string.prefs_e2e_mnemonic)
                     .setMessage(mnemonic)
+                    .setNegativeButton(R.string.common_cancel, (dialog, i) -> dialog.dismiss())
+                    .setNeutralButton(R.string.common_copy, (dialog, i) ->
+                        ClipboardUtil.copyToClipboard(this, mnemonic, false))
                     .setPositiveButton(R.string.common_ok, (dialog, which) -> dialog.dismiss())
                     .create();
 

+ 46 - 0
app/src/main/java/com/owncloud/android/ui/activity/SetupEncryptionActivity.kt

@@ -0,0 +1,46 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2022 Tobias Kaminsky
+ * Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.activity
+
+import android.os.Bundle
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.nextcloud.client.account.User
+import com.owncloud.android.R
+import com.owncloud.android.ui.dialog.SetupEncryptionDialogFragment
+
+class SetupEncryptionActivity : AppCompatActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        val user = intent?.getParcelableExtra("EXTRA_USER") as User?
+
+        if (user == null) {
+            Toast.makeText(this, getString(R.string.error_showing_encryption_dialog), Toast.LENGTH_LONG).show()
+            return
+        }
+
+        val setupEncryptionDialogFragment = SetupEncryptionDialogFragment.newInstance(user, -1)
+        setupEncryptionDialogFragment.show(supportFragmentManager, null)
+    }
+}

+ 7 - 0
app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java

@@ -851,4 +851,11 @@ public final class EncryptionUtils {
             return new RemoteOperationResult(new Exception("No token available"));
         }
     }
+
+    public static void removeE2E(ArbitraryDataProvider arbitraryDataProvider, User user) {
+        // delete stored E2E keys and mnemonic
+        arbitraryDataProvider.deleteKeyForAccount(user.getAccountName(), EncryptionUtils.PRIVATE_KEY);
+        arbitraryDataProvider.deleteKeyForAccount(user.getAccountName(), EncryptionUtils.PUBLIC_KEY);
+        arbitraryDataProvider.deleteKeyForAccount(user.getAccountName(), EncryptionUtils.MNEMONIC);
+    }
 }

+ 10 - 0
app/src/main/res/values/strings.xml

@@ -124,6 +124,7 @@
     <string name="common_send">Send</string>
     <string name="common_share">Share</string>
     <string name="common_skip">Skip</string>
+    <string name="common_copy">Copy</string>
     <string name="about_title">About</string>
     <string name="delete_account">Remove account</string>
     <string name="delete_account_warning">Remove account %s and delete all local files?\n\nDeletion cannot be undone.</string>
@@ -1056,4 +1057,13 @@
     <string name="error_file_actions">Error showing file actions</string>
     <string name="pin_home">Pin to Home screen</string>
     <string name="pin_shortcut_label">Open %1$s</string>
+    <string name="displays_mnemonic">Displays your 12 word passphrase</string>
+    <string name="prefs_setup_e2e">Set up end to end encryption</string>
+    <string name="prefs_e2e_active">End to end encryption is set up!</string>
+    <string name="prefs_remove_e2e">Remove encryption locally</string>
+    <string name="remove_e2e">You can remove end to end encryption locally on this client</string>
+    <string name="confirm_removal">Remove local encryption</string>
+    <string name="remove_e2e_message">You can remove end to end encryption locally on this client. The encrypted files will remain on server, but will not be synced to this computer any longer.</string>
+    <string name="setup_e2e">During setup of end to end encryption you will receive random 12 word mnemonic, which you need to add another client. This will only be stored on this computer and can be shown here. Please note it down to a secure place!</string>
+    <string name="error_showing_encryption_dialog">Error showing setup encryption dialog!</string>
 </resources>

+ 35 - 15
app/src/main/res/xml/preferences.xml

@@ -59,27 +59,47 @@
             android:key="show_media_scan_notifications"/>
 	</PreferenceCategory>
 
-	<PreferenceCategory android:title="@string/prefs_category_more" android:key="more">
+	<PreferenceCategory
+        android:title="@string/prefs_category_more"
+        android:key="more">
         <Preference
             android:title="@string/drawer_synced_folders"
             android:key="syncedFolders"
-            android:summary="@string/prefs_sycned_folders_summary"/>
-		<Preference android:title="@string/prefs_calendar_contacts"
-					android:key="calendar_contacts"
-					android:summary="@string/prefs_calendar_contacts_summary" />
-		<Preference
+            android:summary="@string/prefs_sycned_folders_summary" />
+        <Preference
+            android:title="@string/prefs_calendar_contacts"
+            android:key="calendar_contacts"
+            android:summary="@string/prefs_calendar_contacts_summary" />
+        <Preference
             android:title="@string/backup_title"
             android:key="backup"
             android:summary="@string/prefs_daily_backup_summary" />
-		<Preference
-			android:title="@string/prefs_e2e_mnemonic"
-			android:key="mnemonic"
-			android:summary="Displays your E2E 12 words passphrase" />
-		<Preference android:title="@string/prefs_help" android:key="help" />
-		<Preference android:title="@string/prefs_recommend" android:key="recommend" />
-		<Preference android:title="@string/logs_title" android:key="logger" />
-		<Preference android:title="@string/prefs_imprint" android:key="imprint" />
-	</PreferenceCategory>
+        <Preference
+            android:title="@string/prefs_setup_e2e"
+            android:key="setup_e2e"
+            android:summary="@string/setup_e2e" />
+        <Preference
+            android:title="@string/prefs_e2e_active"
+            android:key="mnemonic"
+            android:summary="@string/displays_mnemonic" />
+        <Preference
+            android:title="@string/prefs_remove_e2e"
+            android:key="remove_e2e"
+            android:summary="@string/remove_e2e" />
+
+        <Preference
+            android:title="@string/prefs_help"
+            android:key="help" />
+        <Preference
+            android:title="@string/prefs_recommend"
+            android:key="recommend" />
+        <Preference
+            android:title="@string/logs_title"
+            android:key="logger" />
+        <Preference
+            android:title="@string/prefs_imprint"
+            android:key="imprint" />
+    </PreferenceCategory>
 	<PreferenceCategory android:title="@string/prefs_category_about" android:key="about">
 		<Preference
 			android:title="@string/privacy"