Check verification codes for changing phone numbers against the stand-alone registration service when possible
This commit is contained in:
		
							parent
							
								
									3c6c6c3706
								
							
						
					
					
						commit
						0a64e31625
					
				| 
						 | 
					@ -552,13 +552,20 @@ public class AccountController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      rateLimiters.getVerifyLimiter().validate(number);
 | 
					      rateLimiters.getVerifyLimiter().validate(number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      final Optional<StoredVerificationCode> storedVerificationCode = pendingAccounts.getCodeForNumber(number);
 | 
					      final Optional<StoredVerificationCode> maybeStoredVerificationCode = pendingAccounts.getCodeForNumber(number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (storedVerificationCode.isEmpty() || !storedVerificationCode.get().isValid(request.code())) {
 | 
					      final boolean codeVerified = maybeStoredVerificationCode.map(storedVerificationCode ->
 | 
				
			||||||
 | 
					              storedVerificationCode.sessionId() != null ?
 | 
				
			||||||
 | 
					                  registrationServiceClient.checkVerificationCode(storedVerificationCode.sessionId(),
 | 
				
			||||||
 | 
					                      request.code(), REGISTRATION_RPC_TIMEOUT).join() :
 | 
				
			||||||
 | 
					                  storedVerificationCode.isValid(request.code()))
 | 
				
			||||||
 | 
					          .orElse(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!codeVerified) {
 | 
				
			||||||
        throw new ForbiddenException();
 | 
					        throw new ForbiddenException();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      storedVerificationCode.map(StoredVerificationCode::twilioVerificationSid)
 | 
					      maybeStoredVerificationCode.map(StoredVerificationCode::twilioVerificationSid)
 | 
				
			||||||
          .ifPresent(
 | 
					          .ifPresent(
 | 
				
			||||||
              verificationSid -> smsSender.reportVerificationSucceeded(verificationSid, userAgent, "changeNumber"));
 | 
					              verificationSid -> smsSender.reportVerificationSucceeded(verificationSid, userAgent, "changeNumber"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1452,6 +1452,35 @@ class AccountControllerTest {
 | 
				
			||||||
    assertThat(accountIdentityResponse.getPni()).isNotEqualTo(AuthHelper.VALID_PNI);
 | 
					    assertThat(accountIdentityResponse.getPni()).isNotEqualTo(AuthHelper.VALID_PNI);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  void testChangePhoneNumberWithRegistrationService() throws Exception {
 | 
				
			||||||
 | 
					    final String number = "+18005559876";
 | 
				
			||||||
 | 
					    final String code = "987654";
 | 
				
			||||||
 | 
					    final byte[] sessionId = "session".getBytes(StandardCharsets.UTF_8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    when(pendingAccountsManager.getCodeForNumber(number)).thenReturn(Optional.of(
 | 
				
			||||||
 | 
					        new StoredVerificationCode(code, System.currentTimeMillis(), "push", null, sessionId)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    when(registrationServiceClient.checkVerificationCode(any(), any(), any()))
 | 
				
			||||||
 | 
					        .thenReturn(CompletableFuture.completedFuture(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final AccountIdentityResponse accountIdentityResponse =
 | 
				
			||||||
 | 
					        resources.getJerseyTest()
 | 
				
			||||||
 | 
					            .target("/v1/accounts/number")
 | 
				
			||||||
 | 
					            .request()
 | 
				
			||||||
 | 
					            .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
 | 
				
			||||||
 | 
					            .put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null, null, null),
 | 
				
			||||||
 | 
					                MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    verify(registrationServiceClient).checkVerificationCode(sessionId, code, AccountController.REGISTRATION_RPC_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), eq(number), any(), any(), any(), any());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assertThat(accountIdentityResponse.getUuid()).isEqualTo(AuthHelper.VALID_UUID);
 | 
				
			||||||
 | 
					    assertThat(accountIdentityResponse.getNumber()).isEqualTo(number);
 | 
				
			||||||
 | 
					    assertThat(accountIdentityResponse.getPni()).isNotEqualTo(AuthHelper.VALID_PNI);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Test
 | 
					  @Test
 | 
				
			||||||
  void testChangePhoneNumberImpossibleNumber() throws Exception {
 | 
					  void testChangePhoneNumberImpossibleNumber() throws Exception {
 | 
				
			||||||
    final String number = "This is not a real phone number";
 | 
					    final String number = "This is not a real phone number";
 | 
				
			||||||
| 
						 | 
					@ -1544,6 +1573,32 @@ class AccountControllerTest {
 | 
				
			||||||
    verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any(), any(), any());
 | 
					    verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any(), any(), any());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  void testChangePhoneNumberIncorrectCodeWithRegistrationService() throws Exception {
 | 
				
			||||||
 | 
					    final String number = "+18005559876";
 | 
				
			||||||
 | 
					    final String code = "987654";
 | 
				
			||||||
 | 
					    final byte[] sessionId = "session-id".getBytes(StandardCharsets.UTF_8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    when(pendingAccountsManager.getCodeForNumber(number)).thenReturn(Optional.of(
 | 
				
			||||||
 | 
					        new StoredVerificationCode(code, System.currentTimeMillis(), "push", null, sessionId)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    when(registrationServiceClient.checkVerificationCode(any(), any(), any()))
 | 
				
			||||||
 | 
					        .thenReturn(CompletableFuture.completedFuture(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final Response response =
 | 
				
			||||||
 | 
					        resources.getJerseyTest()
 | 
				
			||||||
 | 
					            .target("/v1/accounts/number")
 | 
				
			||||||
 | 
					            .request()
 | 
				
			||||||
 | 
					            .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
 | 
				
			||||||
 | 
					            .put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null, null, null),
 | 
				
			||||||
 | 
					                MediaType.APPLICATION_JSON_TYPE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    verify(registrationServiceClient).checkVerificationCode(sessionId, code, AccountController.REGISTRATION_RPC_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assertThat(response.getStatus()).isEqualTo(403);
 | 
				
			||||||
 | 
					    verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any(), any(), any());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Test
 | 
					  @Test
 | 
				
			||||||
  void testChangePhoneNumberExistingAccountReglockNotRequired() throws Exception {
 | 
					  void testChangePhoneNumberExistingAccountReglockNotRequired() throws Exception {
 | 
				
			||||||
    final String number = "+18005559876";
 | 
					    final String number = "+18005559876";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue