More flexible password change when fingerprint is saved

This commit is contained in:
Matéo Duparc 2022-09-27 18:33:43 +02:00
parent 7cdfc32c31
commit 4df1086734
Signed by: hardcoresushi
GPG Key ID: AFE384344A45E13A
9 changed files with 65 additions and 26 deletions

View File

@ -1,11 +1,13 @@
package sushi.hardcore.droidfs package sushi.hardcore.droidfs
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import sushi.hardcore.droidfs.databinding.ActivityChangePasswordBinding import sushi.hardcore.droidfs.databinding.ActivityChangePasswordBinding
@ -24,6 +26,9 @@ class ChangePasswordActivity: BaseActivity() {
private lateinit var volumeDatabase: VolumeDatabase private lateinit var volumeDatabase: VolumeDatabase
private var fingerprintProtector: FingerprintProtector? = null private var fingerprintProtector: FingerprintProtector? = null
private var usfFingerprint: Boolean = false private var usfFingerprint: Boolean = false
private val inputMethodManager by lazy {
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -38,8 +43,7 @@ class ChangePasswordActivity: BaseActivity() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
fingerprintProtector = FingerprintProtector.new(this, themeValue, volumeDatabase) fingerprintProtector = FingerprintProtector.new(this, themeValue, volumeDatabase)
if (fingerprintProtector != null && volume.encryptedHash != null) { if (fingerprintProtector != null && volume.encryptedHash != null) {
binding.textCurrentPasswordLabel.visibility = View.GONE binding.fingerprintSwitchContainer.visibility = View.VISIBLE
binding.editCurrentPassword.visibility = View.GONE
} }
} }
if (!usfFingerprint || fingerprintProtector == null) { if (!usfFingerprint || fingerprintProtector == null) {
@ -50,6 +54,20 @@ class ChangePasswordActivity: BaseActivity() {
it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
} }
} }
binding.fingerprintSwitchContainer.setOnClickListener {
binding.switchUseFingerprint.toggle()
}
binding.switchUseFingerprint.setOnCheckedChangeListener { _, isChecked ->
if (isChecked && binding.editCurrentPassword.hasFocus()) {
binding.editCurrentPassword.clearFocus()
inputMethodManager.hideSoftInputFromWindow(binding.editCurrentPassword.windowToken, 0)
}
}
binding.editCurrentPassword.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
binding.switchUseFingerprint.isChecked = false
}
}
binding.editPasswordConfirm.setOnEditorActionListener { _, _, _ -> binding.editPasswordConfirm.setOnEditorActionListener { _, _, _ ->
changeVolumePassword() changeVolumePassword()
true true
@ -81,22 +99,24 @@ class ChangePasswordActivity: BaseActivity() {
volume.encryptedHash?.let { encryptedHash -> volume.encryptedHash?.let { encryptedHash ->
volume.iv?.let { iv -> volume.iv?.let { iv ->
fingerprintProtector?.let { fingerprintProtector?.let {
changeWithCurrentPassword = false if (binding.switchUseFingerprint.isChecked) {
it.listener = object : FingerprintProtector.Listener { changeWithCurrentPassword = false
override fun onHashStorageReset() { it.listener = object : FingerprintProtector.Listener {
showCurrentPasswordInput() override fun onHashStorageReset() {
volume.encryptedHash = null showCurrentPasswordInput()
volume.iv = null volume.encryptedHash = null
} volume.iv = null
override fun onPasswordHashDecrypted(hash: ByteArray) { }
changeVolumePassword(newPassword, hash) override fun onPasswordHashDecrypted(hash: ByteArray) {
} changeVolumePassword(newPassword, hash)
override fun onPasswordHashSaved() {} }
override fun onFailed(pending: Boolean) { override fun onPasswordHashSaved() {}
Arrays.fill(newPassword, 0) override fun onFailed(pending: Boolean) {
Arrays.fill(newPassword, 0)
}
} }
it.loadPasswordHash(volume.name, encryptedHash, iv)
} }
it.loadPasswordHash(volume.name, encryptedHash, iv)
} }
} }
} }

View File

@ -283,7 +283,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
removeVolumes(selectedVolumes) removeVolumes(selectedVolumes)
true true
} }
R.id.forget_password -> { R.id.delete_password_hash -> {
for (i in volumeAdapter.selectedItems) { for (i in volumeAdapter.selectedItems) {
if (volumeDatabase.removeHash(volumeAdapter.volumes[i])) if (volumeDatabase.removeHash(volumeAdapter.volumes[i]))
volumeAdapter.onVolumeChanged(i) volumeAdapter.onVolumeChanged(i)
@ -349,7 +349,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
val isSelecting = volumeAdapter.selectedItems.isNotEmpty() val isSelecting = volumeAdapter.selectedItems.isNotEmpty()
menu.findItem(R.id.select_all).isVisible = isSelecting menu.findItem(R.id.select_all).isVisible = isSelecting
menu.findItem(R.id.remove).isVisible = isSelecting menu.findItem(R.id.remove).isVisible = isSelecting
menu.findItem(R.id.forget_password).isVisible = menu.findItem(R.id.delete_password_hash).isVisible =
isSelecting && isSelecting &&
!volumeAdapter.selectedItems.any { i -> volumeAdapter.volumes[i].encryptedHash == null } !volumeAdapter.selectedItems.any { i -> volumeAdapter.volumes[i].encryptedHash == null }
val onlyOneSelected = volumeAdapter.selectedItems.size == 1 val onlyOneSelected = volumeAdapter.selectedItems.size == 1

View File

@ -31,15 +31,37 @@
android:id="@+id/edit_current_password" android:id="@+id/edit_current_password"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/volume_operation_vertical_gap"
android:autofillHints="password" android:autofillHints="password"
android:hint="@string/current_password_hint" android:hint="@string/current_password_hint"
android:inputType="textPassword" android:inputType="textPassword"
android:maxLines="1" /> android:maxLines="1" />
<LinearLayout
android:id="@+id/fingerprint_switch_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:visibility="gone">
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@drawable/icon_fingerprint"
android:layout_marginEnd="5dp"/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch_use_fingerprint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/use_fingerprint"
android:checked="true"/>
</LinearLayout>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/volume_operation_vertical_gap"
android:text="@string/new_password_label" /> android:text="@string/new_password_label" />
<EditText <EditText

View File

@ -23,10 +23,10 @@
android:icon="@drawable/icon_settings"/> android:icon="@drawable/icon_settings"/>
<item <item
android:id="@+id/forget_password" android:id="@+id/delete_password_hash"
app:showAsAction="never" app:showAsAction="never"
android:visible="false" android:visible="false"
android:title="@string/forget_password"/> android:title="@string/remove_fingerprint"/>
<item <item
android:id="@+id/change_password" android:id="@+id/change_password"

View File

@ -186,7 +186,6 @@
<string name="remove">إزالة</string> <string name="remove">إزالة</string>
<string name="settings">إعدادات</string> <string name="settings">إعدادات</string>
<string name="select_all">تحديد الكل</string> <string name="select_all">تحديد الكل</string>
<string name="forget_password">نسيان كلمة المرور</string>
<string name="unrecoverable_key_exception_msg">%s. فشل تحميل مفتاح التشفير.</string> <string name="unrecoverable_key_exception_msg">%s. فشل تحميل مفتاح التشفير.</string>
<string name="unrecoverable_key_exception">UnrecoverableKeyException</string> <string name="unrecoverable_key_exception">UnrecoverableKeyException</string>
<string name="delete_hidden_volume_question">%s مخفي ، هل تريد فقط نسيان مسار المجلد أو حذف كل محتوياته أيضًا?</string> <string name="delete_hidden_volume_question">%s مخفي ، هل تريد فقط نسيان مسار المجلد أو حذف كل محتوياته أيضًا?</string>

View File

@ -186,7 +186,6 @@
<string name="remove">Eliminar</string> <string name="remove">Eliminar</string>
<string name="settings">Ajustes</string> <string name="settings">Ajustes</string>
<string name="select_all">Seleccionar todo</string> <string name="select_all">Seleccionar todo</string>
<string name="forget_password">Olvidar la contraseña</string>
<string name="unrecoverable_key_exception_msg">%s. No se puede cargar la clave de encriptación.</string> <string name="unrecoverable_key_exception_msg">%s. No se puede cargar la clave de encriptación.</string>
<string name="unrecoverable_key_exception">UnrecoverableKeyException</string> <string name="unrecoverable_key_exception">UnrecoverableKeyException</string>
<string name="delete_hidden_volume_question">%s está oculto, ¿sólo quieres olvidar la ruta del volumen o también BORRAR todo su CONTENIDO?</string> <string name="delete_hidden_volume_question">%s está oculto, ¿sólo quieres olvidar la ruta del volumen o también BORRAR todo su CONTENIDO?</string>

View File

@ -180,7 +180,6 @@
<string name="remove">Remover</string> <string name="remove">Remover</string>
<string name="settings">Configurações</string> <string name="settings">Configurações</string>
<string name="select_all">Selecionar tudo</string> <string name="select_all">Selecionar tudo</string>
<string name="forget_password">Abandonar a senha</string>
<string name="unrecoverable_key_exception_msg">%s. Não foi possível carregar a chave de criptografia.</string> <string name="unrecoverable_key_exception_msg">%s. Não foi possível carregar a chave de criptografia.</string>
<string name="unrecoverable_key_exception">UnrecoverableKeyException</string> <string name="unrecoverable_key_exception">UnrecoverableKeyException</string>
<string name="delete_hidden_volume_question">%s está oculto, você só quer abandonar o caminho do volume ou também REMOVER todo o seu CONTEÚDO?</string> <string name="delete_hidden_volume_question">%s está oculto, você só quer abandonar o caminho do volume ou também REMOVER todo o seu CONTEÚDO?</string>

View File

@ -180,7 +180,6 @@
<string name="remove">Удалить</string> <string name="remove">Удалить</string>
<string name="settings">Настройки</string> <string name="settings">Настройки</string>
<string name="select_all">Выбрать все</string> <string name="select_all">Выбрать все</string>
<string name="forget_password">Забыть пароль</string>
<string name="unrecoverable_key_exception_msg">%s. Невозможно загрузить ключ шифрования.</string> <string name="unrecoverable_key_exception_msg">%s. Невозможно загрузить ключ шифрования.</string>
<string name="delete_hidden_volume_question">Том \"%s\" скрытый, вы хотите только забыть путь к нему или УДАЛИТЬ том со всем его СОДЕРЖИМЫМ?</string> <string name="delete_hidden_volume_question">Том \"%s\" скрытый, вы хотите только забыть путь к нему или УДАЛИТЬ том со всем его СОДЕРЖИМЫМ?</string>
<string name="forget_only">Только забыть</string> <string name="forget_only">Только забыть</string>

View File

@ -187,7 +187,7 @@
<string name="remove">Remove</string> <string name="remove">Remove</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="select_all">Select All</string> <string name="select_all">Select All</string>
<string name="forget_password">Forget password</string> <string name="remove_fingerprint">Remove fingerprint</string>
<string name="unrecoverable_key_exception_msg">%s. Can\'t load encryption key.</string> <string name="unrecoverable_key_exception_msg">%s. Can\'t load encryption key.</string>
<string name="unrecoverable_key_exception">UnrecoverableKeyException</string> <string name="unrecoverable_key_exception">UnrecoverableKeyException</string>
<string name="delete_hidden_volume_question">%s is hidden, do you just want to forget the path of the volume or also DELETE all its CONTENT?</string> <string name="delete_hidden_volume_question">%s is hidden, do you just want to forget the path of the volume or also DELETE all its CONTENT?</string>
@ -249,4 +249,5 @@
<string name="volume_type">(%s)</string> <string name="volume_type">(%s)</string>
<string name="volume_type_read_only">(%s, read-only)</string> <string name="volume_type_read_only">(%s, read-only)</string>
<string name="io_error">I/O Error.</string> <string name="io_error">I/O Error.</string>
<string name="use_fingerprint">Use fingerprint instead of current password</string>
</resources> </resources>