Require PNI-associated registration IDs for new devices

This commit is contained in:
Jon Chambers 2023-11-27 11:32:17 -05:00 committed by Jon Chambers
parent 3980dec123
commit 01fde4f9ca
11 changed files with 74 additions and 69 deletions

View File

@ -28,6 +28,8 @@ public class TestUser {
private final int registrationId; private final int registrationId;
private final int pniRegistrationId;
private final IdentityKeyPair aciIdentityKey; private final IdentityKeyPair aciIdentityKey;
private final Map<Byte, TestDevice> devices = new ConcurrentHashMap<>(); private final Map<Byte, TestDevice> devices = new ConcurrentHashMap<>();
@ -54,11 +56,13 @@ public class TestUser {
final IdentityKeyPair pniIdentityKey = IdentityKeyPair.generate(); final IdentityKeyPair pniIdentityKey = IdentityKeyPair.generate();
// registration id // registration id
final int registrationId = KeyHelper.generateRegistrationId(false); final int registrationId = KeyHelper.generateRegistrationId(false);
final int pniRegistrationId = KeyHelper.generateRegistrationId(false);
// uak // uak
final byte[] unidentifiedAccessKey = RandomUtils.nextBytes(UnidentifiedAccessUtil.UNIDENTIFIED_ACCESS_KEY_LENGTH); final byte[] unidentifiedAccessKey = RandomUtils.nextBytes(UnidentifiedAccessUtil.UNIDENTIFIED_ACCESS_KEY_LENGTH);
return new TestUser( return new TestUser(
registrationId, registrationId,
pniRegistrationId,
aciIdentityKey, aciIdentityKey,
phoneNumber, phoneNumber,
pniIdentityKey, pniIdentityKey,
@ -69,6 +73,7 @@ public class TestUser {
public TestUser( public TestUser(
final int registrationId, final int registrationId,
final int pniRegistrationId,
final IdentityKeyPair aciIdentityKey, final IdentityKeyPair aciIdentityKey,
final String phoneNumber, final String phoneNumber,
final IdentityKeyPair pniIdentityKey, final IdentityKeyPair pniIdentityKey,
@ -76,6 +81,7 @@ public class TestUser {
final String accountPassword, final String accountPassword,
final byte[] registrationPassword) { final byte[] registrationPassword) {
this.registrationId = registrationId; this.registrationId = registrationId;
this.pniRegistrationId = pniRegistrationId;
this.aciIdentityKey = aciIdentityKey; this.aciIdentityKey = aciIdentityKey;
this.phoneNumber = phoneNumber; this.phoneNumber = phoneNumber;
this.pniIdentityKey = pniIdentityKey; this.pniIdentityKey = pniIdentityKey;
@ -118,7 +124,7 @@ public class TestUser {
} }
public AccountAttributes accountAttributes() { public AccountAttributes accountAttributes() {
return new AccountAttributes(true, registrationId, "", "", true, new Device.DeviceCapabilities(false, false, false, false)) return new AccountAttributes(true, registrationId, pniRegistrationId, "", "", true, new Device.DeviceCapabilities(false, false, false, false))
.withUnidentifiedAccessKey(unidentifiedAccessKey) .withUnidentifiedAccessKey(unidentifiedAccessKey)
.withRecoveryPassword(registrationPassword); .withRecoveryPassword(registrationPassword);
} }

View File

@ -231,7 +231,7 @@ public class AccountController {
d.setLastSeen(Util.todayInMillis()); d.setLastSeen(Util.todayInMillis());
d.setCapabilities(attributes.getCapabilities()); d.setCapabilities(attributes.getCapabilities());
d.setRegistrationId(attributes.getRegistrationId()); d.setRegistrationId(attributes.getRegistrationId());
attributes.getPhoneNumberIdentityRegistrationId().ifPresent(d::setPhoneNumberIdentityRegistrationId); d.setPhoneNumberIdentityRegistrationId(attributes.getPhoneNumberIdentityRegistrationId());
d.setUserAgent(userAgent); d.setUserAgent(userAgent);
}); });

View File

@ -396,7 +396,7 @@ public class DeviceController {
device.setAuthTokenHash(SaltedTokenHash.generateFor(password)); device.setAuthTokenHash(SaltedTokenHash.generateFor(password));
device.setFetchesMessages(accountAttributes.getFetchesMessages()); device.setFetchesMessages(accountAttributes.getFetchesMessages());
device.setRegistrationId(accountAttributes.getRegistrationId()); device.setRegistrationId(accountAttributes.getRegistrationId());
accountAttributes.getPhoneNumberIdentityRegistrationId().ifPresent(device::setPhoneNumberIdentityRegistrationId); device.setPhoneNumberIdentityRegistrationId(accountAttributes.getPhoneNumberIdentityRegistrationId());
device.setLastSeen(Util.todayInMillis()); device.setLastSeen(Util.todayInMillis());
device.setCreated(System.currentTimeMillis()); device.setCreated(System.currentTimeMillis());
device.setCapabilities(accountAttributes.getCapabilities()); device.setCapabilities(accountAttributes.getCapabilities());

View File

@ -10,7 +10,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.validation.constraints.AssertTrue; import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
@ -28,7 +27,7 @@ public class AccountAttributes {
private int registrationId; private int registrationId;
@JsonProperty("pniRegistrationId") @JsonProperty("pniRegistrationId")
private Integer phoneNumberIdentityRegistrationId; private int phoneNumberIdentityRegistrationId;
@JsonProperty @JsonProperty
@Size(max = 204, message = "This field must be less than 50 characters") @Size(max = 204, message = "This field must be less than 50 characters")
@ -62,12 +61,14 @@ public class AccountAttributes {
public AccountAttributes( public AccountAttributes(
final boolean fetchesMessages, final boolean fetchesMessages,
final int registrationId, final int registrationId,
final int phoneNumberIdentifierRegistrationId,
final String name, final String name,
final String registrationLock, final String registrationLock,
final boolean discoverableByPhoneNumber, final boolean discoverableByPhoneNumber,
final DeviceCapabilities capabilities) { final DeviceCapabilities capabilities) {
this.fetchesMessages = fetchesMessages; this.fetchesMessages = fetchesMessages;
this.registrationId = registrationId; this.registrationId = registrationId;
this.phoneNumberIdentityRegistrationId = phoneNumberIdentifierRegistrationId;
this.name = name; this.name = name;
this.registrationLock = registrationLock; this.registrationLock = registrationLock;
this.discoverableByPhoneNumber = discoverableByPhoneNumber; this.discoverableByPhoneNumber = discoverableByPhoneNumber;
@ -82,8 +83,8 @@ public class AccountAttributes {
return registrationId; return registrationId;
} }
public OptionalInt getPhoneNumberIdentityRegistrationId() { public int getPhoneNumberIdentityRegistrationId() {
return phoneNumberIdentityRegistrationId != null ? OptionalInt.of(phoneNumberIdentityRegistrationId) : OptionalInt.empty(); return phoneNumberIdentityRegistrationId;
} }
public String getName() { public String getName() {
@ -133,7 +134,6 @@ public class AccountAttributes {
@AssertTrue @AssertTrue
public boolean isEachRegistrationIdValid() { public boolean isEachRegistrationIdValid() {
return validRegistrationId(registrationId) && return validRegistrationId(registrationId) && validRegistrationId(phoneNumberIdentityRegistrationId);
(phoneNumberIdentityRegistrationId == null || validRegistrationId(phoneNumberIdentityRegistrationId));
} }
} }

View File

@ -200,7 +200,7 @@ public class AccountsManager {
device.setAuthTokenHash(SaltedTokenHash.generateFor(password)); device.setAuthTokenHash(SaltedTokenHash.generateFor(password));
device.setFetchesMessages(accountAttributes.getFetchesMessages()); device.setFetchesMessages(accountAttributes.getFetchesMessages());
device.setRegistrationId(accountAttributes.getRegistrationId()); device.setRegistrationId(accountAttributes.getRegistrationId());
accountAttributes.getPhoneNumberIdentityRegistrationId().ifPresent(device::setPhoneNumberIdentityRegistrationId); device.setPhoneNumberIdentityRegistrationId(accountAttributes.getPhoneNumberIdentityRegistrationId());
device.setName(accountAttributes.getName()); device.setName(accountAttributes.getName());
device.setCapabilities(accountAttributes.getCapabilities()); device.setCapabilities(accountAttributes.getCapabilities());
device.setCreated(System.currentTimeMillis()); device.setCreated(System.currentTimeMillis());

View File

@ -762,7 +762,7 @@ class AccountControllerTest {
.target("/v1/accounts/attributes/") .target("/v1/accounts/attributes/")
.request() .request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new AccountAttributes(false, 2222, null, null, true, null))); .put(Entity.json(new AccountAttributes(false, 2222, 3333, null, null, true, null)));
assertThat(response.getStatus()).isEqualTo(204); assertThat(response.getStatus()).isEqualTo(204);
} }
@ -774,7 +774,7 @@ class AccountControllerTest {
.target("/v1/accounts/attributes/") .target("/v1/accounts/attributes/")
.request() .request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.UNDISCOVERABLE_UUID, AuthHelper.UNDISCOVERABLE_PASSWORD)) .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.UNDISCOVERABLE_UUID, AuthHelper.UNDISCOVERABLE_PASSWORD))
.put(Entity.json(new AccountAttributes(false, 2222, null, null, true, null))); .put(Entity.json(new AccountAttributes(false, 2222, 3333, null, null, true, null)));
assertThat(response.getStatus()).isEqualTo(204); assertThat(response.getStatus()).isEqualTo(204);
} }
@ -787,7 +787,7 @@ class AccountControllerTest {
.target("/v1/accounts/attributes/") .target("/v1/accounts/attributes/")
.request() .request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.UNDISCOVERABLE_UUID, AuthHelper.UNDISCOVERABLE_PASSWORD)) .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.UNDISCOVERABLE_UUID, AuthHelper.UNDISCOVERABLE_PASSWORD))
.put(Entity.json(new AccountAttributes(false, 2222, null, null, true, null) .put(Entity.json(new AccountAttributes(false, 2222, 3333, null, null, true, null)
.withRecoveryPassword(recoveryPassword))); .withRecoveryPassword(recoveryPassword)));
assertThat(response.getStatus()).isEqualTo(204); assertThat(response.getStatus()).isEqualTo(204);
@ -801,7 +801,7 @@ class AccountControllerTest {
.target("/v1/accounts/attributes/") .target("/v1/accounts/attributes/")
.request() .request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new AccountAttributes(false, 2222, null, null, false, null))); .put(Entity.json(new AccountAttributes(false, 2222, 3333, null, null, false, null)));
assertThat(response.getStatus()).isEqualTo(204); assertThat(response.getStatus()).isEqualTo(204);
} }
@ -813,7 +813,7 @@ class AccountControllerTest {
.target("/v1/accounts/attributes/") .target("/v1/accounts/attributes/")
.request() .request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new AccountAttributes(false, 2222, null, null, false, null) .put(Entity.json(new AccountAttributes(false, 2222, 3333, null, null, false, null)
.withUnidentifiedAccessKey(new byte[7]))); .withUnidentifiedAccessKey(new byte[7])));
assertThat(response.getStatus()).isEqualTo(422); assertThat(response.getStatus()).isEqualTo(422);

View File

@ -196,8 +196,8 @@ class DeviceControllerTest {
.target("/v1/devices/" + deviceCode.verificationCode()) .target("/v1/devices/" + deviceCode.verificationCode())
.request() .request()
.header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1")) .header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1"))
.put(Entity.entity(new AccountAttributes(false, 1234, null, .put(Entity.entity(new AccountAttributes(false, 1234, 5678,
null, true, null), null, null, true, null),
MediaType.APPLICATION_JSON_TYPE), MediaType.APPLICATION_JSON_TYPE),
DeviceResponse.class); DeviceResponse.class);
@ -223,8 +223,8 @@ class DeviceControllerTest {
.target("/v1/devices/" + verificationToken) .target("/v1/devices/" + verificationToken)
.request() .request()
.header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1")) .header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1"))
.put(Entity.entity(new AccountAttributes(false, 1234, null, .put(Entity.entity(new AccountAttributes(false, 1234, 5678,
null, true, null), null, null, true, null),
MediaType.APPLICATION_JSON_TYPE)); MediaType.APPLICATION_JSON_TYPE));
assertEquals(Response.Status.FORBIDDEN.getStatusCode(), response.getStatus()); assertEquals(Response.Status.FORBIDDEN.getStatusCode(), response.getStatus());
@ -261,8 +261,8 @@ class DeviceControllerTest {
.target("/v1/devices/" + verificationToken) .target("/v1/devices/" + verificationToken)
.request() .request()
.header("Authorization", "This is not a valid authorization header") .header("Authorization", "This is not a valid authorization header")
.put(Entity.entity(new AccountAttributes(false, 1234, null, .put(Entity.entity(new AccountAttributes(false, 1234, 5678,
null, true, null), null, null, true, null),
MediaType.APPLICATION_JSON_TYPE)); MediaType.APPLICATION_JSON_TYPE));
assertEquals(401, response.getStatus()); assertEquals(401, response.getStatus());
@ -308,7 +308,7 @@ class DeviceControllerTest {
when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
new AccountAttributes(fetchesMessages, 1234, null, null, true, null), new AccountAttributes(fetchesMessages, 1234, 5678, null, null, true, null),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, apnRegistrationId, gcmRegistrationId)); new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, apnRegistrationId, gcmRegistrationId));
final DeviceResponse response = resources.getJerseyTest() final DeviceResponse response = resources.getJerseyTest()
@ -389,7 +389,7 @@ class DeviceControllerTest {
when(commands.get(anyString())).thenReturn(""); when(commands.get(anyString())).thenReturn("");
final LinkDeviceRequest request = new LinkDeviceRequest(deviceController.generateVerificationToken(AuthHelper.VALID_UUID), final LinkDeviceRequest request = new LinkDeviceRequest(deviceController.generateVerificationToken(AuthHelper.VALID_UUID),
new AccountAttributes(false, 1234, null, null, true, null), new AccountAttributes(false, 1234, 5678, null, null, true, null),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.of(new GcmRegistrationId("gcm-id")))); new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.of(new GcmRegistrationId("gcm-id"))));
try (final Response response = resources.getJerseyTest() try (final Response response = resources.getJerseyTest()
@ -437,7 +437,7 @@ class DeviceControllerTest {
when(account.getIdentityKey(IdentityType.PNI)).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey())); when(account.getIdentityKey(IdentityType.PNI)).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey()));
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
new AccountAttributes(fetchesMessages, 1234, null, null, true, null), new AccountAttributes(fetchesMessages, 1234, 5678, null, null, true, null),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, apnRegistrationId, gcmRegistrationId)); new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, apnRegistrationId, gcmRegistrationId));
try (final Response response = resources.getJerseyTest() try (final Response response = resources.getJerseyTest()
@ -485,7 +485,7 @@ class DeviceControllerTest {
when(account.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey); when(account.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey);
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
new AccountAttributes(true, 1234, null, null, true, null), new AccountAttributes(true, 1234, 5678, null, null, true, null),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.empty())); new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.empty()));
try (final Response response = resources.getJerseyTest() try (final Response response = resources.getJerseyTest()
@ -543,7 +543,7 @@ class DeviceControllerTest {
when(account.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey); when(account.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey);
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
new AccountAttributes(true, 1234, null, null, true, null), new AccountAttributes(true, 1234, 5678, null, null, true, null),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.empty())); new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.empty()));
try (final Response response = resources.getJerseyTest() try (final Response response = resources.getJerseyTest()
@ -578,7 +578,7 @@ class DeviceControllerTest {
@ParameterizedTest @ParameterizedTest
@MethodSource @MethodSource
void linkDeviceRegistrationId(final int registrationId, final int expectedStatusCode) { void linkDeviceRegistrationId(final int registrationId, final int pniRegistrationId, final int expectedStatusCode) {
final Device existingDevice = mock(Device.class); final Device existingDevice = mock(Device.class);
when(existingDevice.getId()).thenReturn(Device.PRIMARY_ID); when(existingDevice.getId()).thenReturn(Device.PRIMARY_ID);
when(AuthHelper.VALID_ACCOUNT.getDevices()).thenReturn(List.of(existingDevice)); when(AuthHelper.VALID_ACCOUNT.getDevices()).thenReturn(List.of(existingDevice));
@ -604,7 +604,7 @@ class DeviceControllerTest {
when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); when(keysManager.storePqLastResort(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(), final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
new AccountAttributes(false, registrationId, null, null, true, null), new AccountAttributes(false, registrationId, pniRegistrationId, null, null, true, null),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.of(new ApnRegistrationId("apn", null)), Optional.empty())); new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.of(new ApnRegistrationId("apn", null)), Optional.empty()));
try (final Response response = resources.getJerseyTest() try (final Response response = resources.getJerseyTest()
@ -618,11 +618,15 @@ class DeviceControllerTest {
private static Stream<Arguments> linkDeviceRegistrationId() { private static Stream<Arguments> linkDeviceRegistrationId() {
return Stream.of( return Stream.of(
Arguments.of(0x3FFF, 200), Arguments.of(0x3FFF, 0x3FFF, 200),
Arguments.of(0, 422), Arguments.of(0, 0x3FFF, 422),
Arguments.of(-1, 422), Arguments.of(-1, 0x3FFF, 422),
Arguments.of(0x3FFF + 1, 422), Arguments.of(0x3FFF + 1, 0x3FFF, 422),
Arguments.of(Integer.MAX_VALUE, 422) Arguments.of(Integer.MAX_VALUE, 0x3FFF, 422),
Arguments.of(0x3FFF, 0, 422),
Arguments.of(0x3FFF, -1, 422),
Arguments.of(0x3FFF, 0x3FFF + 1, 422),
Arguments.of(0x3FFF, Integer.MAX_VALUE, 422)
); );
} }
@ -661,7 +665,7 @@ class DeviceControllerTest {
.target("/v1/devices/" + deviceCode.verificationCode() + "-incorrect") .target("/v1/devices/" + deviceCode.verificationCode() + "-incorrect")
.request() .request()
.header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1")) .header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1"))
.put(Entity.entity(new AccountAttributes(false, 1234, null, null, true, null), .put(Entity.entity(new AccountAttributes(false, 1234, 5678, null, null, true, null),
MediaType.APPLICATION_JSON_TYPE)); MediaType.APPLICATION_JSON_TYPE));
assertThat(response.getStatus()).isEqualTo(403); assertThat(response.getStatus()).isEqualTo(403);
@ -676,7 +680,7 @@ class DeviceControllerTest {
.request() .request()
.header("Authorization", .header("Authorization",
AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER_TWO, AuthHelper.VALID_PASSWORD_TWO)) AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER_TWO, AuthHelper.VALID_PASSWORD_TWO))
.put(Entity.entity(new AccountAttributes(false, 1234, null, null, true, null), .put(Entity.entity(new AccountAttributes(false, 1234, 5678, null, null, true, null),
MediaType.APPLICATION_JSON_TYPE)); MediaType.APPLICATION_JSON_TYPE));
assertThat(response.getStatus()).isEqualTo(403); assertThat(response.getStatus()).isEqualTo(403);
@ -711,7 +715,7 @@ class DeviceControllerTest {
.target("/v1/devices/" + verificationToken) .target("/v1/devices/" + verificationToken)
.request() .request()
.header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1")) .header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1"))
.put(Entity.entity(new AccountAttributes(false, 1234, .put(Entity.entity(new AccountAttributes(false, 1234, 5678,
"this is a really long name that is longer than 80 characters it's so long that it's even longer than 204 characters. that's a lot of characters. we're talking lots and lots and lots of characters. 12345678", "this is a really long name that is longer than 80 characters it's so long that it's even longer than 204 characters. that's a lot of characters. we're talking lots and lots and lots of characters. 12345678",
null, true, null), null, true, null),
MediaType.APPLICATION_JSON_TYPE)); MediaType.APPLICATION_JSON_TYPE));
@ -725,7 +729,7 @@ class DeviceControllerTest {
DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true,
false, true); false, true);
AccountAttributes accountAttributes = AccountAttributes accountAttributes =
new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); new AccountAttributes(false, 1234, 5678, null, null, true, deviceCapabilities);
final String verificationToken = deviceController.generateVerificationToken(AuthHelper.VALID_UUID); final String verificationToken = deviceController.generateVerificationToken(AuthHelper.VALID_UUID);
@ -739,7 +743,7 @@ class DeviceControllerTest {
assertThat(response.getStatus()).isEqualTo(409); assertThat(response.getStatus()).isEqualTo(409);
deviceCapabilities = new DeviceCapabilities(true, true, true, true); deviceCapabilities = new DeviceCapabilities(true, true, true, true);
accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); accountAttributes = new AccountAttributes(false, 1234, 5678, null, null, true, deviceCapabilities);
response = resources response = resources
.getJerseyTest() .getJerseyTest()
.target("/v1/devices/" + verificationToken) .target("/v1/devices/" + verificationToken)
@ -782,7 +786,7 @@ class DeviceControllerTest {
void deviceDowngradePaymentActivationTest(boolean paymentActivation) { void deviceDowngradePaymentActivationTest(boolean paymentActivation) {
// Update when we start returning true value of capability & restricting downgrades // Update when we start returning true value of capability & restricting downgrades
DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, paymentActivation); DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, paymentActivation);
AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, 5678, null, null, true, deviceCapabilities);
final String verificationToken = deviceController.generateVerificationToken(AuthHelper.VALID_UUID); final String verificationToken = deviceController.generateVerificationToken(AuthHelper.VALID_UUID);

View File

@ -141,8 +141,8 @@ class RegistrationControllerTest {
static Stream<Arguments> invalidRegistrationId() { static Stream<Arguments> invalidRegistrationId() {
return Stream.of( return Stream.of(
Arguments.of(Optional.of(1), Optional.of(1), 200), Arguments.of(Optional.of(1), Optional.of(1), 200),
Arguments.of(Optional.of(1), Optional.empty(), 200), Arguments.of(Optional.of(1), Optional.empty(), 422),
Arguments.of(Optional.of(0x3FFF), Optional.empty(), 200), Arguments.of(Optional.of(0x3FFF), Optional.empty(), 422),
Arguments.of(Optional.empty(), Optional.of(1), 422), Arguments.of(Optional.empty(), Optional.of(1), 422),
Arguments.of(Optional.of(Integer.MAX_VALUE), Optional.empty(), 422), Arguments.of(Optional.of(Integer.MAX_VALUE), Optional.empty(), 422),
Arguments.of(Optional.of(0x3FFF + 1), Optional.empty(), 422), Arguments.of(Optional.of(0x3FFF + 1), Optional.empty(), 422),
@ -170,7 +170,7 @@ class RegistrationControllerTest {
when(accountsManager.create(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any())) when(accountsManager.create(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()))
.thenReturn(account); .thenReturn(account);
final String json = requestJson("sessionId", new byte[0], true, registrationId.orElse(0), pniRegistrationId); final String json = requestJson("sessionId", new byte[0], true, registrationId.orElse(0), pniRegistrationId.orElse(0));
try (Response response = request.post(Entity.json(json))) { try (Response response = request.post(Entity.json(json))) {
assertEquals(statusCode, response.getStatus()); assertEquals(statusCode, response.getStatus());
@ -409,7 +409,7 @@ class RegistrationControllerTest {
.target("/v1/registration") .target("/v1/registration")
.request() .request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getProvisioningAuthHeader(NUMBER, PASSWORD)); .header(HttpHeaders.AUTHORIZATION, AuthHelper.getProvisioningAuthHeader(NUMBER, PASSWORD));
try (Response response = request.post(Entity.json(requestJson("sessionId", new byte[0], skipDeviceTransfer, 1, Optional.of(2))))) { try (Response response = request.post(Entity.json(requestJson("sessionId", new byte[0], skipDeviceTransfer, 1, 2)))) {
assertEquals(expectedStatus, response.getStatus()); assertEquals(expectedStatus, response.getStatus());
} }
} }
@ -477,10 +477,10 @@ class RegistrationControllerTest {
} }
final AccountAttributes fetchesMessagesAccountAttributes = final AccountAttributes fetchesMessagesAccountAttributes =
new AccountAttributes(true, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false)); new AccountAttributes(true, 1, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false));
final AccountAttributes pushAccountAttributes = final AccountAttributes pushAccountAttributes =
new AccountAttributes(false, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false)); new AccountAttributes(false, 1, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false));
return Stream.of( return Stream.of(
// "Fetches messages" is true, but an APNs token is provided // "Fetches messages" is true, but an APNs token is provided
@ -566,7 +566,7 @@ class RegistrationControllerTest {
} }
final AccountAttributes accountAttributes = final AccountAttributes accountAttributes =
new AccountAttributes(true, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false)); new AccountAttributes(true, 1, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false));
return Stream.of( return Stream.of(
// Signed PNI EC pre-key is missing // Signed PNI EC pre-key is missing
@ -746,10 +746,10 @@ class RegistrationControllerTest {
} }
final AccountAttributes fetchesMessagesAccountAttributes = final AccountAttributes fetchesMessagesAccountAttributes =
new AccountAttributes(true, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false)); new AccountAttributes(true, 1, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false));
final AccountAttributes pushAccountAttributes = final AccountAttributes pushAccountAttributes =
new AccountAttributes(false, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false)); new AccountAttributes(false, 1, 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false));
final String apnsToken = "apns-token"; final String apnsToken = "apns-token";
final String apnsVoipToken = "apns-voip-token"; final String apnsVoipToken = "apns-voip-token";
@ -853,7 +853,7 @@ class RegistrationControllerTest {
final byte[] recoveryPassword, final byte[] recoveryPassword,
final boolean skipDeviceTransfer, final boolean skipDeviceTransfer,
final int registrationId, final int registrationId,
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") final Optional<Integer> pniRegistrationId) { int pniRegistrationId) {
final ECKeyPair aciIdentityKeyPair = Curve.generateKeyPair(); final ECKeyPair aciIdentityKeyPair = Curve.generateKeyPair();
final ECKeyPair pniIdentityKeyPair = Curve.generateKeyPair(); final ECKeyPair pniIdentityKeyPair = Curve.generateKeyPair();
@ -861,10 +861,8 @@ class RegistrationControllerTest {
final IdentityKey aciIdentityKey = new IdentityKey(aciIdentityKeyPair.getPublicKey()); final IdentityKey aciIdentityKey = new IdentityKey(aciIdentityKeyPair.getPublicKey());
final IdentityKey pniIdentityKey = new IdentityKey(pniIdentityKeyPair.getPublicKey()); final IdentityKey pniIdentityKey = new IdentityKey(pniIdentityKeyPair.getPublicKey());
final AccountAttributes accountAttributes = new AccountAttributes(true, registrationId, "name", "reglock", true, final AccountAttributes accountAttributes = new AccountAttributes(true, registrationId, pniRegistrationId, "name", "reglock",
new Device.DeviceCapabilities(true, true, true, true)); true, new Device.DeviceCapabilities(true, true, true, true));
pniRegistrationId.ifPresent(accountAttributes::setPhoneNumberIdentityRegistrationId);
final RegistrationRequest request = new RegistrationRequest( final RegistrationRequest request = new RegistrationRequest(
Base64.getEncoder().encodeToString(sessionId.getBytes(StandardCharsets.UTF_8)), Base64.getEncoder().encodeToString(sessionId.getBytes(StandardCharsets.UTF_8)),
@ -892,14 +890,14 @@ class RegistrationControllerTest {
* Valid request JSON with the given session ID * Valid request JSON with the given session ID
*/ */
private static String requestJson(final String sessionId) { private static String requestJson(final String sessionId) {
return requestJson(sessionId, new byte[0], false, 1, Optional.of(2)); return requestJson(sessionId, new byte[0], false, 1, 2);
} }
/** /**
* Valid request JSON with the given Recovery Password * Valid request JSON with the given Recovery Password
*/ */
private static String requestJsonRecoveryPassword(final byte[] recoveryPassword) { private static String requestJsonRecoveryPassword(final byte[] recoveryPassword) {
return requestJson("", recoveryPassword, false, 1, Optional.of(2)); return requestJson("", recoveryPassword, false, 1, 2);
} }
/** /**

View File

@ -174,12 +174,10 @@ public class AccountCreationIntegrationTest {
final AccountAttributes accountAttributes = new AccountAttributes(deliveryChannels.fetchesMessages(), final AccountAttributes accountAttributes = new AccountAttributes(deliveryChannels.fetchesMessages(),
registrationId, registrationId,
pniRegistrationId,
deviceName, deviceName,
registrationLockSecret, registrationLockSecret,
discoverableByPhoneNumber, discoverableByPhoneNumber, deviceCapabilities);
deviceCapabilities);
accountAttributes.setPhoneNumberIdentityRegistrationId(pniRegistrationId);
final List<AccountBadge> badges = new ArrayList<>(List.of(new AccountBadge( final List<AccountBadge> badges = new ArrayList<>(List.of(new AccountBadge(
RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8),
@ -259,7 +257,7 @@ public class AccountCreationIntegrationTest {
final Account originalAccount = accountsManager.create(number, final Account originalAccount = accountsManager.create(number,
RandomStringUtils.randomAlphanumeric(16), RandomStringUtils.randomAlphanumeric(16),
"OWI", "OWI",
new AccountAttributes(true, 1, "name", "registration-lock", false, new Device.DeviceCapabilities(false, false, false, false)), new AccountAttributes(true, 1, 1, "name", "registration-lock", false, new Device.DeviceCapabilities(false, false, false, false)),
Collections.emptyList(), Collections.emptyList(),
new IdentityKey(aciKeyPair.getPublicKey()), new IdentityKey(aciKeyPair.getPublicKey()),
new IdentityKey(pniKeyPair.getPublicKey()), new IdentityKey(pniKeyPair.getPublicKey()),
@ -288,13 +286,12 @@ public class AccountCreationIntegrationTest {
final AccountAttributes accountAttributes = new AccountAttributes(deliveryChannels.fetchesMessages(), final AccountAttributes accountAttributes = new AccountAttributes(deliveryChannels.fetchesMessages(),
registrationId, registrationId,
pniRegistrationId,
deviceName, deviceName,
registrationLockSecret, registrationLockSecret,
discoverableByPhoneNumber, discoverableByPhoneNumber,
deviceCapabilities); deviceCapabilities);
accountAttributes.setPhoneNumberIdentityRegistrationId(pniRegistrationId);
final List<AccountBadge> badges = new ArrayList<>(List.of(new AccountBadge( final List<AccountBadge> badges = new ArrayList<>(List.of(new AccountBadge(
RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8),
CLOCK.instant().plus(Duration.ofDays(7)), CLOCK.instant().plus(Duration.ofDays(7)),

View File

@ -178,7 +178,7 @@ class AccountsManagerChangeNumberIntegrationTest {
final int rotatedPniRegistrationId = 17; final int rotatedPniRegistrationId = 17;
final ECKeyPair rotatedPniIdentityKeyPair = Curve.generateKeyPair(); final ECKeyPair rotatedPniIdentityKeyPair = Curve.generateKeyPair();
final ECSignedPreKey rotatedSignedPreKey = KeysHelper.signedECPreKey(1L, rotatedPniIdentityKeyPair); final ECSignedPreKey rotatedSignedPreKey = KeysHelper.signedECPreKey(1L, rotatedPniIdentityKeyPair);
final AccountAttributes accountAttributes = new AccountAttributes(true, rotatedPniRegistrationId + 1, "test", null, true, new Device.DeviceCapabilities(false, false, false, false)); final AccountAttributes accountAttributes = new AccountAttributes(true, rotatedPniRegistrationId + 1, rotatedPniRegistrationId, "test", null, true, new Device.DeviceCapabilities(false, false, false, false));
final Account account = AccountsHelper.createAccount(accountsManager, originalNumber, accountAttributes); final Account account = AccountsHelper.createAccount(accountsManager, originalNumber, accountAttributes);
account.getPrimaryDevice().orElseThrow().setSignedPreKey(KeysHelper.signedECPreKey(1, rotatedPniIdentityKeyPair)); account.getPrimaryDevice().orElseThrow().setSignedPreKey(KeysHelper.signedECPreKey(1, rotatedPniIdentityKeyPair));

View File

@ -935,7 +935,7 @@ class AccountsManagerTest {
when(accounts.create(any(), any())).thenReturn(true); when(accounts.create(any(), any())).thenReturn(true);
final String e164 = "+18005550123"; final String e164 = "+18005550123";
final AccountAttributes attributes = new AccountAttributes(false, 0, null, null, true, null); final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null, true, null);
createAccount(e164, attributes); createAccount(e164, attributes);
@ -955,7 +955,7 @@ class AccountsManagerTest {
}); });
final String e164 = "+18005550123"; final String e164 = "+18005550123";
final AccountAttributes attributes = new AccountAttributes(false, 0, null, null, true, null); final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null, true, null);
createAccount(e164, attributes); createAccount(e164, attributes);
@ -979,7 +979,7 @@ class AccountsManagerTest {
when(accounts.create(any(), any())).thenReturn(true); when(accounts.create(any(), any())).thenReturn(true);
final String e164 = "+18005550123"; final String e164 = "+18005550123";
final AccountAttributes attributes = new AccountAttributes(false, 0, null, null, true, null); final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null, true, null);
createAccount(e164, attributes); createAccount(e164, attributes);
@ -995,7 +995,7 @@ class AccountsManagerTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(booleans = {true, false}) @ValueSource(booleans = {true, false})
void testCreateWithDiscoverability(final boolean discoverable) throws InterruptedException { void testCreateWithDiscoverability(final boolean discoverable) throws InterruptedException {
final AccountAttributes attributes = new AccountAttributes(false, 0, null, null, discoverable, null); final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null, discoverable, null);
final Account account = createAccount("+18005550123", attributes); final Account account = createAccount("+18005550123", attributes);
assertEquals(discoverable, account.isDiscoverableByPhoneNumber()); assertEquals(discoverable, account.isDiscoverableByPhoneNumber());
@ -1004,8 +1004,8 @@ class AccountsManagerTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(booleans = {true, false}) @ValueSource(booleans = {true, false})
void testCreateWithStorageCapability(final boolean hasStorage) throws InterruptedException { void testCreateWithStorageCapability(final boolean hasStorage) throws InterruptedException {
final AccountAttributes attributes = new AccountAttributes(false, 0, null, null, true, final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null,
new DeviceCapabilities(hasStorage, false, false, false)); true, new DeviceCapabilities(hasStorage, false, false, false));
final Account account = createAccount("+18005550123", attributes); final Account account = createAccount("+18005550123", attributes);