refactor: move out GPG identifier parser to BasePgpActivity
This commit is contained in:
parent
136f4e5caa
commit
df58f484ac
2 changed files with 54 additions and 44 deletions
|
@ -18,7 +18,9 @@ import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
|
import app.passwordstore.crypto.GpgIdentifier
|
||||||
import app.passwordstore.data.crypto.CryptoRepository
|
import app.passwordstore.data.crypto.CryptoRepository
|
||||||
|
import app.passwordstore.data.repo.PasswordRepository
|
||||||
import app.passwordstore.injection.prefs.SettingsPreferences
|
import app.passwordstore.injection.prefs.SettingsPreferences
|
||||||
import app.passwordstore.ui.pgp.PGPKeyImportActivity
|
import app.passwordstore.ui.pgp.PGPKeyImportActivity
|
||||||
import app.passwordstore.util.coroutines.DispatcherProvider
|
import app.passwordstore.util.coroutines.DispatcherProvider
|
||||||
|
@ -150,6 +152,57 @@ open class BasePgpActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of available [GpgIdentifier]s for the current password repository. This method
|
||||||
|
* throws when no identifiers were able to be parsed. If this method returns null, it means that
|
||||||
|
* an invalid identifier was encountered and further execution must stop to let the user correct
|
||||||
|
* the problem.
|
||||||
|
*/
|
||||||
|
fun getGpgIdentifiers(subDir: String): List<GpgIdentifier>? {
|
||||||
|
val repoRoot = PasswordRepository.getRepositoryDirectory()
|
||||||
|
val gpgIdentifierFile =
|
||||||
|
File(repoRoot, subDir).findTillRoot(".gpg-id", repoRoot)
|
||||||
|
?: File(repoRoot, ".gpg-id").apply { createNewFile() }
|
||||||
|
val gpgIdentifiers =
|
||||||
|
gpgIdentifierFile
|
||||||
|
.readLines()
|
||||||
|
.filter { it.isNotBlank() }
|
||||||
|
.map { line ->
|
||||||
|
GpgIdentifier.fromString(line)
|
||||||
|
?: run {
|
||||||
|
// The line being empty means this is most likely an empty `.gpg-id`
|
||||||
|
// file we created. Skip the validation so we can make the user add a
|
||||||
|
// real ID.
|
||||||
|
if (line.isEmpty()) return@run
|
||||||
|
if (line.removePrefix("0x").matches("[a-fA-F0-9]{8}".toRegex()).not()) {
|
||||||
|
snackbar(message = resources.getString(R.string.invalid_gpg_id))
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filterIsInstance<GpgIdentifier>()
|
||||||
|
if (gpgIdentifiers.isEmpty()) {
|
||||||
|
error("Failed to parse identifiers from .gpg-id: ${gpgIdentifierFile.readText()}")
|
||||||
|
}
|
||||||
|
return gpgIdentifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("ReturnCount")
|
||||||
|
private fun File.findTillRoot(fileName: String, rootPath: File): File? {
|
||||||
|
val gpgFile = File(this, fileName)
|
||||||
|
if (gpgFile.exists()) return gpgFile
|
||||||
|
|
||||||
|
if (this.absolutePath == rootPath.absolutePath) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val parent = parentFile
|
||||||
|
return if (parent != null && parent.exists()) {
|
||||||
|
parent.findTillRoot(fileName, rootPath)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val EXTRA_FILE_PATH = "FILE_PATH"
|
const val EXTRA_FILE_PATH = "FILE_PATH"
|
||||||
|
|
|
@ -24,9 +24,7 @@ import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.crypto.GpgIdentifier
|
|
||||||
import app.passwordstore.data.passfile.PasswordEntry
|
import app.passwordstore.data.passfile.PasswordEntry
|
||||||
import app.passwordstore.data.repo.PasswordRepository
|
|
||||||
import app.passwordstore.databinding.PasswordCreationActivityBinding
|
import app.passwordstore.databinding.PasswordCreationActivityBinding
|
||||||
import app.passwordstore.ui.dialogs.DicewarePasswordGeneratorDialogFragment
|
import app.passwordstore.ui.dialogs.DicewarePasswordGeneratorDialogFragment
|
||||||
import app.passwordstore.ui.dialogs.OtpImportDialogFragment
|
import app.passwordstore.ui.dialogs.OtpImportDialogFragment
|
||||||
|
@ -333,31 +331,7 @@ class PasswordCreationActivity : BasePgpActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass enters the key ID into `.gpg-id`.
|
// pass enters the key ID into `.gpg-id`.
|
||||||
val repoRoot = PasswordRepository.getRepositoryDirectory()
|
val gpgIdentifiers = getGpgIdentifiers(directory.text.toString()) ?: return@with
|
||||||
val gpgIdentifierFile =
|
|
||||||
File(repoRoot, directory.text.toString()).findTillRoot(".gpg-id", repoRoot)
|
|
||||||
?: File(repoRoot, ".gpg-id").apply { createNewFile() }
|
|
||||||
val gpgIdentifiers =
|
|
||||||
gpgIdentifierFile
|
|
||||||
.readLines()
|
|
||||||
.filter { it.isNotBlank() }
|
|
||||||
.map { line ->
|
|
||||||
GpgIdentifier.fromString(line)
|
|
||||||
?: run {
|
|
||||||
// The line being empty means this is most likely an empty `.gpg-id`
|
|
||||||
// file we created. Skip the validation so we can make the user add a
|
|
||||||
// real ID.
|
|
||||||
if (line.isEmpty()) return@run
|
|
||||||
if (line.removePrefix("0x").matches("[a-fA-F0-9]{8}".toRegex()).not()) {
|
|
||||||
snackbar(message = resources.getString(R.string.invalid_gpg_id))
|
|
||||||
}
|
|
||||||
return@with
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.filterIsInstance<GpgIdentifier>()
|
|
||||||
if (gpgIdentifiers.isEmpty()) {
|
|
||||||
error("Failed to parse identifiers from .gpg-id: ${gpgIdentifierFile.readText()}")
|
|
||||||
}
|
|
||||||
val content = "$editPass\n$editExtra"
|
val content = "$editPass\n$editExtra"
|
||||||
val path =
|
val path =
|
||||||
when {
|
when {
|
||||||
|
@ -483,23 +457,6 @@ class PasswordCreationActivity : BasePgpActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("ReturnCount")
|
|
||||||
private fun File.findTillRoot(fileName: String, rootPath: File): File? {
|
|
||||||
val gpgFile = File(this, fileName)
|
|
||||||
if (gpgFile.exists()) return gpgFile
|
|
||||||
|
|
||||||
if (this.absolutePath == rootPath.absolutePath) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val parent = parentFile
|
|
||||||
return if (parent != null && parent.exists()) {
|
|
||||||
parent.findTillRoot(fileName, rootPath)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val KEY_PWGEN_TYPE_CLASSIC = "classic"
|
private const val KEY_PWGEN_TYPE_CLASSIC = "classic"
|
||||||
|
|
Loading…
Reference in a new issue