aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt166
1 files changed, 97 insertions, 69 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
index ea9ee654..78a9ca69 100644
--- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt
@@ -7,23 +7,24 @@ package com.zeapo.pwdstore.git
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
-import android.text.InputType
import android.view.LayoutInflater
-import android.view.View
-import android.widget.CheckBox
-import android.widget.EditText
-import android.widget.LinearLayout
+import androidx.core.content.edit
import androidx.preference.PreferenceManager
+import com.google.android.material.checkbox.MaterialCheckBox
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.textfield.TextInputEditText
import com.jcraft.jsch.JSch
import com.jcraft.jsch.JSchException
import com.jcraft.jsch.KeyPair
import com.zeapo.pwdstore.R
import com.zeapo.pwdstore.UserPreference
+import com.zeapo.pwdstore.git.config.ConnectionMode
import com.zeapo.pwdstore.git.config.GitConfigSessionFactory
import com.zeapo.pwdstore.git.config.SshApiSessionFactory
import com.zeapo.pwdstore.git.config.SshConfigSessionFactory
import com.zeapo.pwdstore.utils.PasswordRepository
+import com.zeapo.pwdstore.utils.getEncryptedPrefs
+import com.zeapo.pwdstore.utils.requestInputFocusOnView
import java.io.File
import org.eclipse.jgit.api.GitCommand
import org.eclipse.jgit.lib.Repository
@@ -96,7 +97,7 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit
* @param identity the api identity to use for auth in OpenKeychain connection mode
*/
fun executeAfterAuthentication(
- connectionMode: String,
+ connectionMode: ConnectionMode,
username: String,
sshKey: File?,
identity: SshApiSessionFactory.ApiIdentity?
@@ -114,15 +115,17 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit
* @param showError show the passphrase edit text in red
*/
private fun executeAfterAuthentication(
- connectionMode: String,
+ connectionMode: ConnectionMode,
username: String,
sshKey: File?,
identity: SshApiSessionFactory.ApiIdentity?,
showError: Boolean
) {
- if (connectionMode.equals("ssh-key", ignoreCase = true)) {
- if (sshKey == null || !sshKey.exists()) {
- MaterialAlertDialogBuilder(callingActivity)
+ val encryptedSettings = callingActivity.applicationContext.getEncryptedPrefs("git_operation")
+ when (connectionMode) {
+ ConnectionMode.SshKey -> {
+ if (sshKey == null || !sshKey.exists()) {
+ MaterialAlertDialogBuilder(callingActivity)
.setMessage(callingActivity.resources.getString(R.string.ssh_preferences_dialog_text))
.setTitle(callingActivity.resources.getString(R.string.ssh_preferences_dialog_title))
.setPositiveButton(callingActivity.resources.getString(R.string.ssh_preferences_dialog_import)) { _, _ ->
@@ -152,82 +155,100 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit
// Finish the blank GitActivity so user doesn't have to press back
callingActivity.finish()
}.show()
- } else {
- val layoutInflater = LayoutInflater.from(callingActivity.applicationContext)
- @SuppressLint("InflateParams") val dialogView = layoutInflater.inflate(R.layout.git_passphrase_layout, null)
- val passphrase = dialogView.findViewById<EditText>(R.id.sshkey_passphrase)
- val settings = PreferenceManager.getDefaultSharedPreferences(callingActivity.applicationContext)
- val sshKeyPassphrase = settings.getString("ssh_key_passphrase", null)
- if (showError) {
- passphrase.error = "Wrong passphrase"
- }
- val jsch = JSch()
- try {
- val keyPair = KeyPair.load(jsch, callingActivity.filesDir.toString() + "/.ssh_key")
+ } else {
+ val layoutInflater = LayoutInflater.from(callingActivity)
+ @SuppressLint("InflateParams") val dialogView = layoutInflater.inflate(R.layout.git_passphrase_layout, null)
+ val passphrase = dialogView.findViewById<TextInputEditText>(R.id.git_auth_passphrase)
+ val sshKeyPassphrase = encryptedSettings.getString("ssh_key_local_passphrase", null)
+ if (showError) {
+ passphrase.error = callingActivity.resources.getString(R.string.git_operation_wrong_passphrase)
+ }
+ val jsch = JSch()
+ try {
+ val keyPair = KeyPair.load(jsch, callingActivity.filesDir.toString() + "/.ssh_key")
- if (keyPair.isEncrypted) {
- if (sshKeyPassphrase != null && sshKeyPassphrase.isNotEmpty()) {
- if (keyPair.decrypt(sshKeyPassphrase)) {
- // Authenticate using the ssh-key and then execute the command
- setAuthentication(sshKey, username, sshKeyPassphrase).execute()
+ if (keyPair.isEncrypted) {
+ if (sshKeyPassphrase != null && sshKeyPassphrase.isNotEmpty()) {
+ if (keyPair.decrypt(sshKeyPassphrase)) {
+ // Authenticate using the ssh-key and then execute the command
+ setAuthentication(sshKey, username, sshKeyPassphrase).execute()
+ } else {
+ // call back the method
+ executeAfterAuthentication(connectionMode, username, sshKey, identity, true)
+ }
} else {
- // call back the method
- executeAfterAuthentication(connectionMode, username, sshKey, identity, true)
- }
- } else {
- MaterialAlertDialogBuilder(callingActivity)
+ val dialog = MaterialAlertDialogBuilder(callingActivity)
.setTitle(callingActivity.resources.getString(R.string.passphrase_dialog_title))
.setMessage(callingActivity.resources.getString(R.string.passphrase_dialog_text))
.setView(dialogView)
.setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ ->
if (keyPair.decrypt(passphrase.text.toString())) {
- val rememberPassphrase = (dialogView.findViewById<View>(R.id.sshkey_remember_passphrase) as CheckBox).isChecked
+ val rememberPassphrase = dialogView.findViewById<MaterialCheckBox>(R.id.git_auth_remember_passphrase).isChecked
if (rememberPassphrase) {
- settings.edit().putString("ssh_key_passphrase", passphrase.text.toString()).apply()
+ encryptedSettings.edit().putString("ssh_key_local_passphrase", passphrase.text.toString()).apply()
}
// Authenticate using the ssh-key and then execute the command
setAuthentication(sshKey, username, passphrase.text.toString()).execute()
} else {
- settings.edit().putString("ssh_key_passphrase", null).apply()
+ encryptedSettings.edit().putString("ssh_key_local_passphrase", null).apply()
// call back the method
executeAfterAuthentication(connectionMode, username, sshKey, identity, true)
}
- }.setNegativeButton(callingActivity.resources.getString(R.string.dialog_cancel)) { _, _ ->
- // Do nothing.
- }.show()
+ }
+ .setNegativeButton(callingActivity.resources.getString(R.string.dialog_cancel)) { _, _ ->
+ callingActivity.finish()
+ }
+ .setOnCancelListener { callingActivity.finish() }
+ .create()
+ dialog.requestInputFocusOnView<TextInputEditText>(R.id.git_auth_passphrase)
+ dialog.show()
+ }
+ } else {
+ setAuthentication(sshKey, username, "").execute()
}
- } else {
- setAuthentication(sshKey, username, "").execute()
- }
- } catch (e: JSchException) {
- e.printStackTrace()
- MaterialAlertDialogBuilder(callingActivity)
- .setTitle("Unable to open the ssh-key")
- .setMessage("Please check that it was imported.")
- .setPositiveButton("Ok") { _, _ -> callingActivity.finish() }
+ } catch (e: JSchException) {
+ e.printStackTrace()
+ MaterialAlertDialogBuilder(callingActivity)
+ .setTitle(callingActivity.resources.getString(R.string.git_operation_unable_to_open_ssh_key_title))
+ .setMessage(callingActivity.resources.getString(R.string.git_operation_unable_to_open_ssh_key_message))
+ .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ ->
+ callingActivity.finish()
+ }
.show()
+ }
+ }
+ }
+ ConnectionMode.OpenKeychain -> {
+ setAuthentication(username, identity).execute()
+ }
+ ConnectionMode.Password -> {
+ @SuppressLint("InflateParams") val dialogView = callingActivity.layoutInflater.inflate(R.layout.git_passphrase_layout, null)
+ val passwordView = dialogView.findViewById<TextInputEditText>(R.id.git_auth_passphrase)
+ val password = encryptedSettings.getString("https_password", null)
+ if (password != null && password.isNotEmpty()) {
+ setAuthentication(username, password).execute()
+ } else {
+ val dialog = MaterialAlertDialogBuilder(callingActivity)
+ .setTitle(callingActivity.resources.getString(R.string.passphrase_dialog_title))
+ .setMessage(callingActivity.resources.getString(R.string.password_dialog_text))
+ .setView(dialogView)
+ .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ ->
+ val rememberPassphrase = dialogView.findViewById<MaterialCheckBox>(R.id.git_auth_remember_passphrase).isChecked
+ if (rememberPassphrase) {
+ encryptedSettings.edit().putString("https_password", passwordView.text.toString()).apply()
+ }
+ // authenticate using the user/pwd and then execute the command
+ setAuthentication(username, passwordView.text.toString()).execute()
+ }
+ .setNegativeButton(callingActivity.resources.getString(R.string.dialog_cancel)) { _, _ ->
+ callingActivity.finish()
+ }
+ .setOnCancelListener { callingActivity.finish() }
+ .create()
+ dialog.requestInputFocusOnView<TextInputEditText>(R.id.git_auth_passphrase)
+ dialog.show()
}
}
- } else if (connectionMode.equals("OpenKeychain", ignoreCase = true)) {
- setAuthentication(username, identity).execute()
- } else {
- val password = EditText(callingActivity)
- password.hint = "Password"
- password.width = LinearLayout.LayoutParams.MATCH_PARENT
- password.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
-
- MaterialAlertDialogBuilder(callingActivity)
- .setTitle(callingActivity.resources.getString(R.string.passphrase_dialog_title))
- .setMessage(callingActivity.resources.getString(R.string.password_dialog_text))
- .setView(password)
- .setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ ->
- // authenticate using the user/pwd and then execute the command
- setAuthentication(username, password.text.toString()).execute()
- }
- .setNegativeButton(callingActivity.resources.getString(R.string.dialog_cancel)) { _, _ ->
- callingActivity.finish()
- }
- .show()
}
}
@@ -235,10 +256,17 @@ abstract class GitOperation(fileDir: File, internal val callingActivity: Activit
* Action to execute on error
*/
open fun onError(errorMessage: String) {
+ // Clear various auth related fields on failure
if (SshSessionFactory.getInstance() is SshApiSessionFactory) {
- // Clear stored key id from settings on auth failure
PreferenceManager.getDefaultSharedPreferences(callingActivity.applicationContext)
- .edit().putString("ssh_openkeystore_keyid", null).apply()
+ .edit { putString("ssh_openkeystore_keyid", null) }
+ callingActivity.applicationContext
+ .getEncryptedPrefs("git_operation")
+ .edit { remove("ssh_key_local_passphrase") }
+ } else if (SshSessionFactory.getInstance() is GitConfigSessionFactory) {
+ callingActivity.applicationContext
+ .getEncryptedPrefs("git_operation")
+ .edit { remove("https_password") }
}
}