Retire the `pni` device capability
This commit is contained in:
parent
dcdf401f64
commit
5ff092e541
|
@ -126,7 +126,7 @@ public class TestUser {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountAttributes accountAttributes() {
|
public AccountAttributes accountAttributes() {
|
||||||
return new AccountAttributes(true, registrationId, pniRegistrationId, "".getBytes(StandardCharsets.UTF_8), "", true, new Device.DeviceCapabilities(false, false, false, false))
|
return new AccountAttributes(true, registrationId, pniRegistrationId, "".getBytes(StandardCharsets.UTF_8), "", true, new Device.DeviceCapabilities(false, false, false))
|
||||||
.withUnidentifiedAccessKey(unidentifiedAccessKey)
|
.withUnidentifiedAccessKey(unidentifiedAccessKey)
|
||||||
.withRecoveryPassword(registrationPassword);
|
.withRecoveryPassword(registrationPassword);
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,8 +220,6 @@ public class DeviceController {
|
||||||
|
|
||||||
if (capabilities == null) {
|
if (capabilities == null) {
|
||||||
throw new WebApplicationException(Response.status(422, "Missing device capabilities").build());
|
throw new WebApplicationException(Response.status(422, "Missing device capabilities").build());
|
||||||
} else if (isCapabilityDowngrade(account, capabilities)) {
|
|
||||||
throw new WebApplicationException(Response.status(409).build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String signalAgent;
|
final String signalAgent;
|
||||||
|
@ -355,10 +353,6 @@ public class DeviceController {
|
||||||
return Optional.of(aci);
|
return Optional.of(aci);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isCapabilityDowngrade(Account account, DeviceCapabilities capabilities) {
|
|
||||||
return account.isPniSupported() && !capabilities.pni();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getUsedTokenKey(final String token) {
|
private static String getUsedTokenKey(final String token) {
|
||||||
return "usedToken::" + token;
|
return "usedToken::" + token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,9 @@ package org.whispersystems.textsecuregcm.entities;
|
||||||
|
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
|
|
||||||
public record UserCapabilities(boolean paymentActivation, boolean pni) {
|
public record UserCapabilities(boolean paymentActivation,
|
||||||
|
// TODO Remove the PNI capability entirely on or after 2024-05-14
|
||||||
|
boolean pni) {
|
||||||
|
|
||||||
public static UserCapabilities createForAccount(final Account account) {
|
public static UserCapabilities createForAccount(final Account account) {
|
||||||
return new UserCapabilities(account.isPaymentActivationSupported(), true);
|
return new UserCapabilities(account.isPaymentActivationSupported(), true);
|
||||||
|
|
|
@ -201,7 +201,6 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||||
d -> d.setCapabilities(new Device.DeviceCapabilities(
|
d -> d.setCapabilities(new Device.DeviceCapabilities(
|
||||||
request.getStorage(),
|
request.getStorage(),
|
||||||
request.getTransfer(),
|
request.getTransfer(),
|
||||||
request.getPni(),
|
|
||||||
request.getPaymentActivation())))))
|
request.getPaymentActivation())))))
|
||||||
.thenReturn(SetCapabilitiesResponse.newBuilder().build());
|
.thenReturn(SetCapabilitiesResponse.newBuilder().build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,10 +262,6 @@ public class Account {
|
||||||
.orElse(false);
|
.orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPniSupported() {
|
|
||||||
return allEnabledDevicesHaveCapability(DeviceCapabilities::pni);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPaymentActivationSupported() {
|
public boolean isPaymentActivationSupported() {
|
||||||
return allEnabledDevicesHaveCapability(DeviceCapabilities::paymentActivation);
|
return allEnabledDevicesHaveCapability(DeviceCapabilities::paymentActivation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,6 +251,6 @@ public class Device {
|
||||||
return this.userAgent;
|
return this.userAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record DeviceCapabilities(boolean storage, boolean transfer, boolean pni, boolean paymentActivation) {
|
public record DeviceCapabilities(boolean storage, boolean transfer, boolean paymentActivation) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,8 +147,7 @@ message ClearPushTokenResponse {}
|
||||||
message SetCapabilitiesRequest {
|
message SetCapabilitiesRequest {
|
||||||
bool storage = 1;
|
bool storage = 1;
|
||||||
bool transfer = 2;
|
bool transfer = 2;
|
||||||
bool pni = 3;
|
bool paymentActivation = 3;
|
||||||
bool paymentActivation = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message SetCapabilitiesResponse {}
|
message SetCapabilitiesResponse {}
|
||||||
|
|
|
@ -567,8 +567,6 @@ class AccountControllerV2Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void pniKeyDistributionSuccess() throws Exception {
|
void pniKeyDistributionSuccess() throws Exception {
|
||||||
when(AuthHelper.VALID_ACCOUNT.isPniSupported()).thenReturn(true);
|
|
||||||
|
|
||||||
final AccountIdentityResponse accountIdentityResponse =
|
final AccountIdentityResponse accountIdentityResponse =
|
||||||
resources.getJerseyTest()
|
resources.getJerseyTest()
|
||||||
.target("/v2/accounts/phone_number_identity_key_distribution")
|
.target("/v2/accounts/phone_number_identity_key_distribution")
|
||||||
|
|
|
@ -141,7 +141,6 @@ class DeviceControllerTest {
|
||||||
when(account.getUuid()).thenReturn(AuthHelper.VALID_UUID);
|
when(account.getUuid()).thenReturn(AuthHelper.VALID_UUID);
|
||||||
when(account.getPhoneNumberIdentifier()).thenReturn(AuthHelper.VALID_PNI);
|
when(account.getPhoneNumberIdentifier()).thenReturn(AuthHelper.VALID_PNI);
|
||||||
when(account.isEnabled()).thenReturn(false);
|
when(account.isEnabled()).thenReturn(false);
|
||||||
when(account.isPniSupported()).thenReturn(true);
|
|
||||||
when(account.isPaymentActivationSupported()).thenReturn(false);
|
when(account.isPaymentActivationSupported()).thenReturn(false);
|
||||||
|
|
||||||
when(accountsManager.getByAccountIdentifier(AuthHelper.VALID_UUID)).thenReturn(Optional.of(account));
|
when(accountsManager.getByAccountIdentifier(AuthHelper.VALID_UUID)).thenReturn(Optional.of(account));
|
||||||
|
@ -213,7 +212,7 @@ class DeviceControllerTest {
|
||||||
|
|
||||||
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
||||||
|
|
||||||
final AccountAttributes accountAttributes = new AccountAttributes(fetchesMessages, 1234, 5678, null, null, true, new DeviceCapabilities(true, true, true, true));
|
final AccountAttributes accountAttributes = new AccountAttributes(fetchesMessages, 1234, 5678, null, null, true, new DeviceCapabilities(true, true, true));
|
||||||
|
|
||||||
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
|
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
|
||||||
accountAttributes,
|
accountAttributes,
|
||||||
|
@ -628,7 +627,7 @@ class DeviceControllerTest {
|
||||||
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
||||||
|
|
||||||
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
|
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
|
||||||
new AccountAttributes(false, registrationId, pniRegistrationId, null, null, true, new DeviceCapabilities(true, true, true, true)),
|
new AccountAttributes(false, registrationId, pniRegistrationId, null, null, true, new DeviceCapabilities(true, true, true)),
|
||||||
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()
|
||||||
|
@ -685,61 +684,9 @@ class DeviceControllerTest {
|
||||||
verify(accountsManager, never()).addDevice(any(), any());
|
verify(accountsManager, never()).addDevice(any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@MethodSource
|
|
||||||
void deviceDowngradePniTest(final boolean accountSupportsPni, final boolean deviceSupportsPni, final int expectedStatus) {
|
|
||||||
when(accountsManager.getByAccountIdentifier(AuthHelper.VALID_UUID)).thenReturn(Optional.of(account));
|
|
||||||
when(accountsManager.addDevice(any(), any()))
|
|
||||||
.thenReturn(CompletableFuture.completedFuture(new Pair<>(mock(Account.class), mock(Device.class))));
|
|
||||||
|
|
||||||
final Device primaryDevice = mock(Device.class);
|
|
||||||
when(primaryDevice.getId()).thenReturn(Device.PRIMARY_ID);
|
|
||||||
when(AuthHelper.VALID_ACCOUNT.getDevices()).thenReturn(List.of(primaryDevice));
|
|
||||||
|
|
||||||
final ECSignedPreKey aciSignedPreKey;
|
|
||||||
final ECSignedPreKey pniSignedPreKey;
|
|
||||||
final KEMSignedPreKey aciPqLastResortPreKey;
|
|
||||||
final KEMSignedPreKey pniPqLastResortPreKey;
|
|
||||||
|
|
||||||
final ECKeyPair aciIdentityKeyPair = Curve.generateKeyPair();
|
|
||||||
final ECKeyPair pniIdentityKeyPair = Curve.generateKeyPair();
|
|
||||||
|
|
||||||
aciSignedPreKey = KeysHelper.signedECPreKey(1, aciIdentityKeyPair);
|
|
||||||
pniSignedPreKey = KeysHelper.signedECPreKey(2, pniIdentityKeyPair);
|
|
||||||
aciPqLastResortPreKey = KeysHelper.signedKEMPreKey(3, aciIdentityKeyPair);
|
|
||||||
pniPqLastResortPreKey = KeysHelper.signedKEMPreKey(4, pniIdentityKeyPair);
|
|
||||||
|
|
||||||
when(account.getIdentityKey(IdentityType.ACI)).thenReturn(new IdentityKey(aciIdentityKeyPair.getPublicKey()));
|
|
||||||
when(account.getIdentityKey(IdentityType.PNI)).thenReturn(new IdentityKey(pniIdentityKeyPair.getPublicKey()));
|
|
||||||
when(account.isPniSupported()).thenReturn(accountSupportsPni);
|
|
||||||
|
|
||||||
when(asyncCommands.set(any(), any(), any())).thenReturn(MockRedisFuture.completedFuture(null));
|
|
||||||
|
|
||||||
final LinkDeviceRequest request = new LinkDeviceRequest(deviceController.generateVerificationToken(AuthHelper.VALID_UUID),
|
|
||||||
new AccountAttributes(false, 1234, 5678, null, null, true, new DeviceCapabilities(true, true, deviceSupportsPni, true)),
|
|
||||||
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.empty(), Optional.of(new GcmRegistrationId("gcm-id"))));
|
|
||||||
|
|
||||||
try (final Response response = resources.getJerseyTest()
|
|
||||||
.target("/v1/devices/link")
|
|
||||||
.request()
|
|
||||||
.header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, "password1"))
|
|
||||||
.put(Entity.entity(request, MediaType.APPLICATION_JSON_TYPE))) {
|
|
||||||
|
|
||||||
assertEquals(expectedStatus, response.getStatus());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Arguments> deviceDowngradePniTest() {
|
|
||||||
return List.of(
|
|
||||||
Arguments.of(true, true, 200),
|
|
||||||
Arguments.of(true, false, 409),
|
|
||||||
Arguments.of(false, true, 200),
|
|
||||||
Arguments.of(false, false, 200));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void putCapabilitiesSuccessTest() {
|
void putCapabilitiesSuccessTest() {
|
||||||
final DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true);
|
final DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true);
|
||||||
final Response response = resources
|
final Response response = resources
|
||||||
.getJerseyTest()
|
.getJerseyTest()
|
||||||
.target("/v1/devices/capabilities")
|
.target("/v1/devices/capabilities")
|
||||||
|
|
|
@ -200,14 +200,12 @@ class ProfileControllerTest {
|
||||||
when(profileAccount.getCurrentProfileVersion()).thenReturn(Optional.empty());
|
when(profileAccount.getCurrentProfileVersion()).thenReturn(Optional.empty());
|
||||||
when(profileAccount.getUsernameHash()).thenReturn(Optional.of(USERNAME_HASH));
|
when(profileAccount.getUsernameHash()).thenReturn(Optional.of(USERNAME_HASH));
|
||||||
when(profileAccount.getUnidentifiedAccessKey()).thenReturn(Optional.of(UNIDENTIFIED_ACCESS_KEY));
|
when(profileAccount.getUnidentifiedAccessKey()).thenReturn(Optional.of(UNIDENTIFIED_ACCESS_KEY));
|
||||||
when(profileAccount.isPniSupported()).thenReturn(true);
|
|
||||||
|
|
||||||
Account capabilitiesAccount = mock(Account.class);
|
Account capabilitiesAccount = mock(Account.class);
|
||||||
|
|
||||||
when(capabilitiesAccount.getUuid()).thenReturn(AuthHelper.VALID_UUID);
|
when(capabilitiesAccount.getUuid()).thenReturn(AuthHelper.VALID_UUID);
|
||||||
when(capabilitiesAccount.getIdentityKey(IdentityType.ACI)).thenReturn(ACCOUNT_IDENTITY_KEY);
|
when(capabilitiesAccount.getIdentityKey(IdentityType.ACI)).thenReturn(ACCOUNT_IDENTITY_KEY);
|
||||||
when(capabilitiesAccount.getIdentityKey(IdentityType.PNI)).thenReturn(ACCOUNT_PHONE_NUMBER_IDENTITY_KEY);
|
when(capabilitiesAccount.getIdentityKey(IdentityType.PNI)).thenReturn(ACCOUNT_PHONE_NUMBER_IDENTITY_KEY);
|
||||||
when(capabilitiesAccount.isPniSupported()).thenReturn(true);
|
|
||||||
when(capabilitiesAccount.isPaymentActivationSupported()).thenReturn(false);
|
when(capabilitiesAccount.isPaymentActivationSupported()).thenReturn(false);
|
||||||
when(capabilitiesAccount.isEnabled()).thenReturn(true);
|
when(capabilitiesAccount.isEnabled()).thenReturn(true);
|
||||||
|
|
||||||
|
|
|
@ -477,10 +477,10 @@ class RegistrationControllerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
final AccountAttributes fetchesMessagesAccountAttributes =
|
final AccountAttributes fetchesMessagesAccountAttributes =
|
||||||
new AccountAttributes(true, 1, 1, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false));
|
new AccountAttributes(true, 1, 1, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false));
|
||||||
|
|
||||||
final AccountAttributes pushAccountAttributes =
|
final AccountAttributes pushAccountAttributes =
|
||||||
new AccountAttributes(false, 1, 1, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false));
|
new AccountAttributes(false, 1, 1, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(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, 1, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false));
|
new AccountAttributes(true, 1, 1, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false));
|
||||||
|
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
// Signed PNI EC pre-key is missing
|
// Signed PNI EC pre-key is missing
|
||||||
|
@ -736,13 +736,13 @@ class RegistrationControllerTest {
|
||||||
final int registrationId = 1;
|
final int registrationId = 1;
|
||||||
final int pniRegistrationId = 2;
|
final int pniRegistrationId = 2;
|
||||||
|
|
||||||
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(false, false, false, false);
|
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(false, false, false);
|
||||||
|
|
||||||
final AccountAttributes fetchesMessagesAccountAttributes =
|
final AccountAttributes fetchesMessagesAccountAttributes =
|
||||||
new AccountAttributes(true, registrationId, pniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false));
|
new AccountAttributes(true, registrationId, pniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false));
|
||||||
|
|
||||||
final AccountAttributes pushAccountAttributes =
|
final AccountAttributes pushAccountAttributes =
|
||||||
new AccountAttributes(false, registrationId, pniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false));
|
new AccountAttributes(false, registrationId, pniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(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";
|
||||||
|
@ -857,7 +857,7 @@ class RegistrationControllerTest {
|
||||||
final IdentityKey pniIdentityKey = new IdentityKey(pniIdentityKeyPair.getPublicKey());
|
final IdentityKey pniIdentityKey = new IdentityKey(pniIdentityKeyPair.getPublicKey());
|
||||||
|
|
||||||
final AccountAttributes accountAttributes = new AccountAttributes(true, registrationId, pniRegistrationId, "name".getBytes(StandardCharsets.UTF_8), "reglock",
|
final AccountAttributes accountAttributes = new AccountAttributes(true, registrationId, pniRegistrationId, "name".getBytes(StandardCharsets.UTF_8), "reglock",
|
||||||
true, new Device.DeviceCapabilities(true, true, true, true));
|
true, new Device.DeviceCapabilities(true, true, true));
|
||||||
|
|
||||||
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)),
|
||||||
|
|
|
@ -393,7 +393,6 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
|
||||||
@CartesianTest.Values(bytes = {Device.PRIMARY_ID, Device.PRIMARY_ID + 1}) final byte deviceId,
|
@CartesianTest.Values(bytes = {Device.PRIMARY_ID, Device.PRIMARY_ID + 1}) final byte deviceId,
|
||||||
@CartesianTest.Values(booleans = {true, false}) final boolean storage,
|
@CartesianTest.Values(booleans = {true, false}) final boolean storage,
|
||||||
@CartesianTest.Values(booleans = {true, false}) final boolean transfer,
|
@CartesianTest.Values(booleans = {true, false}) final boolean transfer,
|
||||||
@CartesianTest.Values(booleans = {true, false}) final boolean pni,
|
|
||||||
@CartesianTest.Values(booleans = {true, false}) final boolean paymentActivation) {
|
@CartesianTest.Values(booleans = {true, false}) final boolean paymentActivation) {
|
||||||
|
|
||||||
mockAuthenticationInterceptor().setAuthenticatedDevice(AUTHENTICATED_ACI, deviceId);
|
mockAuthenticationInterceptor().setAuthenticatedDevice(AUTHENTICATED_ACI, deviceId);
|
||||||
|
@ -404,14 +403,12 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
|
||||||
final SetCapabilitiesResponse ignored = authenticatedServiceStub().setCapabilities(SetCapabilitiesRequest.newBuilder()
|
final SetCapabilitiesResponse ignored = authenticatedServiceStub().setCapabilities(SetCapabilitiesRequest.newBuilder()
|
||||||
.setStorage(storage)
|
.setStorage(storage)
|
||||||
.setTransfer(transfer)
|
.setTransfer(transfer)
|
||||||
.setPni(pni)
|
|
||||||
.setPaymentActivation(paymentActivation)
|
.setPaymentActivation(paymentActivation)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
final Device.DeviceCapabilities expectedCapabilities = new Device.DeviceCapabilities(
|
final Device.DeviceCapabilities expectedCapabilities = new Device.DeviceCapabilities(
|
||||||
storage,
|
storage,
|
||||||
transfer,
|
transfer,
|
||||||
pni,
|
|
||||||
paymentActivation);
|
paymentActivation);
|
||||||
|
|
||||||
verify(device).setCapabilities(expectedCapabilities);
|
verify(device).setCapabilities(expectedCapabilities);
|
||||||
|
|
|
@ -178,7 +178,6 @@ public class AccountCreationDeletionIntegrationTest {
|
||||||
final String registrationLockSecret = RandomStringUtils.randomAlphanumeric(16);
|
final String registrationLockSecret = RandomStringUtils.randomAlphanumeric(16);
|
||||||
|
|
||||||
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(
|
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
ThreadLocalRandom.current().nextBoolean());
|
ThreadLocalRandom.current().nextBoolean());
|
||||||
|
@ -291,14 +290,14 @@ public class AccountCreationDeletionIntegrationTest {
|
||||||
final KEMSignedPreKey pniPqLastResortPreKey = KeysHelper.signedKEMPreKey(4, pniKeyPair);
|
final KEMSignedPreKey pniPqLastResortPreKey = KeysHelper.signedKEMPreKey(4, pniKeyPair);
|
||||||
|
|
||||||
final Account originalAccount = accountsManager.create(number,
|
final Account originalAccount = accountsManager.create(number,
|
||||||
new AccountAttributes(true, 1, 1, "name".getBytes(StandardCharsets.UTF_8), "registration-lock", false, new Device.DeviceCapabilities(false, false, false, false)),
|
new AccountAttributes(true, 1, 1, "name".getBytes(StandardCharsets.UTF_8), "registration-lock", false, new Device.DeviceCapabilities(false, false, false)),
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
new IdentityKey(aciKeyPair.getPublicKey()),
|
new IdentityKey(aciKeyPair.getPublicKey()),
|
||||||
new IdentityKey(pniKeyPair.getPublicKey()),
|
new IdentityKey(pniKeyPair.getPublicKey()),
|
||||||
new DeviceSpec(null,
|
new DeviceSpec(null,
|
||||||
"password?",
|
"password?",
|
||||||
"OWI",
|
"OWI",
|
||||||
new Device.DeviceCapabilities(false, false, false, false),
|
new Device.DeviceCapabilities(false, false, false),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
true,
|
true,
|
||||||
|
@ -320,7 +319,6 @@ public class AccountCreationDeletionIntegrationTest {
|
||||||
final String registrationLockSecret = RandomStringUtils.randomAlphanumeric(16);
|
final String registrationLockSecret = RandomStringUtils.randomAlphanumeric(16);
|
||||||
|
|
||||||
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(
|
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
ThreadLocalRandom.current().nextBoolean());
|
ThreadLocalRandom.current().nextBoolean());
|
||||||
|
@ -410,7 +408,6 @@ public class AccountCreationDeletionIntegrationTest {
|
||||||
final String registrationLockSecret = RandomStringUtils.randomAlphanumeric(16);
|
final String registrationLockSecret = RandomStringUtils.randomAlphanumeric(16);
|
||||||
|
|
||||||
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(
|
final Device.DeviceCapabilities deviceCapabilities = new Device.DeviceCapabilities(
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
ThreadLocalRandom.current().nextBoolean(),
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
ThreadLocalRandom.current().nextBoolean());
|
ThreadLocalRandom.current().nextBoolean());
|
||||||
|
|
|
@ -46,30 +46,6 @@ class AccountTest {
|
||||||
private final Device recentSecondaryDevice = mock(Device.class);
|
private final Device recentSecondaryDevice = mock(Device.class);
|
||||||
private final Device oldSecondaryDevice = mock(Device.class);
|
private final Device oldSecondaryDevice = mock(Device.class);
|
||||||
|
|
||||||
private final Device senderKeyCapableDevice = mock(Device.class);
|
|
||||||
private final Device senderKeyIncapableDevice = mock(Device.class);
|
|
||||||
private final Device senderKeyIncapableExpiredDevice = mock(Device.class);
|
|
||||||
|
|
||||||
private final Device announcementGroupCapableDevice = mock(Device.class);
|
|
||||||
private final Device announcementGroupIncapableDevice = mock(Device.class);
|
|
||||||
private final Device announcementGroupIncapableExpiredDevice = mock(Device.class);
|
|
||||||
|
|
||||||
private final Device changeNumberCapableDevice = mock(Device.class);
|
|
||||||
private final Device changeNumberIncapableDevice = mock(Device.class);
|
|
||||||
private final Device changeNumberIncapableExpiredDevice = mock(Device.class);
|
|
||||||
|
|
||||||
private final Device pniCapableDevice = mock(Device.class);
|
|
||||||
private final Device pniIncapableDevice = mock(Device.class);
|
|
||||||
private final Device pniIncapableExpiredDevice = mock(Device.class);
|
|
||||||
|
|
||||||
private final Device storiesCapableDevice = mock(Device.class);
|
|
||||||
private final Device storiesIncapableDevice = mock(Device.class);
|
|
||||||
private final Device storiesIncapableExpiredDevice = mock(Device.class);
|
|
||||||
|
|
||||||
private final Device giftBadgesCapableDevice = mock(Device.class);
|
|
||||||
private final Device giftBadgesIncapableDevice = mock(Device.class);
|
|
||||||
private final Device giftBadgesIncapableExpiredDevice = mock(Device.class);
|
|
||||||
|
|
||||||
private final Device paymentActivationCapableDevice = mock(Device.class);
|
private final Device paymentActivationCapableDevice = mock(Device.class);
|
||||||
private final Device paymentActivationIncapableDevice = mock(Device.class);
|
private final Device paymentActivationIncapableDevice = mock(Device.class);
|
||||||
private final Device paymentActivationIncapableExpiredDevice = mock(Device.class);
|
private final Device paymentActivationIncapableExpiredDevice = mock(Device.class);
|
||||||
|
@ -97,87 +73,14 @@ class AccountTest {
|
||||||
when(oldSecondaryDevice.isEnabled()).thenReturn(false);
|
when(oldSecondaryDevice.isEnabled()).thenReturn(false);
|
||||||
when(oldSecondaryDevice.getId()).thenReturn(deviceId2);
|
when(oldSecondaryDevice.getId()).thenReturn(deviceId2);
|
||||||
|
|
||||||
when(senderKeyCapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(senderKeyCapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(senderKeyIncapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(senderKeyIncapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(senderKeyIncapableExpiredDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(senderKeyIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
when(announcementGroupCapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(announcementGroupCapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(announcementGroupIncapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(announcementGroupIncapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(announcementGroupIncapableExpiredDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(announcementGroupIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
when(changeNumberCapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(changeNumberCapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(changeNumberIncapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(changeNumberIncapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(changeNumberIncapableExpiredDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(changeNumberIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
when(pniCapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, true, false));
|
|
||||||
when(pniCapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(pniIncapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(pniIncapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(pniIncapableExpiredDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(pniIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
when(storiesCapableDevice.getId()).thenReturn(Device.PRIMARY_ID);
|
|
||||||
when(storiesCapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(storiesCapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(storiesCapableDevice.getId()).thenReturn(deviceId2);
|
|
||||||
when(storiesIncapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(storiesIncapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
when(storiesCapableDevice.getId()).thenReturn((byte) 3);
|
|
||||||
when(storiesIncapableExpiredDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, false, false));
|
|
||||||
when(storiesIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
when(giftBadgesCapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, true, false));
|
|
||||||
when(giftBadgesCapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
when(giftBadgesIncapableDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, true, false));
|
|
||||||
when(giftBadgesIncapableDevice.isEnabled()).thenReturn(true);
|
|
||||||
when(giftBadgesIncapableExpiredDevice.getCapabilities()).thenReturn(
|
|
||||||
new DeviceCapabilities(true, true, true, false));
|
|
||||||
when(giftBadgesIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
when(paymentActivationCapableDevice.getCapabilities()).thenReturn(
|
when(paymentActivationCapableDevice.getCapabilities()).thenReturn(
|
||||||
new DeviceCapabilities(true, true, true, true));
|
new DeviceCapabilities(true, true, true));
|
||||||
when(paymentActivationCapableDevice.isEnabled()).thenReturn(true);
|
when(paymentActivationCapableDevice.isEnabled()).thenReturn(true);
|
||||||
when(paymentActivationIncapableDevice.getCapabilities()).thenReturn(
|
when(paymentActivationIncapableDevice.getCapabilities()).thenReturn(
|
||||||
new DeviceCapabilities(true, true, true, false));
|
new DeviceCapabilities(true, true, false));
|
||||||
when(paymentActivationIncapableDevice.isEnabled()).thenReturn(true);
|
when(paymentActivationIncapableDevice.isEnabled()).thenReturn(true);
|
||||||
when(paymentActivationIncapableExpiredDevice.getCapabilities()).thenReturn(
|
when(paymentActivationIncapableExpiredDevice.getCapabilities()).thenReturn(
|
||||||
new DeviceCapabilities(true, true, true, false));
|
new DeviceCapabilities(true, true, false));
|
||||||
when(paymentActivationIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
when(paymentActivationIncapableExpiredDevice.isEnabled()).thenReturn(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -268,19 +171,6 @@ class AccountTest {
|
||||||
assertTrue(account.isDiscoverableByPhoneNumber());
|
assertTrue(account.isDiscoverableByPhoneNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void isPniSupported() {
|
|
||||||
assertThat(AccountsHelper.generateTestAccount("+18005551234", UUID.randomUUID(),
|
|
||||||
UUID.randomUUID(), List.of(pniCapableDevice),
|
|
||||||
"1234".getBytes(StandardCharsets.UTF_8)).isPniSupported()).isTrue();
|
|
||||||
assertThat(AccountsHelper.generateTestAccount("+18005551234", UUID.randomUUID(),
|
|
||||||
UUID.randomUUID(), List.of(pniCapableDevice, pniIncapableDevice),
|
|
||||||
"1234".getBytes(StandardCharsets.UTF_8)).isPniSupported()).isFalse();
|
|
||||||
assertThat(AccountsHelper.generateTestAccount("+18005551234", UUID.randomUUID(),
|
|
||||||
UUID.randomUUID(), List.of(pniCapableDevice, pniIncapableExpiredDevice),
|
|
||||||
"1234".getBytes(StandardCharsets.UTF_8)).isPniSupported()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void isPaymentActivationSupported() {
|
void isPaymentActivationSupported() {
|
||||||
assertThat(AccountsHelper.generateTestAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID(),
|
assertThat(AccountsHelper.generateTestAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID(),
|
||||||
|
|
|
@ -187,7 +187,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, rotatedPniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false));
|
final AccountAttributes accountAttributes = new AccountAttributes(true, rotatedPniRegistrationId + 1, rotatedPniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false));
|
||||||
final Account account = AccountsHelper.createAccount(accountsManager, originalNumber, accountAttributes);
|
final Account account = AccountsHelper.createAccount(accountsManager, originalNumber, accountAttributes);
|
||||||
|
|
||||||
keysManager.storeEcSignedPreKeys(account.getIdentifier(IdentityType.ACI),
|
keysManager.storeEcSignedPreKeys(account.getIdentifier(IdentityType.ACI),
|
||||||
|
|
|
@ -157,7 +157,7 @@ class AccountsManagerConcurrentModificationIntegrationTest {
|
||||||
null,
|
null,
|
||||||
"password",
|
"password",
|
||||||
null,
|
null,
|
||||||
new Device.DeviceCapabilities(false, false, false, false),
|
new Device.DeviceCapabilities(false, false, false),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -878,7 +878,7 @@ class AccountsManagerTest {
|
||||||
@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, 1, 2, null, null,
|
final AccountAttributes attributes = new AccountAttributes(false, 1, 2, null, null,
|
||||||
true, new DeviceCapabilities(hasStorage, false, false, false));
|
true, new DeviceCapabilities(hasStorage, false, false));
|
||||||
|
|
||||||
final Account account = createAccount("+18005550123", attributes);
|
final Account account = createAccount("+18005550123", attributes);
|
||||||
|
|
||||||
|
@ -903,7 +903,7 @@ class AccountsManagerTest {
|
||||||
final byte[] deviceNameCiphertext = "device-name".getBytes(StandardCharsets.UTF_8);
|
final byte[] deviceNameCiphertext = "device-name".getBytes(StandardCharsets.UTF_8);
|
||||||
final String password = "password";
|
final String password = "password";
|
||||||
final String signalAgent = "OWT";
|
final String signalAgent = "OWT";
|
||||||
final DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true);
|
final DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true);
|
||||||
final int aciRegistrationId = 17;
|
final int aciRegistrationId = 17;
|
||||||
final int pniRegistrationId = 19;
|
final int pniRegistrationId = 19;
|
||||||
final ECSignedPreKey aciSignedPreKey = KeysHelper.signedECPreKey(1, aciKeyPair);
|
final ECSignedPreKey aciSignedPreKey = KeysHelper.signedECPreKey(1, aciKeyPair);
|
||||||
|
|
|
@ -166,7 +166,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||||
"password",
|
"password",
|
||||||
"OWT",
|
"OWT",
|
||||||
new Device.DeviceCapabilities(true, true, true, true),
|
new Device.DeviceCapabilities(true, true, true),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
true,
|
true,
|
||||||
|
@ -209,7 +209,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||||
"password",
|
"password",
|
||||||
"OWT",
|
"OWT",
|
||||||
new Device.DeviceCapabilities(true, true, true, true),
|
new Device.DeviceCapabilities(true, true, true),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
true,
|
true,
|
||||||
|
@ -258,7 +258,7 @@ public class AddRemoveDeviceIntegrationTest {
|
||||||
"device-name".getBytes(StandardCharsets.UTF_8),
|
"device-name".getBytes(StandardCharsets.UTF_8),
|
||||||
"password",
|
"password",
|
||||||
"OWT",
|
"OWT",
|
||||||
new Device.DeviceCapabilities(true, true, true, true),
|
new Device.DeviceCapabilities(true, true, true),
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -148,7 +148,6 @@ public class AccountsHelper {
|
||||||
case "isEnabled" -> when(updatedAccount.isEnabled()).thenAnswer(stubbing);
|
case "isEnabled" -> when(updatedAccount.isEnabled()).thenAnswer(stubbing);
|
||||||
case "isDiscoverableByPhoneNumber" -> when(updatedAccount.isDiscoverableByPhoneNumber()).thenAnswer(stubbing);
|
case "isDiscoverableByPhoneNumber" -> when(updatedAccount.isDiscoverableByPhoneNumber()).thenAnswer(stubbing);
|
||||||
case "getNextDeviceId" -> when(updatedAccount.getNextDeviceId()).thenAnswer(stubbing);
|
case "getNextDeviceId" -> when(updatedAccount.getNextDeviceId()).thenAnswer(stubbing);
|
||||||
case "isPniSupported" -> when(updatedAccount.isPniSupported()).thenAnswer(stubbing);
|
|
||||||
case "isPaymentActivationSupported" -> when(updatedAccount.isPaymentActivationSupported()).thenAnswer(stubbing);
|
case "isPaymentActivationSupported" -> when(updatedAccount.isPaymentActivationSupported()).thenAnswer(stubbing);
|
||||||
case "hasEnabledLinkedDevice" -> when(updatedAccount.hasEnabledLinkedDevice()).thenAnswer(stubbing);
|
case "hasEnabledLinkedDevice" -> when(updatedAccount.hasEnabledLinkedDevice()).thenAnswer(stubbing);
|
||||||
case "getRegistrationLock" -> when(updatedAccount.getRegistrationLock()).thenAnswer(stubbing);
|
case "getRegistrationLock" -> when(updatedAccount.getRegistrationLock()).thenAnswer(stubbing);
|
||||||
|
|
Loading…
Reference in New Issue