From 549ee790d3e52bc62565ddf92e6a556e98b5195e Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Fri, 15 Jul 2022 00:53:48 +0530 Subject: all: re-do package structure yet again --- .../dev/msfjarvis/aps/util/settings/GitSettings.kt | 186 --------------------- .../dev/msfjarvis/aps/util/settings/Migrations.kt | 154 ----------------- .../aps/util/settings/PasswordSortOrder.kt | 53 ------ .../msfjarvis/aps/util/settings/PreferenceKeys.kt | 88 ---------- 4 files changed, 481 deletions(-) delete mode 100644 app/src/main/java/dev/msfjarvis/aps/util/settings/GitSettings.kt delete mode 100644 app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt delete mode 100644 app/src/main/java/dev/msfjarvis/aps/util/settings/PasswordSortOrder.kt delete mode 100644 app/src/main/java/dev/msfjarvis/aps/util/settings/PreferenceKeys.kt (limited to 'app/src/main/java/dev/msfjarvis/aps/util/settings') diff --git a/app/src/main/java/dev/msfjarvis/aps/util/settings/GitSettings.kt b/app/src/main/java/dev/msfjarvis/aps/util/settings/GitSettings.kt deleted file mode 100644 index 4f5187c4..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/settings/GitSettings.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package dev.msfjarvis.aps.util.settings - -import android.content.SharedPreferences -import androidx.core.content.edit -import com.github.michaelbull.result.getOrElse -import com.github.michaelbull.result.runCatching -import dev.msfjarvis.aps.data.repo.PasswordRepository -import dev.msfjarvis.aps.injection.context.FilesDirPath -import dev.msfjarvis.aps.injection.prefs.GitPreferences -import dev.msfjarvis.aps.injection.prefs.ProxyPreferences -import dev.msfjarvis.aps.injection.prefs.SettingsPreferences -import dev.msfjarvis.aps.util.extensions.getString -import java.io.File -import javax.inject.Inject -import javax.inject.Singleton -import org.eclipse.jgit.transport.URIish - -enum class Protocol(val pref: String) { - Ssh("ssh://"), - Https("https://"), - ; - - companion object { - - private val map = values().associateBy(Protocol::pref) - fun fromString(type: String?): Protocol { - return map[type ?: return Ssh] - ?: throw IllegalArgumentException("$type is not a valid Protocol") - } - } -} - -enum class AuthMode(val pref: String) { - SshKey("ssh-key"), - Password("username/password"), - OpenKeychain("OpenKeychain"), - None("None"), - ; - - companion object { - - private val map = values().associateBy(AuthMode::pref) - fun fromString(type: String?): AuthMode { - return map[type ?: return SshKey] - ?: throw IllegalArgumentException("$type is not a valid AuthMode") - } - } -} - -@Singleton -class GitSettings -@Inject -constructor( - @SettingsPreferences private val settings: SharedPreferences, - @GitPreferences private val encryptedSettings: SharedPreferences, - @ProxyPreferences private val proxySettings: SharedPreferences, - @FilesDirPath private val filesDirPath: String, -) { - - private val hostKeyPath = "$filesDirPath/.host_key" - var authMode - get() = AuthMode.fromString(settings.getString(PreferenceKeys.GIT_REMOTE_AUTH)) - private set(value) { - settings.edit { putString(PreferenceKeys.GIT_REMOTE_AUTH, value.pref) } - } - var url - get() = settings.getString(PreferenceKeys.GIT_REMOTE_URL) - private set(value) { - require(value != null) - if (value == url) return - settings.edit { putString(PreferenceKeys.GIT_REMOTE_URL, value) } - if (PasswordRepository.isInitialized) PasswordRepository.addRemote("origin", value, true) - // When the server changes, remote password, multiplexing support and host key file - // should be deleted/reset. - useMultiplexing = true - encryptedSettings.edit { remove(PreferenceKeys.HTTPS_PASSWORD) } - clearSavedHostKey() - } - var authorName - get() = settings.getString(PreferenceKeys.GIT_CONFIG_AUTHOR_NAME) ?: "" - set(value) { - settings.edit { putString(PreferenceKeys.GIT_CONFIG_AUTHOR_NAME, value) } - } - var authorEmail - get() = settings.getString(PreferenceKeys.GIT_CONFIG_AUTHOR_EMAIL) ?: "" - set(value) { - settings.edit { putString(PreferenceKeys.GIT_CONFIG_AUTHOR_EMAIL, value) } - } - var branch - get() = settings.getString(PreferenceKeys.GIT_BRANCH_NAME) ?: DEFAULT_BRANCH - private set(value) { - settings.edit { putString(PreferenceKeys.GIT_BRANCH_NAME, value) } - } - var useMultiplexing - get() = settings.getBoolean(PreferenceKeys.GIT_REMOTE_USE_MULTIPLEXING, true) - set(value) { - settings.edit { putBoolean(PreferenceKeys.GIT_REMOTE_USE_MULTIPLEXING, value) } - } - var proxyHost - get() = proxySettings.getString(PreferenceKeys.PROXY_HOST) - set(value) { - proxySettings.edit { putString(PreferenceKeys.PROXY_HOST, value) } - } - var proxyPort - get() = proxySettings.getInt(PreferenceKeys.PROXY_PORT, -1) - set(value) { - proxySettings.edit { putInt(PreferenceKeys.PROXY_PORT, value) } - } - var proxyUsername - get() = settings.getString(PreferenceKeys.PROXY_USERNAME) - set(value) { - proxySettings.edit { putString(PreferenceKeys.PROXY_USERNAME, value) } - } - var proxyPassword - get() = proxySettings.getString(PreferenceKeys.PROXY_PASSWORD) - set(value) { - proxySettings.edit { putString(PreferenceKeys.PROXY_PASSWORD, value) } - } - var rebaseOnPull - get() = settings.getBoolean(PreferenceKeys.REBASE_ON_PULL, true) - set(value) { - settings.edit { putBoolean(PreferenceKeys.REBASE_ON_PULL, value) } - } - - sealed class UpdateConnectionSettingsResult { - class MissingUsername(val newProtocol: Protocol) : UpdateConnectionSettingsResult() - class AuthModeMismatch(val newProtocol: Protocol, val validModes: List) : - UpdateConnectionSettingsResult() - object Valid : UpdateConnectionSettingsResult() - object FailedToParseUrl : UpdateConnectionSettingsResult() - } - - fun updateConnectionSettingsIfValid( - newAuthMode: AuthMode, - newUrl: String, - newBranch: String - ): UpdateConnectionSettingsResult { - val parsedUrl = - runCatching { URIish(newUrl) } - .getOrElse { - return UpdateConnectionSettingsResult.FailedToParseUrl - } - val newProtocol = - when (parsedUrl.scheme) { - in listOf("http", "https") -> Protocol.Https - in listOf("ssh", null) -> Protocol.Ssh - else -> return UpdateConnectionSettingsResult.FailedToParseUrl - } - if ( - (newAuthMode != AuthMode.None && newProtocol != Protocol.Https) && - parsedUrl.user.isNullOrBlank() - ) - return UpdateConnectionSettingsResult.MissingUsername(newProtocol) - val validHttpsAuth = listOf(AuthMode.None, AuthMode.Password) - val validSshAuth = listOf(AuthMode.OpenKeychain, AuthMode.Password, AuthMode.SshKey) - when { - newProtocol == Protocol.Https && newAuthMode !in validHttpsAuth -> { - return UpdateConnectionSettingsResult.AuthModeMismatch(newProtocol, validHttpsAuth) - } - newProtocol == Protocol.Ssh && newAuthMode !in validSshAuth -> { - return UpdateConnectionSettingsResult.AuthModeMismatch(newProtocol, validSshAuth) - } - } - - url = newUrl - authMode = newAuthMode - branch = newBranch - return UpdateConnectionSettingsResult.Valid - } - - /** Deletes a previously saved SSH host key */ - fun clearSavedHostKey() { - File(hostKeyPath).delete() - } - - /** Returns true if a host key was previously saved */ - fun hasSavedHostKey(): Boolean = File(hostKeyPath).exists() - - companion object { - private const val DEFAULT_BRANCH = "master" - } -} diff --git a/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt b/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt deleted file mode 100644 index 7e91ab41..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -@file:Suppress("DEPRECATION") - -package dev.msfjarvis.aps.util.settings - -import android.content.SharedPreferences -import androidx.core.content.edit -import com.github.michaelbull.result.get -import com.github.michaelbull.result.runCatching -import dev.msfjarvis.aps.util.extensions.getString -import dev.msfjarvis.aps.util.git.sshj.SshKey -import java.io.File -import java.net.URI -import logcat.LogPriority.ERROR -import logcat.LogPriority.INFO -import logcat.logcat - -private const val TAG = "Migrations" - -fun runMigrations(filesDirPath: String, sharedPrefs: SharedPreferences, gitSettings: GitSettings) { - migrateToGitUrlBasedConfig(sharedPrefs, gitSettings) - migrateToHideAll(sharedPrefs) - migrateToSshKey(filesDirPath, sharedPrefs) - migrateToClipboardHistory(sharedPrefs) - migrateToDiceware(sharedPrefs) - removeExternalStorageProperties(sharedPrefs) -} - -private fun migrateToGitUrlBasedConfig(sharedPrefs: SharedPreferences, gitSettings: GitSettings) { - val serverHostname = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_SERVER) ?: return - logcat(TAG, INFO) { "Migrating to URL-based Git config" } - val serverPort = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_PORT) ?: "" - val serverUser = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_USERNAME) ?: "" - val serverPath = sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_LOCATION) ?: "" - val protocol = Protocol.fromString(sharedPrefs.getString(PreferenceKeys.GIT_REMOTE_PROTOCOL)) - - // Whether we need the leading ssh:// depends on the use of a custom port. - val hostnamePart = serverHostname.removePrefix("ssh://") - val url = - when (protocol) { - Protocol.Ssh -> { - val userPart = if (serverUser.isEmpty()) "" else "${serverUser.trimEnd('@')}@" - val portPart = if (serverPort == "22" || serverPort.isEmpty()) "" else ":$serverPort" - if (portPart.isEmpty()) { - "$userPart$hostnamePart:$serverPath" - } else { - // Only absolute paths are supported with custom ports. - if (!serverPath.startsWith('/')) { - null - } else { - // We have to specify the ssh scheme as this is the only way to pass a custom - // port. - "ssh://$userPart$hostnamePart$portPart$serverPath" - } - } - } - Protocol.Https -> { - val portPart = if (serverPort == "443" || serverPort.isEmpty()) "" else ":$serverPort" - val pathPart = serverPath.trimStart('/', ':') - val urlWithFreeEntryScheme = "$hostnamePart$portPart/$pathPart" - val url = - when { - urlWithFreeEntryScheme.startsWith("https://") -> urlWithFreeEntryScheme - urlWithFreeEntryScheme.startsWith("http://") -> - urlWithFreeEntryScheme.replaceFirst("http", "https") - else -> "https://$urlWithFreeEntryScheme" - } - runCatching { if (URI(url).rawAuthority != null) url else null }.get() - } - } - - sharedPrefs.edit { - remove(PreferenceKeys.GIT_REMOTE_LOCATION) - remove(PreferenceKeys.GIT_REMOTE_PORT) - remove(PreferenceKeys.GIT_REMOTE_SERVER) - remove(PreferenceKeys.GIT_REMOTE_USERNAME) - remove(PreferenceKeys.GIT_REMOTE_PROTOCOL) - } - if ( - url == null || - gitSettings.updateConnectionSettingsIfValid( - newAuthMode = gitSettings.authMode, - newUrl = url, - newBranch = gitSettings.branch - ) != GitSettings.UpdateConnectionSettingsResult.Valid - ) { - logcat(TAG, ERROR) { "Failed to migrate to URL-based Git config, generated URL is invalid" } - } -} - -private fun migrateToHideAll(sharedPrefs: SharedPreferences) { - sharedPrefs.all[PreferenceKeys.SHOW_HIDDEN_FOLDERS] ?: return - val isHidden = sharedPrefs.getBoolean(PreferenceKeys.SHOW_HIDDEN_FOLDERS, false) - sharedPrefs.edit { - remove(PreferenceKeys.SHOW_HIDDEN_FOLDERS) - putBoolean(PreferenceKeys.SHOW_HIDDEN_CONTENTS, isHidden) - } -} - -private fun migrateToSshKey(filesDirPath: String, sharedPrefs: SharedPreferences) { - val privateKeyFile = File(filesDirPath, ".ssh_key") - if ( - sharedPrefs.contains(PreferenceKeys.USE_GENERATED_KEY) && - !SshKey.exists && - privateKeyFile.exists() - ) { - // Currently uses a private key imported or generated with an old version of Password Store. - // Generated keys come with a public key which the user should still be able to view after - // the migration (not possible for regular imported keys), hence the special case. - val isGeneratedKey = sharedPrefs.getBoolean(PreferenceKeys.USE_GENERATED_KEY, false) - SshKey.useLegacyKey(isGeneratedKey) - sharedPrefs.edit { remove(PreferenceKeys.USE_GENERATED_KEY) } - } -} - -private fun migrateToClipboardHistory(sharedPrefs: SharedPreferences) { - if (sharedPrefs.contains(PreferenceKeys.CLEAR_CLIPBOARD_20X)) { - sharedPrefs.edit { - putBoolean( - PreferenceKeys.CLEAR_CLIPBOARD_HISTORY, - sharedPrefs.getBoolean(PreferenceKeys.CLEAR_CLIPBOARD_20X, false) - ) - remove(PreferenceKeys.CLEAR_CLIPBOARD_20X) - } - } -} - -private fun migrateToDiceware(sharedPrefs: SharedPreferences) { - if (sharedPrefs.contains(PreferenceKeys.PREF_KEY_PWGEN_TYPE)) { - sharedPrefs.edit { - if (sharedPrefs.getString(PreferenceKeys.PREF_KEY_PWGEN_TYPE) == "xkpasswd") { - putString(PreferenceKeys.PREF_KEY_PWGEN_TYPE, "diceware") - } - } - } -} - -private fun removeExternalStorageProperties(prefs: SharedPreferences) { - logcat(TAG, INFO) { "Removing preferences related to external storage" } - prefs.edit { - if (prefs.contains(PreferenceKeys.GIT_EXTERNAL)) { - if (prefs.getBoolean(PreferenceKeys.GIT_EXTERNAL, false)) { - putBoolean(PreferenceKeys.GIT_EXTERNAL_MIGRATED, true) - } - remove(PreferenceKeys.GIT_EXTERNAL) - } - if (prefs.contains(PreferenceKeys.GIT_EXTERNAL_REPO)) { - remove(PreferenceKeys.GIT_EXTERNAL_REPO) - } - } -} diff --git a/app/src/main/java/dev/msfjarvis/aps/util/settings/PasswordSortOrder.kt b/app/src/main/java/dev/msfjarvis/aps/util/settings/PasswordSortOrder.kt deleted file mode 100644 index 6b48b6a9..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/settings/PasswordSortOrder.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package dev.msfjarvis.aps.util.settings - -import android.content.Context -import android.content.SharedPreferences -import dev.msfjarvis.aps.Application -import dev.msfjarvis.aps.data.password.PasswordItem -import dev.msfjarvis.aps.util.extensions.base64 -import dev.msfjarvis.aps.util.extensions.getString - -enum class PasswordSortOrder(val comparator: java.util.Comparator) { - FOLDER_FIRST( - Comparator { p1: PasswordItem, p2: PasswordItem -> - (p1.type + p1.name).compareTo(p2.type + p2.name, ignoreCase = true) - } - ), - INDEPENDENT( - Comparator { p1: PasswordItem, p2: PasswordItem -> - p1.name.compareTo(p2.name, ignoreCase = true) - } - ), - RECENTLY_USED( - Comparator { p1: PasswordItem, p2: PasswordItem -> - val recentHistory = - Application.instance.getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) - val timeP1 = recentHistory.getString(p1.file.absolutePath.base64()) - val timeP2 = recentHistory.getString(p2.file.absolutePath.base64()) - when { - timeP1 != null && timeP2 != null -> timeP2.compareTo(timeP1) - timeP1 != null && timeP2 == null -> return@Comparator -1 - timeP1 == null && timeP2 != null -> return@Comparator 1 - else -> p1.name.compareTo(p2.name, ignoreCase = true) - } - } - ), - FILE_FIRST( - Comparator { p1: PasswordItem, p2: PasswordItem -> - (p2.type + p1.name).compareTo(p1.type + p2.name, ignoreCase = true) - } - ); - - companion object { - - @JvmStatic - fun getSortOrder(settings: SharedPreferences): PasswordSortOrder { - return valueOf(settings.getString(PreferenceKeys.SORT_ORDER) ?: FOLDER_FIRST.name) - } - } -} diff --git a/app/src/main/java/dev/msfjarvis/aps/util/settings/PreferenceKeys.kt b/app/src/main/java/dev/msfjarvis/aps/util/settings/PreferenceKeys.kt deleted file mode 100644 index 7f4e0daf..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/settings/PreferenceKeys.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package dev.msfjarvis.aps.util.settings - -object PreferenceKeys { - - const val APP_THEME = "app_theme" - const val AUTOFILL_ENABLE = "autofill_enable" - const val BIOMETRIC_AUTH = "biometric_auth" - @Deprecated( - message = "Use CLEAR_CLIPBOARD_HISTORY instead", - replaceWith = ReplaceWith("PreferenceKeys.CLEAR_CLIPBOARD_HISTORY"), - ) - const val CLEAR_CLIPBOARD_20X = "clear_clipboard_20x" - const val CLEAR_CLIPBOARD_HISTORY = "clear_clipboard_history" - const val CLEAR_SAVED_PASS = "clear_saved_pass" - const val COPY_ON_DECRYPT = "copy_on_decrypt" - const val ENABLE_DEBUG_LOGGING = "enable_debug_logging" - const val EXPORT_PASSWORDS = "export_passwords" - const val FILTER_RECURSIVELY = "filter_recursively" - const val GENERAL_SHOW_TIME = "general_show_time" - const val GIT_CONFIG = "git_config" - const val GIT_CONFIG_AUTHOR_EMAIL = "git_config_user_email" - const val GIT_CONFIG_AUTHOR_NAME = "git_config_user_name" - @Deprecated(message = "We're removing support for external storage") - const val GIT_EXTERNAL = "git_external" - @Deprecated(message = "We're removing support for external storage") - const val GIT_EXTERNAL_REPO = "git_external_repo" - const val GIT_EXTERNAL_MIGRATED = "git_external_migrated" - const val GIT_REMOTE_AUTH = "git_remote_auth" - const val GIT_REMOTE_KEY_TYPE = "git_remote_key_type" - - @Deprecated("Use GIT_REMOTE_URL instead") const val GIT_REMOTE_LOCATION = "git_remote_location" - const val GIT_REMOTE_USE_MULTIPLEXING = "git_remote_use_multiplexing" - - @Deprecated("Use GIT_REMOTE_URL instead") const val GIT_REMOTE_PORT = "git_remote_port" - - @Deprecated("Use GIT_REMOTE_URL instead") const val GIT_REMOTE_PROTOCOL = "git_remote_protocol" - const val GIT_DELETE_REPO = "git_delete_repo" - - @Deprecated("Use GIT_REMOTE_URL instead") const val GIT_REMOTE_SERVER = "git_remote_server" - const val GIT_REMOTE_URL = "git_remote_url" - - @Deprecated("Use GIT_REMOTE_URL instead") const val GIT_REMOTE_USERNAME = "git_remote_username" - const val GIT_SERVER_INFO = "git_server_info" - const val GIT_BRANCH_NAME = "git_branch" - const val HTTPS_PASSWORD = "https_password" - 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 PREF_KEY_PWGEN_TYPE = "pref_key_pwgen_type" - const val REPOSITORY_INITIALIZED = "repository_initialized" - const val REPO_CHANGED = "repo_changed" - const val SEARCH_ON_START = "search_on_start" - - @Deprecated( - message = "Use SHOW_HIDDEN_CONTENTS instead", - replaceWith = ReplaceWith("PreferenceKeys.SHOW_HIDDEN_CONTENTS") - ) - const val SHOW_HIDDEN_FOLDERS = "show_hidden_folders" - const val SHOW_HIDDEN_CONTENTS = "show_hidden_contents" - const val SORT_ORDER = "sort_order" - const val SHOW_PASSWORD = "show_password" - const val SSH_KEY = "ssh_key" - const val SSH_KEYGEN = "ssh_keygen" - const val SSH_KEY_LOCAL_PASSPHRASE = "ssh_key_local_passphrase" - const val SSH_OPENKEYSTORE_CLEAR_KEY_ID = "ssh_openkeystore_clear_keyid" - const val SSH_OPENKEYSTORE_KEYID = "ssh_openkeystore_keyid" - const val SSH_SEE_KEY = "ssh_see_key" - - @Deprecated("To be used only in Migrations.kt") const val USE_GENERATED_KEY = "use_generated_key" - - const val PROXY_SETTINGS = "proxy_settings" - const val PROXY_HOST = "proxy_host" - const val PROXY_PORT = "proxy_port" - const val PROXY_USERNAME = "proxy_username" - const val PROXY_PASSWORD = "proxy_password" - - const val REBASE_ON_PULL = "rebase_on_pull" - - const val DICEWARE_SEPARATOR = "diceware_separator" - const val DICEWARE_LENGTH = "diceware_length" - const val DISABLE_SYNC_ACTION = "disable_sync_action" -} -- cgit v1.2.3