Update ChangeNumber to allow reset of registration IDs.
This commit is contained in:
parent
5cfb133f79
commit
7001ad1445
|
@ -25,6 +25,7 @@ import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
@ -86,6 +87,7 @@ import org.whispersystems.textsecuregcm.storage.AbusiveHostRules;
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||||
import org.whispersystems.textsecuregcm.storage.ChangeNumberManager;
|
import org.whispersystems.textsecuregcm.storage.ChangeNumberManager;
|
||||||
|
import org.whispersystems.textsecuregcm.storage.ChangeNumberManager.DeviceUpdate;
|
||||||
import org.whispersystems.textsecuregcm.storage.Device;
|
import org.whispersystems.textsecuregcm.storage.Device;
|
||||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||||
import org.whispersystems.textsecuregcm.storage.StoredVerificationCodeManager;
|
import org.whispersystems.textsecuregcm.storage.StoredVerificationCodeManager;
|
||||||
|
@ -408,22 +410,27 @@ public class AccountController {
|
||||||
throw new ForbiddenException();
|
throw new ForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.getDeviceSignedPrekeys() != null && !request.getDeviceSignedPrekeys().isEmpty()) {
|
Map<Long, DeviceUpdate> devices = Collections.emptyMap();
|
||||||
if (request.getDeviceMessages() == null || request.getDeviceMessages().size() != request.getDeviceSignedPrekeys().size() - 1) {
|
if (request.getDeviceUpdates() != null && !request.getDeviceUpdates().isEmpty()) {
|
||||||
// device_messages should exist and be one shorter than device_signed_prekeys, since it doesn't have the primary's key.
|
devices = request.getDeviceUpdates().entrySet().stream()
|
||||||
throw new WebApplicationException(Response.status(400).build());
|
.collect(Collectors.toMap(
|
||||||
}
|
e -> e.getKey(),
|
||||||
|
e -> new DeviceUpdate(e.getValue().getSignedPhoneNumberIdentityPreKey(), e.getValue().getMessage(), e.getValue().getRegistrationID())));
|
||||||
try {
|
try {
|
||||||
// Checks that all except master ID are in device messages
|
// Checks that all except master ID are in device messages
|
||||||
|
List<IncomingMessage> deviceMessages = devices.entrySet().stream()
|
||||||
|
.map(e -> e.getValue().message())
|
||||||
|
.filter(e -> e != null)
|
||||||
|
.collect(Collectors.toList());
|
||||||
MessageValidation.validateCompleteDeviceList(
|
MessageValidation.validateCompleteDeviceList(
|
||||||
authenticatedAccount.getAccount(), request.getDeviceMessages(),
|
authenticatedAccount.getAccount(), deviceMessages,
|
||||||
IncomingMessage::getDestinationDeviceId, true, Optional.of(Device.MASTER_ID));
|
IncomingMessage::getDestinationDeviceId, true, Optional.of(Device.MASTER_ID));
|
||||||
MessageValidation.validateRegistrationIds(
|
MessageValidation.validateRegistrationIds(
|
||||||
authenticatedAccount.getAccount(), request.getDeviceMessages(),
|
authenticatedAccount.getAccount(), deviceMessages,
|
||||||
IncomingMessage::getDestinationDeviceId, IncomingMessage::getDestinationRegistrationId);
|
IncomingMessage::getDestinationDeviceId, IncomingMessage::getDestinationRegistrationId);
|
||||||
// Checks that all including master ID are in signed prekeys
|
// Checks that all including master ID are in signed prekeys
|
||||||
MessageValidation.validateCompleteDeviceList(
|
MessageValidation.validateCompleteDeviceList(
|
||||||
authenticatedAccount.getAccount(), request.getDeviceSignedPrekeys().entrySet(),
|
authenticatedAccount.getAccount(), devices.entrySet(),
|
||||||
e -> e.getKey(), false, Optional.empty());
|
e -> e.getKey(), false, Optional.empty());
|
||||||
} catch (MismatchedDevicesException e) {
|
} catch (MismatchedDevicesException e) {
|
||||||
throw new WebApplicationException(Response.status(409)
|
throw new WebApplicationException(Response.status(409)
|
||||||
|
@ -437,9 +444,6 @@ public class AccountController {
|
||||||
.entity(new StaleDevices(e.getStaleDevices()))
|
.entity(new StaleDevices(e.getStaleDevices()))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
} else if (request.getDeviceMessages() != null && !request.getDeviceMessages().isEmpty()) {
|
|
||||||
// device_messages shouldn't exist without device_signed_prekeys.
|
|
||||||
throw new WebApplicationException(Response.status(400).build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String number = request.getNumber();
|
final String number = request.getNumber();
|
||||||
|
@ -470,8 +474,7 @@ public class AccountController {
|
||||||
final Account updatedAccount = changeNumberManager.changeNumber(
|
final Account updatedAccount = changeNumberManager.changeNumber(
|
||||||
authenticatedAccount.getAccount(),
|
authenticatedAccount.getAccount(),
|
||||||
request.getNumber(),
|
request.getNumber(),
|
||||||
Optional.ofNullable(request.getDeviceSignedPrekeys()).orElse(Collections.emptyMap()),
|
devices);
|
||||||
Optional.ofNullable(request.getDeviceMessages()).orElse(Collections.emptyList()));
|
|
||||||
|
|
||||||
return new AccountIdentityResponse(
|
return new AccountIdentityResponse(
|
||||||
updatedAccount.getUuid(),
|
updatedAccount.getUuid(),
|
||||||
|
|
|
@ -9,7 +9,6 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ChangePhoneNumberRequest {
|
public class ChangePhoneNumberRequest {
|
||||||
|
@ -26,26 +25,48 @@ public class ChangePhoneNumberRequest {
|
||||||
@Nullable
|
@Nullable
|
||||||
final String registrationLock;
|
final String registrationLock;
|
||||||
|
|
||||||
@JsonProperty("device_messages")
|
@JsonProperty("deviceUpdates")
|
||||||
@Nullable
|
@Nullable
|
||||||
final List<IncomingMessage> deviceMessages;
|
final Map<Long, DeviceUpdate> deviceUpdates;
|
||||||
|
|
||||||
@JsonProperty("device_signed_prekeys")
|
public static class DeviceUpdate {
|
||||||
@Nullable
|
|
||||||
final Map<Long, SignedPreKey> deviceSignedPrekeys;
|
private final IncomingMessage message;
|
||||||
|
private final SignedPreKey signedPhoneNumberIdentityPreKey;
|
||||||
|
private final Integer registrationID;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public DeviceUpdate(
|
||||||
|
@JsonProperty("message") final IncomingMessage message,
|
||||||
|
@JsonProperty("signedPhoneNumberIdentityPrekey") final SignedPreKey signedPhoneNumberIdentityPreKey,
|
||||||
|
@JsonProperty("registratonId") final Integer registrationID) {
|
||||||
|
this.message = message;
|
||||||
|
this.signedPhoneNumberIdentityPreKey = signedPhoneNumberIdentityPreKey;
|
||||||
|
this.registrationID = registrationID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncomingMessage getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignedPreKey getSignedPhoneNumberIdentityPreKey() {
|
||||||
|
return signedPhoneNumberIdentityPreKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getRegistrationID() {
|
||||||
|
return registrationID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public ChangePhoneNumberRequest(@JsonProperty("number") final String number,
|
public ChangePhoneNumberRequest(@JsonProperty("number") final String number,
|
||||||
@JsonProperty("code") final String code,
|
@JsonProperty("code") final String code,
|
||||||
@JsonProperty("reglock") @Nullable final String registrationLock,
|
@JsonProperty("reglock") @Nullable final String registrationLock,
|
||||||
@JsonProperty("device_messages") @Nullable final List<IncomingMessage> deviceMessages,
|
@JsonProperty("deviceUpdates") @Nullable final Map<Long, DeviceUpdate> deviceUpdates) {
|
||||||
@JsonProperty("device_signed_prekeys") @Nullable final Map<Long, SignedPreKey> deviceSignedPrekeys) {
|
|
||||||
|
|
||||||
this.number = number;
|
this.number = number;
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.registrationLock = registrationLock;
|
this.registrationLock = registrationLock;
|
||||||
this.deviceMessages = deviceMessages;
|
this.deviceUpdates = deviceUpdates;
|
||||||
this.deviceSignedPrekeys = deviceSignedPrekeys;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNumber() {
|
public String getNumber() {
|
||||||
|
@ -62,12 +83,5 @@ public class ChangePhoneNumberRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<IncomingMessage> getDeviceMessages() {
|
public Map<Long, DeviceUpdate> getDeviceUpdates() { return deviceUpdates; }
|
||||||
return deviceMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Map<Long, SignedPreKey> getDeviceSignedPrekeys() {
|
|
||||||
return deviceSignedPrekeys;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
import org.whispersystems.textsecuregcm.push.MessageSender;
|
import org.whispersystems.textsecuregcm.push.MessageSender;
|
||||||
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -32,11 +31,13 @@ public class ChangeNumberManager {
|
||||||
this.accountsManager = accountsManager;
|
this.accountsManager = accountsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record DeviceUpdate(SignedPreKey signedPhoneNumberIdentityPreKey, IncomingMessage message, Integer registrationID) {
|
||||||
|
}
|
||||||
|
|
||||||
public Account changeNumber(
|
public Account changeNumber(
|
||||||
@NotNull Account account,
|
@NotNull Account account,
|
||||||
@NotNull final String number,
|
@NotNull final String number,
|
||||||
@NotNull final Map<Long, SignedPreKey> deviceSignedPrekeys,
|
@NotNull final Map<Long, DeviceUpdate> deviceUpdates) throws InterruptedException {
|
||||||
@NotNull final List<IncomingMessage> deviceMessages) throws InterruptedException {
|
|
||||||
|
|
||||||
final Account updatedAccount;
|
final Account updatedAccount;
|
||||||
if (number.equals(account.getNumber())) {
|
if (number.equals(account.getNumber())) {
|
||||||
|
@ -51,14 +52,17 @@ public class ChangeNumberManager {
|
||||||
// This makes it so the client can resend a request they didn't get a response for (timeout, etc)
|
// This makes it so the client can resend a request they didn't get a response for (timeout, etc)
|
||||||
// to make sure their messages sent and prekeys were updated, even if the first time around the
|
// to make sure their messages sent and prekeys were updated, even if the first time around the
|
||||||
// server crashed at/above this point.
|
// server crashed at/above this point.
|
||||||
if (deviceSignedPrekeys != null && !deviceSignedPrekeys.isEmpty()) {
|
if (deviceUpdates != null && !deviceUpdates.isEmpty()) {
|
||||||
for (Map.Entry<Long, SignedPreKey> entry : deviceSignedPrekeys.entrySet()) {
|
for (Map.Entry<Long, DeviceUpdate> entry : deviceUpdates.entrySet()) {
|
||||||
|
DeviceUpdate deviceUpdate = entry.getValue();
|
||||||
accountsManager.updateDevice(updatedAccount, entry.getKey(),
|
accountsManager.updateDevice(updatedAccount, entry.getKey(),
|
||||||
d -> d.setPhoneNumberIdentitySignedPreKey(entry.getValue()));
|
device -> {
|
||||||
|
if (deviceUpdate.signedPhoneNumberIdentityPreKey() != null) device.setPhoneNumberIdentitySignedPreKey(deviceUpdate.signedPhoneNumberIdentityPreKey());
|
||||||
|
if (deviceUpdate.registrationID() != null) device.setRegistrationId(deviceUpdate.registrationID());
|
||||||
|
});
|
||||||
|
if (deviceUpdate.message() != null) {
|
||||||
|
sendMessageToSelf(updatedAccount, updatedAccount.getDevice(entry.getKey()), deviceUpdate.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IncomingMessage message : deviceMessages) {
|
|
||||||
sendMessageToSelf(updatedAccount, updatedAccount.getDevice(message.getDestinationDeviceId()), message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return updatedAccount;
|
return updatedAccount;
|
||||||
|
|
|
@ -12,9 +12,9 @@ import org.mockito.stubbing.Answer;
|
||||||
import org.whispersystems.textsecuregcm.entities.IncomingMessage;
|
import org.whispersystems.textsecuregcm.entities.IncomingMessage;
|
||||||
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
import org.whispersystems.textsecuregcm.push.MessageSender;
|
import org.whispersystems.textsecuregcm.push.MessageSender;
|
||||||
|
import org.whispersystems.textsecuregcm.storage.ChangeNumberManager.DeviceUpdate;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -60,7 +60,7 @@ public class ChangeNumberManagerTest {
|
||||||
void changeNumberNoMessages() throws Exception {
|
void changeNumberNoMessages() throws Exception {
|
||||||
Account account = mock(Account.class);
|
Account account = mock(Account.class);
|
||||||
when(account.getNumber()).thenReturn("+18005551234");
|
when(account.getNumber()).thenReturn("+18005551234");
|
||||||
changeNumberManager.changeNumber(account, "+18025551234", Collections.EMPTY_MAP, Collections.EMPTY_LIST);
|
changeNumberManager.changeNumber(account, "+18025551234", Collections.EMPTY_MAP);
|
||||||
verify(accountsManager).changeNumber(account, "+18025551234");
|
verify(accountsManager).changeNumber(account, "+18025551234");
|
||||||
verify(accountsManager, never()).updateDevice(any(), eq(1L), any());
|
verify(accountsManager, never()).updateDevice(any(), eq(1L), any());
|
||||||
verify(messageSender, never()).sendMessage(eq(account), any(), any(), eq(false));
|
verify(messageSender, never()).sendMessage(eq(account), any(), any(), eq(false));
|
||||||
|
@ -70,8 +70,8 @@ public class ChangeNumberManagerTest {
|
||||||
void changeNumberSetPrimaryDevicePrekey() throws Exception {
|
void changeNumberSetPrimaryDevicePrekey() throws Exception {
|
||||||
Account account = mock(Account.class);
|
Account account = mock(Account.class);
|
||||||
when(account.getNumber()).thenReturn("+18005551234");
|
when(account.getNumber()).thenReturn("+18005551234");
|
||||||
var prekeys = Map.of(1L, new SignedPreKey());
|
var devices = Map.of(1L, new DeviceUpdate(new SignedPreKey(), null, null));
|
||||||
changeNumberManager.changeNumber(account, "+18025551234", prekeys, Collections.EMPTY_LIST);
|
changeNumberManager.changeNumber(account, "+18025551234", devices);
|
||||||
verify(accountsManager).changeNumber(account, "+18025551234");
|
verify(accountsManager).changeNumber(account, "+18025551234");
|
||||||
verify(accountsManager).updateDevice(any(), eq(1L), any());
|
verify(accountsManager).updateDevice(any(), eq(1L), any());
|
||||||
verify(messageSender, never()).sendMessage(eq(account), any(), any(), eq(false));
|
verify(messageSender, never()).sendMessage(eq(account), any(), any(), eq(false));
|
||||||
|
@ -84,11 +84,13 @@ public class ChangeNumberManagerTest {
|
||||||
when(account.getUuid()).thenReturn(UUID.randomUUID());
|
when(account.getUuid()).thenReturn(UUID.randomUUID());
|
||||||
Device d2 = mock(Device.class);
|
Device d2 = mock(Device.class);
|
||||||
when(account.getDevice(2L)).thenReturn(Optional.of(d2));
|
when(account.getDevice(2L)).thenReturn(Optional.of(d2));
|
||||||
var prekeys = Map.of(1L, new SignedPreKey(), 2L, new SignedPreKey());
|
|
||||||
IncomingMessage msg = mock(IncomingMessage.class);
|
IncomingMessage msg = mock(IncomingMessage.class);
|
||||||
when(msg.getDestinationDeviceId()).thenReturn(2L);
|
when(msg.getDestinationDeviceId()).thenReturn(2L);
|
||||||
when(msg.getContent()).thenReturn(Base64.encodeBase64String(new byte[]{1}));
|
when(msg.getContent()).thenReturn(Base64.encodeBase64String(new byte[]{1}));
|
||||||
changeNumberManager.changeNumber(account, "+18025551234", prekeys, List.of(msg));
|
var devices = Map.of(
|
||||||
|
1L, new DeviceUpdate(new SignedPreKey(), null, null),
|
||||||
|
2L, new DeviceUpdate(new SignedPreKey(), msg, null));
|
||||||
|
changeNumberManager.changeNumber(account, "+18025551234", devices);
|
||||||
verify(accountsManager).changeNumber(account, "+18025551234");
|
verify(accountsManager).changeNumber(account, "+18025551234");
|
||||||
verify(accountsManager).updateDevice(any(), eq(1L), any());
|
verify(accountsManager).updateDevice(any(), eq(1L), any());
|
||||||
verify(accountsManager).updateDevice(any(), eq(2L), any());
|
verify(accountsManager).updateDevice(any(), eq(2L), any());
|
||||||
|
|
|
@ -30,7 +30,7 @@ class DeviceTest {
|
||||||
|
|
||||||
private static Stream<Arguments> testIsEnabled() {
|
private static Stream<Arguments> testIsEnabled() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
// master fetchesMessages apnId gcmId signedPreKey lastSeen expectEnabled
|
// master fetchesMessages apnId gcmId signedPhoneNumberIdentityPreKey lastSeen expectEnabled
|
||||||
Arguments.of(true, false, null, null, null, Duration.ofDays(60), false),
|
Arguments.of(true, false, null, null, null, Duration.ofDays(60), false),
|
||||||
Arguments.of(true, false, null, null, null, Duration.ofDays(1), false),
|
Arguments.of(true, false, null, null, null, Duration.ofDays(1), false),
|
||||||
Arguments.of(true, false, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false),
|
Arguments.of(true, false, null, null, mock(SignedPreKey.class), Duration.ofDays(60), false),
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.ApnRegistrationId;
|
import org.whispersystems.textsecuregcm.entities.ApnRegistrationId;
|
||||||
import org.whispersystems.textsecuregcm.entities.ChangePhoneNumberRequest;
|
import org.whispersystems.textsecuregcm.entities.ChangePhoneNumberRequest;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.ChangePhoneNumberRequest.DeviceUpdate;
|
||||||
import org.whispersystems.textsecuregcm.entities.GcmRegistrationId;
|
import org.whispersystems.textsecuregcm.entities.GcmRegistrationId;
|
||||||
import org.whispersystems.textsecuregcm.entities.IncomingMessage;
|
import org.whispersystems.textsecuregcm.entities.IncomingMessage;
|
||||||
import org.whispersystems.textsecuregcm.entities.RegistrationLock;
|
import org.whispersystems.textsecuregcm.entities.RegistrationLock;
|
||||||
|
@ -250,7 +251,7 @@ class AccountControllerTest {
|
||||||
when(accountsManager.setUsername(AuthHelper.VALID_ACCOUNT, "takenusername"))
|
when(accountsManager.setUsername(AuthHelper.VALID_ACCOUNT, "takenusername"))
|
||||||
.thenThrow(new UsernameNotAvailableException());
|
.thenThrow(new UsernameNotAvailableException());
|
||||||
|
|
||||||
when(changeNumberManager.changeNumber(any(), any(), any(), any())).thenAnswer((Answer<Account>) invocation -> {
|
when(changeNumberManager.changeNumber(any(), any(), any())).thenAnswer((Answer<Account>) invocation -> {
|
||||||
final Account account = invocation.getArgument(0, Account.class);
|
final Account account = invocation.getArgument(0, Account.class);
|
||||||
final String number = invocation.getArgument(1, String.class);
|
final String number = invocation.getArgument(1, String.class);
|
||||||
|
|
||||||
|
@ -1248,10 +1249,10 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
|
MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
|
||||||
|
|
||||||
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), eq(number), any(), any());
|
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), eq(number), any());
|
||||||
|
|
||||||
assertThat(accountIdentityResponse.getUuid()).isEqualTo(AuthHelper.VALID_UUID);
|
assertThat(accountIdentityResponse.getUuid()).isEqualTo(AuthHelper.VALID_UUID);
|
||||||
assertThat(accountIdentityResponse.getNumber()).isEqualTo(number);
|
assertThat(accountIdentityResponse.getNumber()).isEqualTo(number);
|
||||||
|
@ -1268,12 +1269,12 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(400);
|
assertThat(response.getStatus()).isEqualTo(400);
|
||||||
assertThat(response.readEntity(String.class)).isBlank();
|
assertThat(response.readEntity(String.class)).isBlank();
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1286,7 +1287,7 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(400);
|
assertThat(response.getStatus()).isEqualTo(400);
|
||||||
|
@ -1295,7 +1296,7 @@ class AccountControllerTest {
|
||||||
assertThat(responseEntity.getOriginalNumber()).isEqualTo(number);
|
assertThat(responseEntity.getOriginalNumber()).isEqualTo(number);
|
||||||
assertThat(responseEntity.getNormalizedNumber()).isEqualTo("+447700900111");
|
assertThat(responseEntity.getNormalizedNumber()).isEqualTo("+447700900111");
|
||||||
|
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1305,10 +1306,10 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(AuthHelper.VALID_NUMBER, "567890", null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(AuthHelper.VALID_NUMBER, "567890", null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
|
MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
|
||||||
|
|
||||||
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), any(), any(), any());
|
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1323,11 +1324,11 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(403);
|
assertThat(response.getStatus()).isEqualTo(403);
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1343,11 +1344,11 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code + "-incorrect", null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code + "-incorrect", null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(403);
|
assertThat(response.getStatus()).isEqualTo(403);
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1373,11 +1374,11 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), any(), any(), any());
|
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1403,11 +1404,11 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(423);
|
assertThat(response.getStatus()).isEqualTo(423);
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1435,11 +1436,11 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, reglock, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, reglock, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(423);
|
assertThat(response.getStatus()).isEqualTo(423);
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1467,11 +1468,11 @@ class AccountControllerTest {
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, reglock, null, null),
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, reglock, null),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(200);
|
assertThat(response.getStatus()).isEqualTo(200);
|
||||||
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), any(), any(), any());
|
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1488,11 +1489,14 @@ class AccountControllerTest {
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null,
|
.put(Entity.entity(new ChangePhoneNumberRequest(number, code, null,
|
||||||
List.of(new IncomingMessage(1, null, 1, 1, "foo")), null),
|
Map.of(1L, new DeviceUpdate(
|
||||||
|
new IncomingMessage(1, null, 1, 1, "foo"),
|
||||||
|
null,
|
||||||
|
null))),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(400);
|
assertThat(response.getStatus()).isEqualTo(409);
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1517,14 +1521,19 @@ class AccountControllerTest {
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(
|
.put(Entity.entity(new ChangePhoneNumberRequest(
|
||||||
number, code, null,
|
number, code, null,
|
||||||
List.of(
|
Map.of(
|
||||||
|
2L, new DeviceUpdate(
|
||||||
new IncomingMessage(1, null, 2, 1, "foo"),
|
new IncomingMessage(1, null, 2, 1, "foo"),
|
||||||
new IncomingMessage(1, null, 4, 1, "foo")),
|
null,
|
||||||
Map.of(1L, new SignedPreKey(), 2L, new SignedPreKey(), 3L, new SignedPreKey())),
|
null),
|
||||||
|
4L, new DeviceUpdate(
|
||||||
|
new IncomingMessage(1, null, 4, 1, "foo"),
|
||||||
|
null,
|
||||||
|
null))),
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(409);
|
assertThat(response.getStatus()).isEqualTo(409);
|
||||||
verify(changeNumberManager, never()).changeNumber(any(), any(), any(), any());
|
verify(changeNumberManager, never()).changeNumber(any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1546,10 +1555,19 @@ class AccountControllerTest {
|
||||||
when(pendingAccountsManager.getCodeForNumber(number)).thenReturn(Optional.of(
|
when(pendingAccountsManager.getCodeForNumber(number)).thenReturn(Optional.of(
|
||||||
new StoredVerificationCode(code, System.currentTimeMillis(), "push", null)));
|
new StoredVerificationCode(code, System.currentTimeMillis(), "push", null)));
|
||||||
|
|
||||||
var deviceMessages = List.of(
|
Map<Long, DeviceUpdate> perDevice = Map.of(
|
||||||
|
1L, new DeviceUpdate(
|
||||||
|
null,
|
||||||
|
new SignedPreKey(),
|
||||||
|
null),
|
||||||
|
2L, new DeviceUpdate(
|
||||||
new IncomingMessage(1, null, 2, 2, "content2"),
|
new IncomingMessage(1, null, 2, 2, "content2"),
|
||||||
new IncomingMessage(1, null, 3, 3, "content3"));
|
new SignedPreKey(),
|
||||||
var deviceKeys = Map.of(1L, new SignedPreKey(), 2L, new SignedPreKey(), 3L, new SignedPreKey());
|
null),
|
||||||
|
3L, new DeviceUpdate(
|
||||||
|
new IncomingMessage(1, null, 3, 3, "content3"),
|
||||||
|
new SignedPreKey(),
|
||||||
|
null));
|
||||||
|
|
||||||
final AccountIdentityResponse accountIdentityResponse =
|
final AccountIdentityResponse accountIdentityResponse =
|
||||||
resources.getJerseyTest()
|
resources.getJerseyTest()
|
||||||
|
@ -1557,12 +1575,10 @@ class AccountControllerTest {
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(
|
.put(Entity.entity(new ChangePhoneNumberRequest(
|
||||||
number, code, null,
|
number, code, null, perDevice),
|
||||||
deviceMessages,
|
|
||||||
deviceKeys),
|
|
||||||
MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
|
MediaType.APPLICATION_JSON_TYPE), AccountIdentityResponse.class);
|
||||||
|
|
||||||
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), eq(number), any(), any());
|
verify(changeNumberManager).changeNumber(eq(AuthHelper.VALID_ACCOUNT), eq(number), any());
|
||||||
|
|
||||||
assertThat(accountIdentityResponse.getUuid()).isEqualTo(AuthHelper.VALID_UUID);
|
assertThat(accountIdentityResponse.getUuid()).isEqualTo(AuthHelper.VALID_UUID);
|
||||||
assertThat(accountIdentityResponse.getNumber()).isEqualTo(number);
|
assertThat(accountIdentityResponse.getNumber()).isEqualTo(number);
|
||||||
|
@ -1588,17 +1604,27 @@ class AccountControllerTest {
|
||||||
when(pendingAccountsManager.getCodeForNumber(number)).thenReturn(Optional.of(
|
when(pendingAccountsManager.getCodeForNumber(number)).thenReturn(Optional.of(
|
||||||
new StoredVerificationCode(code, System.currentTimeMillis(), "push", null)));
|
new StoredVerificationCode(code, System.currentTimeMillis(), "push", null)));
|
||||||
|
|
||||||
|
Map<Long, DeviceUpdate> perDevice = Map.of(
|
||||||
|
1L, new DeviceUpdate(
|
||||||
|
null,
|
||||||
|
new SignedPreKey(),
|
||||||
|
null),
|
||||||
|
2L, new DeviceUpdate(
|
||||||
|
new IncomingMessage(1, null, 2, 1, "foo"),
|
||||||
|
new SignedPreKey(),
|
||||||
|
null),
|
||||||
|
3L, new DeviceUpdate(
|
||||||
|
new IncomingMessage(1, null, 3, 1, "foo"),
|
||||||
|
new SignedPreKey(),
|
||||||
|
null));
|
||||||
|
|
||||||
final Response response =
|
final Response response =
|
||||||
resources.getJerseyTest()
|
resources.getJerseyTest()
|
||||||
.target("/v1/accounts/number")
|
.target("/v1/accounts/number")
|
||||||
.request()
|
.request()
|
||||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||||
.put(Entity.entity(new ChangePhoneNumberRequest(
|
.put(Entity.entity(new ChangePhoneNumberRequest(
|
||||||
number, code, null,
|
number, code, null, perDevice),
|
||||||
List.of(
|
|
||||||
new IncomingMessage(1, null, 2, 1, "foo"),
|
|
||||||
new IncomingMessage(1, null, 3, 1, "foo")),
|
|
||||||
Map.of(1L, new SignedPreKey(), 2L, new SignedPreKey(), 3L, new SignedPreKey())),
|
|
||||||
MediaType.APPLICATION_JSON_TYPE));
|
MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
assertThat(response.getStatus()).isEqualTo(410);
|
assertThat(response.getStatus()).isEqualTo(410);
|
||||||
|
|
Loading…
Reference in New Issue