mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-01-20 21:40:56 +01:00
Logout after 3 wrong PIN codes
This commit is contained in:
parent
4cba1388f9
commit
b090468109
@ -37,6 +37,25 @@ interface PinCodeStore {
|
||||
fun getEncodedPin(): String?
|
||||
|
||||
suspend fun hasEncodedPin(): Boolean
|
||||
|
||||
fun getRemainingPinCodeAttemptsNumber(): Int
|
||||
|
||||
fun getRemainingBiometricsAttemptsNumber(): Int
|
||||
|
||||
/**
|
||||
* Will return the number of remaining attempts
|
||||
*/
|
||||
fun onWrongPin(): Int
|
||||
|
||||
/**
|
||||
* Will return the number of remaining attempts
|
||||
*/
|
||||
fun onWrongBiometrics(): Int
|
||||
|
||||
/**
|
||||
* Will reset the counters
|
||||
*/
|
||||
fun resetCounters()
|
||||
}
|
||||
|
||||
class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences: SharedPreferences) : PinCodeStore {
|
||||
@ -48,6 +67,8 @@ class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences:
|
||||
}
|
||||
|
||||
override suspend fun deleteEncodedPin() = withContext(Dispatchers.IO) {
|
||||
// Also reset the counters
|
||||
resetCounters()
|
||||
sharedPreferences.edit {
|
||||
remove(ENCODED_PIN_CODE_KEY)
|
||||
}
|
||||
@ -72,11 +93,47 @@ class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences:
|
||||
result.error == null && result.result
|
||||
}
|
||||
|
||||
override fun getRemainingPinCodeAttemptsNumber(): Int {
|
||||
return sharedPreferences.getInt(REMAINING_PIN_CODE_ATTEMPTS_KEY, MAX_PIN_CODE_ATTEMPTS_NUMBER_BEFORE_LOGOUT)
|
||||
}
|
||||
|
||||
override fun getRemainingBiometricsAttemptsNumber(): Int {
|
||||
return sharedPreferences.getInt(REMAINING_BIOMETRICS_ATTEMPTS_KEY, MAX_BIOMETRIC_ATTEMPTS_NUMBER_BEFORE_FORCE_PIN)
|
||||
}
|
||||
|
||||
override fun onWrongPin(): Int {
|
||||
val remaining = getRemainingPinCodeAttemptsNumber() - 1
|
||||
sharedPreferences.edit {
|
||||
putInt(REMAINING_PIN_CODE_ATTEMPTS_KEY, remaining)
|
||||
}
|
||||
return remaining
|
||||
}
|
||||
|
||||
override fun onWrongBiometrics(): Int {
|
||||
val remaining = getRemainingBiometricsAttemptsNumber() - 1
|
||||
sharedPreferences.edit {
|
||||
putInt(REMAINING_BIOMETRICS_ATTEMPTS_KEY, remaining)
|
||||
}
|
||||
return remaining
|
||||
}
|
||||
|
||||
override fun resetCounters() {
|
||||
sharedPreferences.edit {
|
||||
remove(REMAINING_PIN_CODE_ATTEMPTS_KEY)
|
||||
remove(REMAINING_BIOMETRICS_ATTEMPTS_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend inline fun <T> awaitPinCodeCallback(crossinline callback: (PFPinCodeHelperCallback<T>) -> Unit) = suspendCoroutine<PFResult<T>> { cont ->
|
||||
callback(PFPinCodeHelperCallback<T> { result -> cont.resume(result) })
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ENCODED_PIN_CODE_KEY = "ENCODED_PIN_CODE_KEY"
|
||||
private const val REMAINING_PIN_CODE_ATTEMPTS_KEY = "REMAINING_PIN_CODE_ATTEMPTS_KEY"
|
||||
private const val REMAINING_BIOMETRICS_ATTEMPTS_KEY = "REMAINING_BIOMETRICS_ATTEMPTS_KEY"
|
||||
|
||||
private const val MAX_PIN_CODE_ATTEMPTS_NUMBER_BEFORE_LOGOUT = 3
|
||||
private const val MAX_BIOMETRIC_ATTEMPTS_NUMBER_BEFORE_FORCE_PIN = 5
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.beautycoder.pflockscreen.fragments.PFLockScreenFragment
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.replaceFragment
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.MainActivity
|
||||
import im.vector.app.features.MainActivityArgs
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
@ -61,7 +62,7 @@ class PinFragment @Inject constructor(
|
||||
val encodedPin = pinCodeStore.getEncodedPin() ?: return
|
||||
val authFragment = PFLockScreenFragment()
|
||||
val builder = PFFLockScreenConfiguration.Builder(requireContext())
|
||||
.setUseBiometric(true)
|
||||
.setUseBiometric(pinCodeStore.getRemainingBiometricsAttemptsNumber() > 0)
|
||||
.setTitle(getString(R.string.auth_pin_confirm_to_disable_title))
|
||||
.setClearCodeOnError(true)
|
||||
.setMode(PFFLockScreenConfiguration.MODE_AUTH)
|
||||
@ -69,6 +70,7 @@ class PinFragment @Inject constructor(
|
||||
authFragment.setEncodedPinCode(encodedPin)
|
||||
authFragment.setLoginListener(object : PFLockScreenFragment.OnPFLockScreenLoginListener {
|
||||
override fun onPinLoginFailed() {
|
||||
onWrongPin()
|
||||
}
|
||||
|
||||
override fun onBiometricAuthSuccessful() {
|
||||
@ -80,6 +82,12 @@ class PinFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onBiometricAuthLoginFailed() {
|
||||
val remainingAttempts = pinCodeStore.onWrongBiometrics()
|
||||
if (remainingAttempts <= 0) {
|
||||
// Disable Biometrics
|
||||
builder.setUseBiometric(false)
|
||||
authFragment.setConfiguration(builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCodeInputSuccessful() {
|
||||
@ -121,8 +129,12 @@ class PinFragment @Inject constructor(
|
||||
private fun showAuthFragment() {
|
||||
val encodedPin = pinCodeStore.getEncodedPin() ?: return
|
||||
val authFragment = PFLockScreenFragment()
|
||||
val canUseBiometrics = pinCodeStore.getRemainingBiometricsAttemptsNumber() > 0
|
||||
val builder = PFFLockScreenConfiguration.Builder(requireContext())
|
||||
.setUseBiometric(true)
|
||||
.setAutoShowBiometric(true)
|
||||
.setUseBiometric(canUseBiometrics)
|
||||
.setAutoShowBiometric(canUseBiometrics)
|
||||
.setTitle(getString(R.string.auth_pin_title))
|
||||
.setLeftButton(getString(R.string.auth_pin_forgot))
|
||||
.setClearCodeOnError(true)
|
||||
@ -134,17 +146,26 @@ class PinFragment @Inject constructor(
|
||||
}
|
||||
authFragment.setLoginListener(object : PFLockScreenFragment.OnPFLockScreenLoginListener {
|
||||
override fun onPinLoginFailed() {
|
||||
onWrongPin()
|
||||
}
|
||||
|
||||
override fun onBiometricAuthSuccessful() {
|
||||
pinCodeStore.resetCounters()
|
||||
vectorBaseActivity.setResult(Activity.RESULT_OK)
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
|
||||
override fun onBiometricAuthLoginFailed() {
|
||||
val remainingAttempts = pinCodeStore.onWrongBiometrics()
|
||||
if (remainingAttempts <= 0) {
|
||||
// Disable Biometrics
|
||||
builder.setUseBiometric(false)
|
||||
authFragment.setConfiguration(builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCodeInputSuccessful() {
|
||||
pinCodeStore.resetCounters()
|
||||
vectorBaseActivity.setResult(Activity.RESULT_OK)
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
@ -152,6 +173,21 @@ class PinFragment @Inject constructor(
|
||||
replaceFragment(R.id.pinFragmentContainer, authFragment)
|
||||
}
|
||||
|
||||
private fun onWrongPin() {
|
||||
val remainingAttempts = pinCodeStore.onWrongPin()
|
||||
when {
|
||||
remainingAttempts > 1 ->
|
||||
requireActivity().toast(resources.getQuantityString(R.plurals.wrong_pin_message_remaining_attempts, remainingAttempts, remainingAttempts))
|
||||
remainingAttempts == 1 ->
|
||||
requireActivity().toast(R.string.wrong_pin_message_last_remaining_attempt)
|
||||
else -> {
|
||||
requireActivity().toast(R.string.too_many_pin_failures)
|
||||
// Logout
|
||||
MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCredentials = true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayForgotPinWarningDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(getString(R.string.auth_pin_reset_title))
|
||||
|
@ -2516,6 +2516,12 @@
|
||||
|
||||
<string name="alert_push_are_disabled_title">Push notifications are disabled</string>
|
||||
<string name="alert_push_are_disabled_description">Review your settings to enable push notifications</string>
|
||||
<plurals name="wrong_pin_message_remaining_attempts">
|
||||
<item quantity="one">Wrong code, %d remaining attempt</item>
|
||||
<item quantity="other">Wrong code, %d remaining attempts</item>
|
||||
</plurals>
|
||||
<string name="wrong_pin_message_last_remaining_attempt">Warning! Last remaining attempt before logout!</string>
|
||||
<string name="too_many_pin_failures">Too many errors, you\'ve been logged out</string>
|
||||
<string name="create_pin_title">Choose a PIN for security</string>
|
||||
<string name="create_pin_confirm_title">Confirm PIN</string>
|
||||
<string name="create_pin_confirm_failure">Failed to validate pin, please tap a new one.</string>
|
||||
|
Loading…
Reference in New Issue
Block a user