Allow registration with landlines.

This commit is contained in:
Nicholas 2023-06-07 14:46:01 -04:00 committed by GitHub
parent bf048e2a75
commit 2c4c6bf87c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 92 additions and 29 deletions

View file

@ -4,10 +4,12 @@ import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedExcep
import org.whispersystems.signalservice.api.push.exceptions.ExternalServiceFailureException
import org.whispersystems.signalservice.api.push.exceptions.ImpossiblePhoneNumberException
import org.whispersystems.signalservice.api.push.exceptions.InvalidTransportModeException
import org.whispersystems.signalservice.api.push.exceptions.MalformedRequestException
import org.whispersystems.signalservice.api.push.exceptions.MustRequestNewCodeException
import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException
import org.whispersystems.signalservice.api.push.exceptions.NonNormalizedPhoneNumberException
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException
import org.whispersystems.signalservice.api.push.exceptions.RegistrationRetryException
import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException
import org.whispersystems.signalservice.api.util.Preconditions
import org.whispersystems.signalservice.internal.ServiceResponse
@ -167,6 +169,30 @@ sealed class RegistrationSessionProcessor(response: ServiceResponse<Registration
abstract fun verificationCodeRequestSuccess(): Boolean
fun isMalformedRequest(): Boolean {
return error is MalformedRequestException
}
fun isRetryException(): Boolean {
return error is RegistrationRetryException
}
fun isAlreadyVerified(): Boolean {
return error is AlreadyVerifiedException
}
fun mustRequestNewCode(): Boolean {
return error is MustRequestNewCodeException
}
fun externalServiceFailure(): Boolean {
return error is ExternalServiceFailureException
}
fun invalidTransportModeFailure(): Boolean {
return error is InvalidTransportModeException
}
class RegistrationSessionProcessorForSession(response: ServiceResponse<RegistrationSessionMetadataResponse>) : RegistrationSessionProcessor(response) {
override fun verificationCodeRequestSuccess(): Boolean = false
@ -174,21 +200,5 @@ sealed class RegistrationSessionProcessor(response: ServiceResponse<Registration
class RegistrationSessionProcessorForVerification(response: ServiceResponse<RegistrationSessionMetadataResponse>) : RegistrationSessionProcessor(response) {
override fun verificationCodeRequestSuccess(): Boolean = hasResult()
fun isAlreadyVerified(): Boolean {
return error is AlreadyVerifiedException
}
fun mustRequestNewCode(): Boolean {
return error is MustRequestNewCodeException
}
fun externalServiceFailure(): Boolean {
return error is ExternalServiceFailureException
}
fun invalidTransportModeFailure(): Boolean {
return error is InvalidTransportModeException
}
}
}

View file

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.registration.fragments;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
@ -286,8 +287,9 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
}
private void requestVerificationCode(@NonNull Mode mode) {
NavController navController = NavHostFragment.findNavController(this);
MccMncProducer mccMncProducer = new MccMncProducer(requireContext());
NavController navController = NavHostFragment.findNavController(this);
MccMncProducer mccMncProducer = new MccMncProducer(requireContext());
final DialogInterface.OnClickListener proceedToNextScreen = (dialog, which) -> SafeNavigation.safeNavigate(navController, EnterPhoneNumberFragmentDirections.actionEnterVerificationCode());
Disposable request = viewModel.requestVerificationCode(mode, mccMncProducer.getMcc(), mccMncProducer.getMnc())
.doOnSubscribe(unused -> SignalStore.account().setRegistered(false))
.observeOn(AndroidSchedulers.mainThread())
@ -314,11 +316,23 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
} else if (processor.isTokenRejected()) {
Log.i(TAG, "The server did not accept the information.", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_we_need_to_verify_that_youre_human));
} else if (processor instanceof RegistrationSessionProcessor.RegistrationSessionProcessorForVerification
&& ((RegistrationSessionProcessor.RegistrationSessionProcessorForVerification) processor).externalServiceFailure())
{
} else if (processor.externalServiceFailure()) {
Log.w(TAG, "The server reported a failure with an external service.", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_external_service_error));
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service), proceedToNextScreen);
} else if (processor.invalidTransportModeFailure()) {
Log.w(TAG, "The server reported an invalid transport mode failure.", processor.getError());
new MaterialAlertDialogBuilder(register.getContext())
.setMessage(R.string.RegistrationActivity_we_couldnt_send_you_a_verification_code)
.setPositiveButton(R.string.RegistrationActivity_voice_call, (dialog, which) -> requestVerificationCode(Mode.PHONE_CALL))
.setNegativeButton(R.string.RegistrationActivity_cancel, null)
.show();
} else if ( processor.isMalformedRequest()){
Log.w(TAG, "The server reported a malformed request.", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service), proceedToNextScreen);
} else if (processor.isRetryException()) {
Log.w(TAG, "The server reported a failure that is retryable.", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service), proceedToNextScreen);
} else {
Log.i(TAG, "Unknown error during verification code request", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service));
@ -343,7 +357,11 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
}
public void showErrorDialog(Context context, String msg) {
new MaterialAlertDialogBuilder(context).setMessage(msg).setPositiveButton(R.string.ok, null).show();
showErrorDialog(context, msg, null);
}
public void showErrorDialog(Context context, String msg, DialogInterface.OnClickListener positiveButtonListener) {
new MaterialAlertDialogBuilder(context).setMessage(msg).setPositiveButton(R.string.ok, positiveButtonListener).show();
}
@Override

View file

@ -1856,6 +1856,10 @@
<!-- During registration, if the user attempts (and fails) to register, we display this error message with a number of minutes timer they are allowed to try again.-->
<string name="RegistrationActivity_rate_limited_to_try_again">You\'ve made too many attempts to register this number. Please try again in %s.</string>
<string name="RegistrationActivity_unable_to_connect_to_service">Unable to connect to service. Please check network connection and try again.</string>
<!-- A description text for an alert dialog where we do not or can not explain the error to the user. -->
<string name="RegistrationActivity_generic_error">An unexpected error occurred.</string>
<!-- A description text for an alert dialog when the entered phone number is not eligible for a verification SMS. -->
<string name="RegistrationActivity_we_couldnt_send_you_a_verification_code">We couldn\'t send you a verification code via SMS. Try receiving your code via voice call instead.</string>
<!-- Generic error when the app is unable to request an SMS code for an unknown reason. -->
<string name="RegistrationActivity_unable_to_request_verification_code">Unable to request a verification code. Please check network connection and try again.</string>
<string name="RegistrationActivity_non_standard_number_format">Non-standard number format</string>
@ -1874,6 +1878,10 @@
<string name="RegistrationActivity_we_need_to_verify_that_youre_human">We need to verify that you\'re human.</string>
<!-- An error shown when the request was valid, but due to an issue with a partner vendor, the server is unable to send an SMS code -->
<string name="RegistrationActivity_external_service_error">Signal was unable to send an SMS code due to an external failure.</string>
<!-- Button label to trigger a phone call to provide the registration code, in lieu of an SMS code -->
<string name="RegistrationActivity_voice_call">Voice Call</string>
<!-- Dialog button to cancel the pending action and return to the previous state. -->
<string name="RegistrationActivity_cancel">Cancel</string>
<string name="RegistrationActivity_next">Next</string>
<string name="RegistrationActivity_continue">Continue</string>
<string name="RegistrationActivity_take_privacy_with_you_be_yourself_in_every_message">Take privacy with you.\nBe yourself in every message.</string>

View file

@ -0,0 +1,8 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.api.push.exceptions
class MalformedRequestException : NonSuccessfulResponseCodeException(400)

View file

@ -0,0 +1,8 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.api.push.exceptions
class RegistrationRetryException : NonSuccessfulResponseCodeException(429)

View file

@ -69,6 +69,7 @@ import org.whispersystems.signalservice.api.push.exceptions.ExternalServiceFailu
import org.whispersystems.signalservice.api.push.exceptions.HttpConflictException;
import org.whispersystems.signalservice.api.push.exceptions.IncorrectRegistrationRecoveryPasswordException;
import org.whispersystems.signalservice.api.push.exceptions.InvalidTransportModeException;
import org.whispersystems.signalservice.api.push.exceptions.MalformedRequestException;
import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException;
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
import org.whispersystems.signalservice.api.push.exceptions.MustRequestNewCodeException;
@ -82,6 +83,7 @@ import org.whispersystems.signalservice.api.push.exceptions.PushChallengeRequire
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import org.whispersystems.signalservice.api.push.exceptions.RangeException;
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
import org.whispersystems.signalservice.api.push.exceptions.RegistrationRetryException;
import org.whispersystems.signalservice.api.push.exceptions.RemoteAttestationResponseExpiredException;
import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException;
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
@ -2553,7 +2555,10 @@ public class PushServiceSocket {
@Override
public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException {
if (responseCode == 403) {
if (responseCode == 400) {
throw new MalformedRequestException();
} else if (responseCode == 403) {
throw new IncorrectRegistrationRecoveryPasswordException();
} else if (responseCode == 404) {
throw new NoSuchSessionException();
@ -2572,13 +2577,17 @@ public class PushServiceSocket {
} else {
throw new HttpConflictException();
}
} else if (responseCode == 502) {
} else if (responseCode == 418) {
throw new InvalidTransportModeException();
} else if (responseCode == 429) {
throw new RegistrationRetryException();
} else if (responseCode == 440) {
VerificationCodeFailureResponseBody response;
try {
response = JsonUtil.fromJson(body.string(), VerificationCodeFailureResponseBody.class);
} catch (IOException e) {
Log.e(TAG, "Unable to read response body.", e);
throw new NonSuccessfulResponseCodeException(502);
throw new NonSuccessfulResponseCodeException(responseCode);
}
throw new ExternalServiceFailureException(response.getPermanentFailure(), response.getReason());
}
@ -2615,7 +2624,9 @@ public class PushServiceSocket {
}
private static class RegistrationCodeRequestResponseHandler implements ResponseCodeHandler {
@Override public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException {
@Override
public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException {
switch (responseCode) {
case 400:
throw new InvalidTransportModeException();
@ -2637,13 +2648,13 @@ public class PushServiceSocket {
} else {
throw new HttpConflictException();
}
case 502:
case 440:
VerificationCodeFailureResponseBody codeFailureResponse;
try {
codeFailureResponse = JsonUtil.fromJson(body.string(), VerificationCodeFailureResponseBody.class);
} catch (IOException e) {
Log.e(TAG, "Unable to read response body.", e);
throw new NonSuccessfulResponseCodeException(502);
throw new NonSuccessfulResponseCodeException(responseCode);
}
throw new ExternalServiceFailureException(codeFailureResponse.getPermanentFailure(), codeFailureResponse.getReason());