mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-24 02:39:55 +01:00
Fix bugs around requesting and entering verification codes.
This commit is contained in:
@@ -4,7 +4,9 @@ import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.annotation.StringRes
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class ActionCountDownButton @JvmOverloads constructor(
|
||||
context: Context,
|
||||
@@ -17,7 +19,7 @@ class ActionCountDownButton @JvmOverloads constructor(
|
||||
@StringRes
|
||||
private var disabledText = 0
|
||||
|
||||
private var countDownToTime: Long = 0
|
||||
private var countDownToTime: Duration = 0.seconds
|
||||
private var listener: Listener? = null
|
||||
|
||||
private var updateRunnable = Runnable {
|
||||
@@ -27,8 +29,8 @@ class ActionCountDownButton @JvmOverloads constructor(
|
||||
/**
|
||||
* Starts a count down to the specified {@param time}.
|
||||
*/
|
||||
fun startCountDownTo(time: Long) {
|
||||
if (time > 0) {
|
||||
fun startCountDownTo(time: Duration) {
|
||||
if (time > 0.seconds) {
|
||||
countDownToTime = time
|
||||
removeCallbacks(updateRunnable)
|
||||
updateCountDown()
|
||||
@@ -46,11 +48,11 @@ class ActionCountDownButton @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun updateCountDown() {
|
||||
val remainingMillis = countDownToTime - System.currentTimeMillis()
|
||||
if (remainingMillis > 1000) {
|
||||
val remaining = countDownToTime - System.currentTimeMillis().milliseconds
|
||||
if (remaining > 1.seconds) {
|
||||
isEnabled = false
|
||||
alpha = 0.5f
|
||||
val totalRemainingSeconds = TimeUnit.MILLISECONDS.toSeconds(remainingMillis).toInt()
|
||||
val totalRemainingSeconds = remaining.inWholeSeconds.toInt()
|
||||
val minutesRemaining = totalRemainingSeconds / 60
|
||||
val secondsRemaining = totalRemainingSeconds % 60
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.registration.sms.ReceivedSmsEvent
|
||||
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
/**
|
||||
* Screen used to enter the registration code provided by the service.
|
||||
@@ -132,8 +133,8 @@ class ChangeNumberEnterCodeFragment : LoggingFragment(R.layout.fragment_change_n
|
||||
}
|
||||
|
||||
private fun onStateUpdate(state: ChangeNumberState) {
|
||||
binding.codeEntryLayout.resendSmsCountDown.startCountDownTo(state.nextSmsTimestamp)
|
||||
binding.codeEntryLayout.callMeCountDown.startCountDownTo(state.nextCallTimestamp)
|
||||
binding.codeEntryLayout.resendSmsCountDown.startCountDownTo(state.nextSmsTimestamp.milliseconds)
|
||||
binding.codeEntryLayout.callMeCountDown.startCountDownTo(state.nextCallTimestamp.milliseconds)
|
||||
when (val outcome = state.changeNumberOutcome) {
|
||||
is ChangeNumberOutcome.RecoveryPasswordWorked,
|
||||
is ChangeNumberOutcome.VerificationCodeWorked -> changeNumberSuccess()
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.registration.data.RegistrationData
|
||||
import org.thoughtcrime.securesms.registration.data.RegistrationRepository
|
||||
import org.thoughtcrime.securesms.registration.data.network.Challenge
|
||||
import org.thoughtcrime.securesms.registration.data.network.RegistrationSessionCreationResult
|
||||
import org.thoughtcrime.securesms.registration.data.network.SessionMetadataResult
|
||||
import org.thoughtcrime.securesms.registration.data.network.VerificationCodeRequestResult
|
||||
import org.thoughtcrime.securesms.registration.sms.SmsRetrieverReceiver
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationViewModel
|
||||
@@ -33,7 +34,6 @@ import org.thoughtcrime.securesms.registration.viewmodel.NumberViewState
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.SvrAuthCredentialSet
|
||||
import org.thoughtcrime.securesms.util.dualsim.MccMncProducer
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
@@ -240,7 +240,7 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
private suspend fun verifyCodeInternal(context: Context, pin: String?, verificationErrorHandler: (VerificationCodeRequestResult) -> Unit, numberChangeErrorHandler: (ChangeNumberResult) -> Unit) {
|
||||
val sessionId = getOrCreateValidSession(context)?.metadata?.id ?: return bail { Log.i(TAG, "Bailing from code verification due to invalid session.") }
|
||||
val sessionId = getOrCreateValidSession(context)?.sessionId ?: return bail { Log.i(TAG, "Bailing from code verification due to invalid session.") }
|
||||
val registrationData = getRegistrationData(context)
|
||||
|
||||
val verificationResponse = RegistrationRepository.submitVerificationCode(context, sessionId, registrationData)
|
||||
@@ -285,8 +285,8 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
|
||||
viewModelScope.launch {
|
||||
Log.d(TAG, "Getting session in order to submit captcha token…")
|
||||
val session = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Bailing captcha token submission due to invalid session.") }
|
||||
if (!Challenge.parse(session.metadata.requestedInformation).contains(Challenge.CAPTCHA)) {
|
||||
val sessionData = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Bailing captcha token submission due to invalid session.") }
|
||||
if (!sessionData.challengesRequested.contains(Challenge.CAPTCHA)) {
|
||||
Log.d(TAG, "Captcha submission no longer necessary, bailing.")
|
||||
store.update {
|
||||
it.copy(
|
||||
@@ -297,7 +297,7 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
return@launch
|
||||
}
|
||||
Log.d(TAG, "Submitting captcha token…")
|
||||
val captchaSubmissionResult = RegistrationRepository.submitCaptchaToken(context, e164, password, session.metadata.id, captchaToken)
|
||||
val captchaSubmissionResult = RegistrationRepository.submitCaptchaToken(context, e164, password, sessionData.sessionId, captchaToken)
|
||||
Log.d(TAG, "Captcha token submitted.")
|
||||
store.update {
|
||||
it.copy(inProgress = false, changeNumberOutcome = ChangeNumberOutcome.ChangeNumberRequestOutcome(captchaSubmissionResult))
|
||||
@@ -314,9 +314,9 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
|
||||
viewModelScope.launch {
|
||||
Log.d(TAG, "Getting session in order to perform push token verification…")
|
||||
val session = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Bailing from push token verification due to invalid session.") }
|
||||
val sessionData = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Bailing from push token verification due to invalid session.") }
|
||||
|
||||
if (!Challenge.parse(session.metadata.requestedInformation).contains(Challenge.PUSH)) {
|
||||
if (!sessionData.challengesRequested.contains(Challenge.PUSH)) {
|
||||
Log.d(TAG, "Push submission no longer necessary, bailing.")
|
||||
store.update {
|
||||
it.copy(
|
||||
@@ -328,7 +328,7 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
Log.d(TAG, "Requesting push challenge token…")
|
||||
val pushSubmissionResult = RegistrationRepository.requestAndVerifyPushToken(context, session.metadata.id, e164, password)
|
||||
val pushSubmissionResult = RegistrationRepository.requestAndVerifyPushToken(context, sessionData.sessionId, e164, password)
|
||||
Log.d(TAG, "Push challenge token submitted.")
|
||||
store.update {
|
||||
it.copy(inProgress = false, changeNumberOutcome = ChangeNumberOutcome.ChangeNumberRequestOutcome(pushSubmissionResult))
|
||||
@@ -361,14 +361,18 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
|
||||
// region Private actions
|
||||
|
||||
private fun updateLocalStateFromSession(response: RegistrationSessionMetadataResponse) {
|
||||
private fun updateLocalStateFromSession(sessionData: SessionMetadataResult) {
|
||||
Log.v(TAG, "updateLocalStateFromSession()")
|
||||
store.update {
|
||||
it.copy(sessionId = response.metadata.id, challengesRequested = Challenge.parse(response.metadata.requestedInformation), allowedToRequestCode = response.metadata.allowedToRequestCode)
|
||||
it.copy(
|
||||
sessionId = sessionData.sessionId,
|
||||
challengesRequested = sessionData.challengesRequested,
|
||||
allowedToRequestCode = sessionData.allowedToRequestCode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getOrCreateValidSession(context: Context): RegistrationSessionMetadataResponse? {
|
||||
private suspend fun getOrCreateValidSession(context: Context): SessionMetadataResult? {
|
||||
Log.v(TAG, "getOrCreateValidSession()")
|
||||
val e164 = number.e164Number
|
||||
val mccMncProducer = MccMncProducer(context)
|
||||
@@ -477,15 +481,15 @@ class ChangeNumberViewModel : ViewModel() {
|
||||
return
|
||||
}
|
||||
|
||||
val result = if (!validSession.metadata.allowedToRequestCode) {
|
||||
val challenges = validSession.metadata.requestedInformation.joinToString()
|
||||
val result = if (!validSession.allowedToRequestCode) {
|
||||
val challenges = validSession.challengesRequested.joinToString()
|
||||
Log.i(TAG, "Not allowed to request code! Remaining challenges: $challenges")
|
||||
VerificationCodeRequestResult.ChallengeRequired(Challenge.parse(validSession.metadata.requestedInformation))
|
||||
VerificationCodeRequestResult.ChallengeRequired(validSession.challengesRequested)
|
||||
} else {
|
||||
store.update {
|
||||
it.copy(changeNumberOutcome = null, challengesRequested = emptyList())
|
||||
}
|
||||
val response = RegistrationRepository.requestSmsCode(context = context, sessionId = validSession.metadata.id, e164 = e164, password = password, mode = mode)
|
||||
val response = RegistrationRepository.requestSmsCode(context = context, sessionId = validSession.sessionId, e164 = e164, password = password, mode = mode)
|
||||
Log.d(TAG, "SMS code request submitted")
|
||||
response
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user