Add reregistration flag to account creation response
This commit is contained in:
parent
26c348520f
commit
8d0d0d61f1
|
@ -36,6 +36,7 @@ import java.util.Optional;
|
||||||
import org.whispersystems.textsecuregcm.auth.BasicAuthorizationHeader;
|
import org.whispersystems.textsecuregcm.auth.BasicAuthorizationHeader;
|
||||||
import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager;
|
import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager;
|
||||||
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.AccountCreationResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.RegistrationLockFailure;
|
import org.whispersystems.textsecuregcm.entities.RegistrationLockFailure;
|
||||||
|
@ -100,7 +101,7 @@ public class RegistrationController {
|
||||||
@ApiResponse(responseCode = "429", description = "Too many attempts", headers = @Header(
|
@ApiResponse(responseCode = "429", description = "Too many attempts", headers = @Header(
|
||||||
name = "Retry-After",
|
name = "Retry-After",
|
||||||
description = "If present, an positive integer indicating the number of seconds before a subsequent attempt could succeed"))
|
description = "If present, an positive integer indicating the number of seconds before a subsequent attempt could succeed"))
|
||||||
public AccountIdentityResponse register(
|
public AccountCreationResponse register(
|
||||||
@HeaderParam(HttpHeaders.AUTHORIZATION) @NotNull final BasicAuthorizationHeader authorizationHeader,
|
@HeaderParam(HttpHeaders.AUTHORIZATION) @NotNull final BasicAuthorizationHeader authorizationHeader,
|
||||||
@HeaderParam(HeaderUtils.X_SIGNAL_AGENT) final String signalAgent,
|
@HeaderParam(HeaderUtils.X_SIGNAL_AGENT) final String signalAgent,
|
||||||
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgent,
|
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgent,
|
||||||
|
@ -166,12 +167,14 @@ public class RegistrationController {
|
||||||
Tag.of(VERIFICATION_TYPE_TAG_NAME, verificationType.name())))
|
Tag.of(VERIFICATION_TYPE_TAG_NAME, verificationType.name())))
|
||||||
.increment();
|
.increment();
|
||||||
|
|
||||||
return new AccountIdentityResponseBuilder(account)
|
final AccountIdentityResponse identityResponse = new AccountIdentityResponseBuilder(account)
|
||||||
// If there was an existing account, return whether it could have had something in the storage service
|
// If there was an existing account, return whether it could have had something in the storage service
|
||||||
.storageCapable(existingAccount
|
.storageCapable(existingAccount
|
||||||
.map(a -> a.hasCapability(DeviceCapability.STORAGE))
|
.map(a -> a.hasCapability(DeviceCapability.STORAGE))
|
||||||
.orElse(false))
|
.orElse(false))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
return new AccountCreationResponse(identityResponse, existingAccount.isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.entities;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
// Note, this class cannot be converted into a record because @JsonUnwrapped does not work with records until 2.19. We are on 2.18 until Dropwizard’s BOM updates.
|
||||||
|
// https://github.com/FasterXML/jackson-databind/issues/1467
|
||||||
|
public class AccountCreationResponse {
|
||||||
|
|
||||||
|
@JsonUnwrapped
|
||||||
|
private AccountIdentityResponse identityResponse;
|
||||||
|
|
||||||
|
@Schema(description = "If true, there was an existing account registered for this number")
|
||||||
|
private boolean reregistration;
|
||||||
|
|
||||||
|
public AccountCreationResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountCreationResponse(AccountIdentityResponse identityResponse, boolean reregistration) {
|
||||||
|
this.identityResponse = identityResponse;
|
||||||
|
this.reregistration = reregistration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReregistration() {
|
||||||
|
return reregistration;
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.CsvSource;
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
import org.junitpioneer.jupiter.cartesian.ArgumentSets;
|
import org.junitpioneer.jupiter.cartesian.ArgumentSets;
|
||||||
import org.junitpioneer.jupiter.cartesian.CartesianTest;
|
import org.junitpioneer.jupiter.cartesian.CartesianTest;
|
||||||
import org.signal.libsignal.protocol.IdentityKey;
|
import org.signal.libsignal.protocol.IdentityKey;
|
||||||
|
@ -59,6 +60,8 @@ import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager;
|
||||||
import org.whispersystems.textsecuregcm.auth.RegistrationLockError;
|
import org.whispersystems.textsecuregcm.auth.RegistrationLockError;
|
||||||
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.AccountCreationResponse;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.ApnRegistrationId;
|
import org.whispersystems.textsecuregcm.entities.ApnRegistrationId;
|
||||||
import org.whispersystems.textsecuregcm.entities.DeviceActivationRequest;
|
import org.whispersystems.textsecuregcm.entities.DeviceActivationRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.ECSignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.ECSignedPreKey;
|
||||||
|
@ -748,6 +751,8 @@ class RegistrationControllerTest {
|
||||||
|
|
||||||
try (Response response = request.post(Entity.json(registrationRequest))) {
|
try (Response response = request.post(Entity.json(registrationRequest))) {
|
||||||
assertEquals(200, response.getStatus());
|
assertEquals(200, response.getStatus());
|
||||||
|
final AccountIdentityResponse identityResponse = response.readEntity(AccountIdentityResponse.class);
|
||||||
|
assertEquals(accountIdentifier, identityResponse.uuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(accountsManager).create(
|
verify(accountsManager).create(
|
||||||
|
@ -760,6 +765,34 @@ class RegistrationControllerTest {
|
||||||
any());
|
any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(booleans = {true, false})
|
||||||
|
void reregistrationFlag(final boolean existingAccount) throws InterruptedException {
|
||||||
|
final RegistrationServiceSession registrationSession =
|
||||||
|
new RegistrationServiceSession(new byte[16], NUMBER, true, null, null, null, SESSION_EXPIRATION_SECONDS);
|
||||||
|
when(registrationServiceClient.getSession(any(), any()))
|
||||||
|
.thenReturn(CompletableFuture.completedFuture(Optional.of(registrationSession)));
|
||||||
|
|
||||||
|
final Optional<Account> maybeAccount = Optional.ofNullable(existingAccount ? mock(Account.class) : null);
|
||||||
|
when(accountsManager.getByE164(any())).thenReturn(maybeAccount);
|
||||||
|
|
||||||
|
final Account account = mock(Account.class);
|
||||||
|
when(account.getPrimaryDevice()).thenReturn(mock(Device.class));
|
||||||
|
|
||||||
|
when(accountsManager.create(any(), any(), any(), any(), any(), any(), any()))
|
||||||
|
.thenReturn(account);
|
||||||
|
|
||||||
|
final Invocation.Builder request = resources.getJerseyTest()
|
||||||
|
.target("/v1/registration")
|
||||||
|
.request()
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getProvisioningAuthHeader(NUMBER, PASSWORD));
|
||||||
|
try (Response response = request.post(Entity.json(requestJson("sessionId")))) {
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
final AccountCreationResponse creationResponse = response.readEntity(AccountCreationResponse.class);
|
||||||
|
assertEquals(existingAccount, creationResponse.isReregistration());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean accountAttributesEqual(final AccountAttributes a, final AccountAttributes b) {
|
private static boolean accountAttributesEqual(final AccountAttributes a, final AccountAttributes b) {
|
||||||
return a.getFetchesMessages() == b.getFetchesMessages()
|
return a.getFetchesMessages() == b.getFetchesMessages()
|
||||||
&& a.getRegistrationId() == b.getRegistrationId()
|
&& a.getRegistrationId() == b.getRegistrationId()
|
||||||
|
|
Loading…
Reference in New Issue