diff options
| author | Harsh Shandilya <msfjarvis@gmail.com> | 2020-08-05 19:02:24 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-05 19:02:24 +0530 |
| commit | 14c44bf584cb7d13ada46b264419efca923ed65c (patch) | |
| tree | b22c8a9a7be7934927ed20fa9b2060c877953082 /app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt | |
| parent | 12a83e5c36b82e42dda6a58248e2879fde9c3ac8 (diff) | |
| download | HardenedPass-14c44bf584cb7d13ada46b264419efca923ed65c.tar.gz HardenedPass-14c44bf584cb7d13ada46b264419efca923ed65c.zip | |
Remove GitAsyncTask and replace with non-blocking coroutines (#865)
Co-authored-by: Fabian Henneke <fabian@henneke.me>
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.kt | 250 |
1 files changed, 0 insertions, 250 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 deleted file mode 100644 index 90f72b7c..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.kt +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.git - -import android.annotation.SuppressLint -import android.content.Intent -import android.view.LayoutInflater -import androidx.annotation.StringRes -import androidx.appcompat.app.AppCompatActivity -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.google.android.material.textfield.TextInputLayout -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.UserPreference -import com.zeapo.pwdstore.git.config.ConnectionMode -import com.zeapo.pwdstore.git.config.InteractivePasswordFinder -import com.zeapo.pwdstore.git.config.SshApiSessionFactory -import com.zeapo.pwdstore.git.config.SshAuthData -import com.zeapo.pwdstore.git.config.SshjSessionFactory -import com.zeapo.pwdstore.utils.PasswordRepository -import com.zeapo.pwdstore.utils.PreferenceKeys -import com.zeapo.pwdstore.utils.getEncryptedPrefs -import com.zeapo.pwdstore.utils.requestInputFocusOnView -import java.io.File -import kotlin.coroutines.Continuation -import kotlin.coroutines.resume -import net.schmizz.sshj.userauth.password.PasswordFinder -import org.eclipse.jgit.api.GitCommand -import org.eclipse.jgit.errors.UnsupportedCredentialItem -import org.eclipse.jgit.lib.Repository -import org.eclipse.jgit.transport.CredentialItem -import org.eclipse.jgit.transport.CredentialsProvider -import org.eclipse.jgit.transport.SshSessionFactory -import org.eclipse.jgit.transport.URIish - - -private class GitOperationCredentialFinder( - val callingActivity: AppCompatActivity, - val connectionMode: ConnectionMode -) : InteractivePasswordFinder() { - - override fun askForPassword(cont: Continuation<String?>, isRetry: Boolean) { - val gitOperationPrefs = callingActivity.getEncryptedPrefs("git_operation") - val credentialPref: String - @StringRes val messageRes: Int - @StringRes val hintRes: Int - @StringRes val rememberRes: Int - @StringRes val errorRes: Int - when (connectionMode) { - ConnectionMode.SshKey -> { - credentialPref = PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE - messageRes = R.string.passphrase_dialog_text - hintRes = R.string.ssh_keygen_passphrase - rememberRes = R.string.git_operation_remember_passphrase - errorRes = R.string.git_operation_wrong_passphrase - } - ConnectionMode.Password -> { - // Could be either an SSH or an HTTPS password - credentialPref = PreferenceKeys.HTTPS_PASSWORD - messageRes = R.string.password_dialog_text - hintRes = R.string.git_operation_hint_password - rememberRes = R.string.git_operation_remember_password - errorRes = R.string.git_operation_wrong_password - } - else -> throw IllegalStateException("Only SshKey and Password connection mode ask for passwords") - } - val storedCredential = gitOperationPrefs.getString(credentialPref, null) - if (isRetry) - gitOperationPrefs.edit { remove(credentialPref) } - if (storedCredential == null) { - val layoutInflater = LayoutInflater.from(callingActivity) - - @SuppressLint("InflateParams") - val dialogView = layoutInflater.inflate(R.layout.git_credential_layout, null) - val credentialLayout = dialogView.findViewById<TextInputLayout>(R.id.git_auth_passphrase_layout) - val editCredential = dialogView.findViewById<TextInputEditText>(R.id.git_auth_credential) - editCredential.setHint(hintRes) - val rememberCredential = dialogView.findViewById<MaterialCheckBox>(R.id.git_auth_remember_credential) - rememberCredential.setText(rememberRes) - if (isRetry) - credentialLayout.error = callingActivity.resources.getString(errorRes) - MaterialAlertDialogBuilder(callingActivity).run { - setTitle(R.string.passphrase_dialog_title) - setMessage(messageRes) - setView(dialogView) - setPositiveButton(R.string.dialog_ok) { _, _ -> - val credential = editCredential.text.toString() - if (rememberCredential.isChecked) { - gitOperationPrefs.edit { - putString(credentialPref, credential) - } - } - cont.resume(credential) - } - setNegativeButton(R.string.dialog_cancel) { _, _ -> - cont.resume(null) - } - setOnCancelListener { - cont.resume(null) - } - create() - }.run { - requestInputFocusOnView<TextInputEditText>(R.id.git_auth_credential) - show() - } - } else { - cont.resume(storedCredential) - } - } -} - -/** - * Creates a new git operation - * - * @param gitDir the git working tree directory - * @param callingActivity the calling activity - */ -abstract class GitOperation(gitDir: File, internal val callingActivity: AppCompatActivity) { - - protected val repository: Repository? = PasswordRepository.getRepository(gitDir) - internal var provider: CredentialsProvider? = null - internal var command: GitCommand<*>? = null - private val sshKeyFile = callingActivity.filesDir.resolve(".ssh_key") - private val hostKeyFile = callingActivity.filesDir.resolve(".host_key") - - private class PasswordFinderCredentialsProvider(private val username: String, private val passwordFinder: PasswordFinder) : CredentialsProvider() { - - override fun isInteractive() = true - - override fun get(uri: URIish?, vararg items: CredentialItem): Boolean { - for (item in items) { - when (item) { - is CredentialItem.Username -> item.value = username - is CredentialItem.Password -> item.value = passwordFinder.reqPassword(null) - else -> UnsupportedCredentialItem(uri, item.javaClass.name) - } - } - return true - } - - override fun supports(vararg items: CredentialItem) = items.all { - it is CredentialItem.Username || it is CredentialItem.Password - } - } - - private fun withPasswordAuthentication(username: String, passwordFinder: InteractivePasswordFinder): GitOperation { - val sessionFactory = SshjSessionFactory(username, SshAuthData.Password(passwordFinder), hostKeyFile) - SshSessionFactory.setInstance(sessionFactory) - this.provider = PasswordFinderCredentialsProvider(username, passwordFinder) - return this - } - - private fun withPublicKeyAuthentication(username: String, passphraseFinder: InteractivePasswordFinder): GitOperation { - val sessionFactory = SshjSessionFactory(username, SshAuthData.PublicKeyFile(sshKeyFile, passphraseFinder), hostKeyFile) - SshSessionFactory.setInstance(sessionFactory) - this.provider = null - return this - } - - private fun withOpenKeychainAuthentication(username: String, identity: SshApiSessionFactory.ApiIdentity?): GitOperation { - SshSessionFactory.setInstance(SshApiSessionFactory(username, identity)) - this.provider = null - return this - } - - private fun getSshKey(make: Boolean) { - try { - // Ask the UserPreference to provide us with the ssh-key - // onResult has to be handled by the callingActivity - val intent = Intent(callingActivity.applicationContext, UserPreference::class.java) - intent.putExtra("operation", if (make) "make_ssh_key" else "get_ssh_key") - callingActivity.startActivityForResult(intent, GET_SSH_KEY_FROM_CLONE) - } catch (e: Exception) { - println("Exception caught :(") - e.printStackTrace() - } - } - - /** - * Executes the GitCommand in an async task - */ - abstract fun execute() - - fun executeAfterAuthentication( - connectionMode: ConnectionMode, - username: String, - identity: SshApiSessionFactory.ApiIdentity? - ) { - when (connectionMode) { - ConnectionMode.SshKey -> if (!sshKeyFile.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)) { _, _ -> - getSshKey(false) - } - .setNegativeButton(callingActivity.resources.getString(R.string.ssh_preferences_dialog_generate)) { _, _ -> - getSshKey(true) - } - .setNeutralButton(callingActivity.resources.getString(R.string.dialog_cancel)) { _, _ -> - // Finish the blank GitActivity so user doesn't have to press back - callingActivity.finish() - }.show() - } else { - withPublicKeyAuthentication(username, GitOperationCredentialFinder(callingActivity, - connectionMode)).execute() - } - ConnectionMode.OpenKeychain -> withOpenKeychainAuthentication(username, identity).execute() - ConnectionMode.Password -> withPasswordAuthentication( - username, GitOperationCredentialFinder(callingActivity, connectionMode)).execute() - ConnectionMode.None -> execute() - } - } - - /** - * Action to execute on error - */ - open fun onError(err: Exception) { - // Clear various auth related fields on failure - when (SshSessionFactory.getInstance()) { - is SshApiSessionFactory -> { - PreferenceManager.getDefaultSharedPreferences(callingActivity.applicationContext) - .edit { remove(PreferenceKeys.SSH_OPENKEYSTORE_KEYID) } - } - is SshjSessionFactory -> { - callingActivity.applicationContext - .getEncryptedPrefs("git_operation") - .edit { - remove(PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE) - remove(PreferenceKeys.HTTPS_PASSWORD) - } - } - } - } - - /** - * Action to execute on success - */ - open fun onSuccess() {} - - companion object { - - const val GET_SSH_KEY_FROM_CLONE = 201 - } -} |
