Skip to content
Snippets Groups Projects
Commit a5f28360 authored by Taras's avatar Taras
Browse files

Add possibility to decrypt with raw key

parent 453e08f2
No related branches found
No related tags found
No related merge requests found
package org.futo.circles.auth.feature.log_in
package org.futo.circles.auth.feature.log_in.recovery
import android.app.ActionBar
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatDialog
import androidx.core.widget.doAfterTextChanged
import org.futo.circles.auth.databinding.DialogEnterPassphraseBinding
import org.futo.circles.core.extensions.getFilename
import org.futo.circles.core.extensions.getText
import org.futo.circles.core.extensions.gone
import org.futo.circles.core.extensions.visible
interface EnterPassPhraseDialogListener {
fun onRestoreBackup(passphrase: String)
fun onRestoreBackup(uri: Uri)
fun onDoNotRestore()
fun onSelectFileClicked()
}
import org.futo.circles.core.extensions.setIsVisible
class EnterPassPhraseDialog(context: Context, private val listener: EnterPassPhraseDialogListener) :
AppCompatDialog(context) {
private val binding = DialogEnterPassphraseBinding.inflate(LayoutInflater.from(context))
private var selectedFileUri: Uri? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
setCancelable(false)
window?.apply {
setBackgroundDrawable(InsetDrawable(ColorDrawable(Color.TRANSPARENT), 20))
setLayout(ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.WRAP_CONTENT)
}
with(binding) {
fileNameGroup.gone()
recoveryTypeGroup.setOnCheckedChangeListener { _, checkedId ->
tilPassphrase.setIsVisible(checkedId == btnPassphrase.id)
vRecoveryKey.setIsVisible(checkedId == btnRecoveryKey.id)
handleRestoreButtonEnabled()
}
vRecoveryKey.setup(
onUploadFileListener = { listener.onSelectFileClicked() },
onInputChanged = { handleRestoreButtonEnabled() }
)
btnCancel.setOnClickListener {
listener.onDoNotRestore()
dismiss()
}
btnRestore.setOnClickListener {
selectedFileUri?.let {
listener.onRestoreBackup(it)
} ?: listener.onRestoreBackup(tilPassphrase.getText())
restoreBackup()
dismiss()
}
tilPassphrase.editText?.doAfterTextChanged { handleRestoreButtonEnabled() }
ivRemoveFile.setOnClickListener {
selectedFileUri = null
binding.passPhraseGroup.visible()
binding.fileNameGroup.gone()
handleRestoreButtonEnabled()
}
btnUploadFile.setOnClickListener {
listener.onSelectFileClicked()
}
}
}
fun selectFile(uri: Uri) {
selectedFileUri = uri
binding.tvFileName.text = uri.getFilename(context) ?: uri.toString()
binding.passPhraseGroup.gone()
binding.fileNameGroup.visible()
handleRestoreButtonEnabled()
binding.vRecoveryKey.selectFile(uri)
}
private fun restoreBackup() {
if (isPassphraseTypeSelected()) {
listener.onRestoreBackupWithPassphrase(binding.tilPassphrase.getText())
} else {
val uri = binding.vRecoveryKey.getFileUri()
uri?.let {
listener.onRestoreBackup(it)
} ?: listener.onRestoreBackupWithRawKey(binding.vRecoveryKey.getRawKey() ?: "")
}
}
private fun isPassphraseTypeSelected() =
binding.recoveryTypeGroup.checkedRadioButtonId == binding.btnPassphrase.id
private fun handleRestoreButtonEnabled() {
binding.btnRestore.isEnabled =
binding.tilPassphrase.getText().isNotEmpty() || selectedFileUri != null
binding.btnRestore.isEnabled = if (isPassphraseTypeSelected()) {
binding.tilPassphrase.getText().isNotEmpty()
} else {
val isRawKeyEntered = binding.vRecoveryKey.getRawKey()?.isNotEmpty() == true
val isFileKeyEntered = binding.vRecoveryKey.getFileUri() != null
isRawKeyEntered || isFileKeyEntered
}
}
}
\ No newline at end of file
package org.futo.circles.auth.feature.log_in.recovery
import android.net.Uri
interface EnterPassPhraseDialogListener {
fun onRestoreBackupWithPassphrase(passphrase: String)
fun onRestoreBackupWithRawKey(key: String)
fun onRestoreBackup(uri: Uri)
fun onDoNotRestore()
fun onSelectFileClicked()
}
\ No newline at end of file
......@@ -15,8 +15,8 @@ import dagger.hilt.android.AndroidEntryPoint
import org.futo.circles.auth.R
import org.futo.circles.auth.base.LoginStageNavigationEvent
import org.futo.circles.auth.databinding.FragmentLoginStagesBinding
import org.futo.circles.auth.feature.log_in.EnterPassPhraseDialog
import org.futo.circles.auth.feature.log_in.EnterPassPhraseDialogListener
import org.futo.circles.auth.feature.log_in.recovery.EnterPassPhraseDialog
import org.futo.circles.auth.feature.log_in.recovery.EnterPassPhraseDialogListener
import org.futo.circles.core.CirclesAppConfig
import org.futo.circles.core.extensions.navigateSafe
import org.futo.circles.core.extensions.observeData
......@@ -98,8 +98,12 @@ class LogInStagesFragment : Fragment(R.layout.fragment_login_stages),
private fun showPassPhraseDialog() {
enterPassPhraseDialog =
EnterPassPhraseDialog(requireContext(), object : EnterPassPhraseDialogListener {
override fun onRestoreBackup(passphrase: String) {
viewModel.restoreBackup(passphrase)
override fun onRestoreBackupWithPassphrase(passphrase: String) {
viewModel.restoreBackupWithPassPhrase(passphrase)
}
override fun onRestoreBackupWithRawKey(key: String) {
viewModel.restoreBackupWithRawKey(key)
}
override fun onRestoreBackup(uri: Uri) {
......
......@@ -121,6 +121,17 @@ class RestoreBackupDataSource @Inject constructor(
loadingLiveData.postValue(LoadingData(isLoading = false))
}
suspend fun restoreKeysWithRawKey(rawKey: String) {
try {
val keyData = ssssDataSource.getRecoveryKeyFromFileKey(rawKey, progressObserver)
restoreKeysWithRecoveryKey(keyData)
} catch (e: Throwable) {
loadingLiveData.postValue(LoadingData(isLoading = false))
throw e
}
loadingLiveData.postValue(LoadingData(isLoading = false))
}
suspend fun restoreKeysWithRecoveryKey(uri: Uri) {
try {
val key = readRecoveryKeyFile(uri)
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
......@@ -23,7 +22,7 @@
android:gravity="center"
android:lines="1"
android:paddingVertical="8dp"
android:text="@string/enter_passphrase"
android:text="@string/recovery"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
......@@ -51,6 +50,40 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleDivider" />
<RadioGroup
android:id="@+id/recoveryTypeGroup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingVertical="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvSubtitle">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/btnPassphrase"
style="@style/body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:checked="true"
android:padding="8dp"
android:text="@string/passphrase" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/btnRecoveryKey"
style="@style/body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:padding="8dp"
android:text="@string/recovery_key" />
</RadioGroup>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilPassphrase"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
......@@ -62,7 +95,7 @@
android:hint="@string/passphrase"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvSubtitle"
app:layout_constraintTop_toBottomOf="@id/recoveryTypeGroup"
app:passwordToggleEnabled="true">
<com.google.android.material.textfield.TextInputEditText
......@@ -74,60 +107,24 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/tvOr"
style="@style/body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/or"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tilPassphrase" />
<TextView
android:id="@+id/tvFileName"
style="@style/body"
android:layout_width="wrap_content"
<org.futo.circles.auth.view.EnterRecoveryKeyView
android:id="@+id/vRecoveryKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="26dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:lines="1"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/ivRemoveFile"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvOr"
tools:text="File name.txt" />
<ImageView
android:id="@+id/ivRemoveFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:background="?android:selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_close"
app:layout_constraintBottom_toBottomOf="@id/tvFileName"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tvFileName"
app:layout_constraintTop_toTopOf="@id/tvFileName"
app:tint="@color/blue" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/recoveryTypeGroup" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnUploadFile"
style="@style/PostButtonStyle"
android:layout_width="wrap_content"
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/upload_recovery_key"
app:icon="@drawable/ic_file"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvFileName" />
app:barrierDirection="bottom"
app:constraint_referenced_ids="tilPassphrase,vRecoveryKey" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnRestore"
......@@ -153,27 +150,15 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btnRestore"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnUploadFile" />
app:layout_constraintTop_toBottomOf="@id/barrier" />
<androidx.constraintlayout.widget.Group
android:id="@+id/passPhraseGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tvOr,tvSubtitle,tilPassphrase" />
<androidx.constraintlayout.widget.Group
android:id="@+id/fileNameGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tvFileName,ivRemoveFile" />
</androidx.constraintlayout.widget.ConstraintLayout>
......
......@@ -75,10 +75,11 @@
<string name="validate_your_token">Validate your token</string>
<string name="sign_up_token_format">abcd–efgh–1234–5678</string>
<string name="validate_token">Validate token</string>
<string name="enter_passphrase">Enter Passphrase</string>
<string name="recovery">Recovery</string>
<string name="recovery_key">Recovery Key</string>
<string name="use_your_recovery_message">Use your Recovery Passphrase or Recovery Key to continue.</string>
<string name="passphrase">Passphrase</string>
<string name="upload_recovery_key">Upload Recovery Key</string>
<string name="upload_recovery_key_file">Upload Recovery Key file</string>
<string name="restore">Restore</string>
<string name="validate_your_email">Validate your email</string>
<string name="not_supported_navigation_event">Not supported navigation event</string>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment