diff options
Diffstat (limited to 'app/src/main/java')
9 files changed, 133 insertions, 129 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt index c202b573..70525083 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt @@ -26,10 +26,10 @@ import app.passwordstore.util.auth.BiometricAuthenticator import app.passwordstore.util.auth.BiometricAuthenticator.Result as BiometricResult import app.passwordstore.util.autofill.AutofillPreferences import app.passwordstore.util.autofill.AutofillResponseBuilder -import app.passwordstore.util.autofill.DirectoryStructure import app.passwordstore.util.extensions.asLog import app.passwordstore.util.features.Feature.EnablePGPPassphraseCache import app.passwordstore.util.features.Features +import app.passwordstore.util.settings.DirectoryStructure import app.passwordstore.util.settings.PreferenceKeys import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.Credentials diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt index 85aa707c..b027657e 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillFilterView.kt @@ -27,9 +27,9 @@ import app.passwordstore.data.password.PasswordItem import app.passwordstore.databinding.ActivityOreoAutofillFilterBinding import app.passwordstore.util.autofill.AutofillMatcher import app.passwordstore.util.autofill.AutofillPreferences -import app.passwordstore.util.autofill.DirectoryStructure import app.passwordstore.util.coroutines.DispatcherProvider import app.passwordstore.util.extensions.viewBinding +import app.passwordstore.util.settings.DirectoryStructure import app.passwordstore.util.viewmodel.FilterMode import app.passwordstore.util.viewmodel.ListMode import app.passwordstore.util.viewmodel.SearchMode diff --git a/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt index a9cdec80..b4fd21e5 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/PasswordCreationActivity.kt @@ -30,7 +30,6 @@ import app.passwordstore.ui.dialogs.DicewarePasswordGeneratorDialogFragment import app.passwordstore.ui.dialogs.OtpImportDialogFragment import app.passwordstore.ui.dialogs.PasswordGeneratorDialogFragment import app.passwordstore.util.autofill.AutofillPreferences -import app.passwordstore.util.autofill.DirectoryStructure import app.passwordstore.util.extensions.asLog import app.passwordstore.util.extensions.base64 import app.passwordstore.util.extensions.commitChange @@ -39,6 +38,7 @@ import app.passwordstore.util.extensions.isInsideRepository import app.passwordstore.util.extensions.snackbar import app.passwordstore.util.extensions.unsafeLazy import app.passwordstore.util.extensions.viewBinding +import app.passwordstore.util.settings.DirectoryStructure import app.passwordstore.util.settings.PreferenceKeys import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.onSuccess diff --git a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt index 9eef3d92..ae00e1d1 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt @@ -15,7 +15,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import app.passwordstore.BuildConfig import app.passwordstore.R -import app.passwordstore.util.autofill.DirectoryStructure import app.passwordstore.util.extensions.autofillManager import app.passwordstore.util.settings.PreferenceKeys import com.github.androidpasswordstore.autofillparser.BrowserAutofillSupportLevel @@ -24,10 +23,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.Maxr1998.modernpreferences.PreferenceScreen import de.Maxr1998.modernpreferences.helpers.editText import de.Maxr1998.modernpreferences.helpers.onClick -import de.Maxr1998.modernpreferences.helpers.singleChoice import de.Maxr1998.modernpreferences.helpers.switch import de.Maxr1998.modernpreferences.preferences.SwitchPreference -import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem class AutofillSettings(private val activity: FragmentActivity) : SettingsProvider { @@ -101,16 +98,6 @@ class AutofillSettings(private val activity: FragmentActivity) : SettingsProvide false } } - val values = - activity.resources.getStringArray(R.array.oreo_autofill_directory_structure_values) - val titles = - activity.resources.getStringArray(R.array.oreo_autofill_directory_structure_entries) - val items = values.zip(titles).map { SelectionItem(it.first, it.second, null) } - singleChoice(PreferenceKeys.OREO_AUTOFILL_DIRECTORY_STRUCTURE, items) { - initialSelection = DirectoryStructure.DEFAULT.value - dependency = PreferenceKeys.AUTOFILL_ENABLE - titleRes = R.string.oreo_autofill_preference_directory_structure - } editText(PreferenceKeys.OREO_AUTOFILL_DEFAULT_USERNAME) { dependency = PreferenceKeys.AUTOFILL_ENABLE titleRes = R.string.preference_default_username_title diff --git a/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt index fb5e095b..e3594269 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt @@ -14,6 +14,7 @@ import app.passwordstore.R import app.passwordstore.util.auth.BiometricAuthenticator import app.passwordstore.util.auth.BiometricAuthenticator.Result import app.passwordstore.util.extensions.sharedPrefs +import app.passwordstore.util.settings.DirectoryStructure import app.passwordstore.util.settings.PreferenceKeys import de.Maxr1998.modernpreferences.PreferenceScreen import de.Maxr1998.modernpreferences.helpers.onClick @@ -34,6 +35,14 @@ class GeneralSettings(private val activity: FragmentActivity) : SettingsProvider titleRes = R.string.pref_app_theme_title } + val values = activity.resources.getStringArray(R.array.directory_structure_values) + val titles = activity.resources.getStringArray(R.array.directory_structure_entries) + val items = values.zip(titles).map { SelectionItem(it.first, it.second, null) } + singleChoice(PreferenceKeys.DIRECTORY_STRUCTURE, items) { + initialSelection = DirectoryStructure.DEFAULT.value + titleRes = R.string.pref_directory_structure + } + val sortValues = activity.resources.getStringArray(R.array.sort_order_values) val sortOptions = activity.resources.getStringArray(R.array.sort_order_entries) val sortItems = sortValues.zip(sortOptions).map { SelectionItem(it.first, it.second, null) } diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt index 21dad1ea..ef7be1ac 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt @@ -9,124 +9,15 @@ import app.passwordstore.data.passfile.PasswordEntry import app.passwordstore.util.extensions.getString import app.passwordstore.util.extensions.sharedPrefs import app.passwordstore.util.services.getDefaultUsername +import app.passwordstore.util.settings.DirectoryStructure import app.passwordstore.util.settings.PreferenceKeys import com.github.androidpasswordstore.autofillparser.Credentials import java.io.File -import java.nio.file.Paths - -enum class DirectoryStructure(val value: String) { - EncryptedUsername("encrypted_username"), - FileBased("file"), - DirectoryBased("directory"); - - /** - * Returns the username associated to [file], following the convention of the current - * [DirectoryStructure]. - * - * Examples: - * - * --> null (EncryptedUsername) - * - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased) - * - work/example.org/john@doe.org/password.gpg --> john@doe.org (DirectoryBased) - * - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback) - */ - fun getUsernameFor(file: File): String? = - when (this) { - EncryptedUsername -> null - FileBased -> file.nameWithoutExtension - DirectoryBased -> file.parentFile?.name ?: file.nameWithoutExtension - } - - /** - * Returns the origin identifier associated to [file], following the convention of the current - * [DirectoryStructure]. - * - * At least one of [DirectoryStructure.getIdentifierFor] and - * [DirectoryStructure.getAccountPartFor] will always return a non-null result. - * - * Examples: - * - work/example.org.gpg --> example.org (EncryptedUsername) - * - work/example.org/john@doe.org.gpg --> example.org (FileBased) - * - example.org.gpg --> example.org (FileBased, fallback) - * - work/example.org/john@doe.org/password.gpg --> example.org (DirectoryBased) - * - Temporary PIN.gpg --> null (DirectoryBased) - */ - fun getIdentifierFor(file: File): String? = - when (this) { - EncryptedUsername -> file.nameWithoutExtension - FileBased -> file.parentFile?.name ?: file.nameWithoutExtension - DirectoryBased -> file.parentFile?.parent - } - - /** - * Returns the path components of [file] until right before the component that contains the origin - * identifier according to the current [DirectoryStructure]. - * - * Examples: - * - work/example.org.gpg --> work (EncryptedUsername) - * - work/example.org/john@doe.org.gpg --> work (FileBased) - * - example.org/john@doe.org.gpg --> null (FileBased) - * - john@doe.org.gpg --> null (FileBased) - * - work/example.org/john@doe.org/password.gpg --> work (DirectoryBased) - * - example.org/john@doe.org/password.gpg --> null (DirectoryBased) - */ - fun getPathToIdentifierFor(file: File): String? = - when (this) { - EncryptedUsername -> file.parent - FileBased -> file.parentFile?.parent - DirectoryBased -> file.parentFile?.parentFile?.parent - } - - /** - * Returns the path component of [file] following the origin identifier according to the current - * [DirectoryStructure](without file extension). - * - * At least one of [DirectoryStructure.getIdentifierFor] and - * [DirectoryStructure.getAccountPartFor] will always return a non-null result. - * - * Examples: - * - * --> null (EncryptedUsername) - * - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased) - * - example.org.gpg --> null (FileBased, fallback) - * - work/example.org/john@doe.org/password.gpg --> john@doe.org/password (DirectoryBased) - * - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback) - */ - fun getAccountPartFor(file: File): String? = - when (this) { - EncryptedUsername -> null - FileBased -> file.nameWithoutExtension.takeIf { file.parentFile != null } - DirectoryBased -> - file.parentFile?.let { parentFile -> "${parentFile.name}/${file.nameWithoutExtension}" } - ?: file.nameWithoutExtension - } - - fun getSaveFolderName(sanitizedIdentifier: String, username: String?) = - when (this) { - EncryptedUsername -> "/" - FileBased -> sanitizedIdentifier - DirectoryBased -> Paths.get(sanitizedIdentifier, username ?: "username").toString() - } - - fun getSaveFileName(username: String?, identifier: String) = - when (this) { - EncryptedUsername -> identifier - FileBased -> username - DirectoryBased -> "password" - } - - companion object { - - val DEFAULT = FileBased - - private val reverseMap = entries.associateBy { it.value } - - fun fromValue(value: String?) = if (value != null) reverseMap[value] ?: DEFAULT else DEFAULT - } -} object AutofillPreferences { fun directoryStructure(context: Context): DirectoryStructure { - val value = context.sharedPrefs.getString(PreferenceKeys.OREO_AUTOFILL_DIRECTORY_STRUCTURE) + val value = context.sharedPrefs.getString(PreferenceKeys.DIRECTORY_STRUCTURE) return DirectoryStructure.fromValue(value) } diff --git a/app/src/main/java/app/passwordstore/util/settings/DirectoryStructure.kt b/app/src/main/java/app/passwordstore/util/settings/DirectoryStructure.kt new file mode 100644 index 00000000..99f982ed --- /dev/null +++ b/app/src/main/java/app/passwordstore/util/settings/DirectoryStructure.kt @@ -0,0 +1,117 @@ +/* + * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package app.passwordstore.util.settings + +import java.io.File +import java.nio.file.Paths + +enum class DirectoryStructure(val value: String) { + EncryptedUsername("encrypted_username"), + FileBased("file"), + DirectoryBased("directory"); + + /** + * Returns the username associated to [file], following the convention of the current + * [DirectoryStructure]. + * + * Examples: + * - * --> null (EncryptedUsername) + * - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased) + * - work/example.org/john@doe.org/password.gpg --> john@doe.org (DirectoryBased) + * - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback) + */ + fun getUsernameFor(file: File): String? = + when (this) { + EncryptedUsername -> null + FileBased -> file.nameWithoutExtension + DirectoryBased -> file.parentFile?.name ?: file.nameWithoutExtension + } + + /** + * Returns the origin identifier associated to [file], following the convention of the current + * [DirectoryStructure]. + * + * At least one of [DirectoryStructure.getIdentifierFor] and + * [DirectoryStructure.getAccountPartFor] will always return a non-null result. + * + * Examples: + * - work/example.org.gpg --> example.org (EncryptedUsername) + * - work/example.org/john@doe.org.gpg --> example.org (FileBased) + * - example.org.gpg --> example.org (FileBased, fallback) + * - work/example.org/john@doe.org/password.gpg --> example.org (DirectoryBased) + * - Temporary PIN.gpg --> null (DirectoryBased) + */ + fun getIdentifierFor(file: File): String? = + when (this) { + EncryptedUsername -> file.nameWithoutExtension + FileBased -> file.parentFile?.name ?: file.nameWithoutExtension + DirectoryBased -> file.parentFile?.parent + } + + /** + * Returns the path components of [file] until right before the component that contains the origin + * identifier according to the current [DirectoryStructure]. + * + * Examples: + * - work/example.org.gpg --> work (EncryptedUsername) + * - work/example.org/john@doe.org.gpg --> work (FileBased) + * - example.org/john@doe.org.gpg --> null (FileBased) + * - john@doe.org.gpg --> null (FileBased) + * - work/example.org/john@doe.org/password.gpg --> work (DirectoryBased) + * - example.org/john@doe.org/password.gpg --> null (DirectoryBased) + */ + fun getPathToIdentifierFor(file: File): String? = + when (this) { + EncryptedUsername -> file.parent + FileBased -> file.parentFile?.parent + DirectoryBased -> file.parentFile?.parentFile?.parent + } + + /** + * Returns the path component of [file] following the origin identifier according to the current + * [DirectoryStructure](without file extension). + * + * At least one of [DirectoryStructure.getIdentifierFor] and + * [DirectoryStructure.getAccountPartFor] will always return a non-null result. + * + * Examples: + * - * --> null (EncryptedUsername) + * - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased) + * - example.org.gpg --> null (FileBased, fallback) + * - work/example.org/john@doe.org/password.gpg --> john@doe.org/password (DirectoryBased) + * - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback) + */ + fun getAccountPartFor(file: File): String? = + when (this) { + EncryptedUsername -> null + FileBased -> file.nameWithoutExtension.takeIf { file.parentFile != null } + DirectoryBased -> + file.parentFile?.let { parentFile -> "${parentFile.name}/${file.nameWithoutExtension}" } + ?: file.nameWithoutExtension + } + + fun getSaveFolderName(sanitizedIdentifier: String, username: String?) = + when (this) { + EncryptedUsername -> "/" + FileBased -> sanitizedIdentifier + DirectoryBased -> Paths.get(sanitizedIdentifier, username ?: "username").toString() + } + + fun getSaveFileName(username: String?, identifier: String) = + when (this) { + EncryptedUsername -> identifier + FileBased -> username + DirectoryBased -> "password" + } + + companion object { + + val DEFAULT = FileBased + + private val reverseMap = entries.associateBy { it.value } + + fun fromValue(value: String?) = if (value != null) reverseMap[value] ?: DEFAULT else DEFAULT + } +} diff --git a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt index 06dfb631..ecc7a51c 100644 --- a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt +++ b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt @@ -56,7 +56,7 @@ object PreferenceKeys { const val LENGTH = "length" const val OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES = "oreo_autofill_custom_public_suffixes" const val OREO_AUTOFILL_DEFAULT_USERNAME = "oreo_autofill_default_username" - const val OREO_AUTOFILL_DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure" + const val DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure" const val PREF_KEY_PWGEN_TYPE = "pref_key_pwgen_type" const val REPOSITORY_INITIALIZED = "repository_initialized" const val REPO_CHANGED = "repo_changed" diff --git a/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt b/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt index c97102e3..2bd75aba 100644 --- a/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt +++ b/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt @@ -25,9 +25,9 @@ import app.passwordstore.data.password.PasswordItem import app.passwordstore.data.repo.PasswordRepository import app.passwordstore.injection.prefs.SettingsPreferences import app.passwordstore.util.autofill.AutofillPreferences -import app.passwordstore.util.autofill.DirectoryStructure import app.passwordstore.util.checkMainThread import app.passwordstore.util.coroutines.DispatcherProvider +import app.passwordstore.util.settings.DirectoryStructure import app.passwordstore.util.settings.PasswordSortOrder import app.passwordstore.util.settings.PreferenceKeys import com.github.androidpasswordstore.sublimefuzzy.Fuzzy |