aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/dev/msfjarvis/aps/util/settings
diff options
context:
space:
mode:
authorHarsh Shandilya <me@msfjarvis.dev>2022-07-15 00:53:48 +0530
committerHarsh Shandilya <me@msfjarvis.dev>2022-07-15 01:13:47 +0530
commit549ee790d3e52bc62565ddf92e6a556e98b5195e (patch)
treed5758e5eb80093704e683c8da926838e18182588 /app/src/main/java/dev/msfjarvis/aps/util/settings
parent010c6e227c9cc27f4d01bc912311f977b2aeb3a7 (diff)
downloadHardenedPass-549ee790d3e52bc62565ddf92e6a556e98b5195e.tar.gz
HardenedPass-549ee790d3e52bc62565ddf92e6a556e98b5195e.zip
all: re-do package structure yet again
Diffstat (limited to 'app/src/main/java/dev/msfjarvis/aps/util/settings')
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/settings/GitSettings.kt186
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/settings/Migrations.kt154
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/settings/PasswordSortOrder.kt53
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/settings/PreferenceKeys.kt88
4 files changed, 0 insertions, 481 deletions
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<AuthMode>) :
- 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<PasswordItem>) {
- 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"
-}