Retire the "distribute PNI key material" endpoint

This commit is contained in:
Jon Chambers
2025-07-11 11:47:29 -04:00
committed by Jon Chambers
parent c97c00bf5f
commit 2564f706d8
2 changed files with 4 additions and 199 deletions

View File

@@ -604,168 +604,6 @@ class AccountControllerV2Test {
}
}
@Nested
class PhoneNumberIdentityKeyDistribution {
@BeforeEach
void setUp() throws Exception {
when(accountsManager.getByAccountIdentifier(AuthHelper.VALID_UUID)).thenReturn(Optional.of(AuthHelper.VALID_ACCOUNT));
when(changeNumberManager.updatePniKeys(any(), any(), any(), any(), any(), any(), any())).thenAnswer(
(Answer<Account>) invocation -> {
final Account account = invocation.getArgument(0);
final IdentityKey pniIdentityKey = invocation.getArgument(1);
final UUID uuid = account.getUuid();
final UUID pni = account.getPhoneNumberIdentifier();
final String number = account.getNumber();
final List<Device> devices = account.getDevices();
final Account updatedAccount = mock(Account.class);
when(updatedAccount.getUuid()).thenReturn(uuid);
when(updatedAccount.getNumber()).thenReturn(number);
when(updatedAccount.getIdentityKey(IdentityType.PNI)).thenReturn(pniIdentityKey);
when(updatedAccount.getPhoneNumberIdentifier()).thenReturn(pni);
when(updatedAccount.getDevices()).thenReturn(devices);
for (byte i = 1; i <= 3; i++) {
final Optional<Device> d = account.getDevice(i);
when(updatedAccount.getDevice(i)).thenReturn(d);
}
return updatedAccount;
});
}
@Test
void pniKeyDistributionSuccess() throws Exception {
final AccountIdentityResponse accountIdentityResponse =
resources.getJerseyTest()
.target("/v2/accounts/phone_number_identity_key_distribution")
.request()
.header(HttpHeaders.AUTHORIZATION,
AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(requestJson()), AccountIdentityResponse.class);
verify(changeNumberManager).updatePniKeys(eq(AuthHelper.VALID_ACCOUNT), eq(IDENTITY_KEY), any(), any(), any(), any(), any());
assertEquals(AuthHelper.VALID_UUID, accountIdentityResponse.uuid());
assertEquals(AuthHelper.VALID_NUMBER, accountIdentityResponse.number());
assertEquals(AuthHelper.VALID_PNI, accountIdentityResponse.pni());
}
@Test
void unprocessableRequestJson() {
final Invocation.Builder request = resources.getJerseyTest()
.target("/v2/accounts/phone_number_identity_key_distribution")
.request()
.header(HttpHeaders.AUTHORIZATION,
AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD));
try (Response response = request.put(Entity.json(unprocessableJson()))) {
assertEquals(400, response.getStatus());
}
}
@Test
void missingBasicAuthorization() {
final Invocation.Builder request = resources.getJerseyTest()
.target("/v2/accounts/phone_number_identity_key_distribution")
.request();
try (Response response = request.put(Entity.json(requestJson()))) {
assertEquals(401, response.getStatus());
}
}
@Test
void invalidBasicAuthorization() {
final Invocation.Builder request = resources.getJerseyTest()
.target("/v2/accounts/phone_number_identity_key_distribution")
.request()
.header(HttpHeaders.AUTHORIZATION, "Basic but-invalid");
try (Response response = request.put(Entity.json(requestJson()))) {
assertEquals(401, response.getStatus());
}
}
@Test
void invalidRequestBody() {
final Invocation.Builder request = resources.getJerseyTest()
.target("/v2/accounts/phone_number_identity_key_distribution")
.request()
.header(HttpHeaders.AUTHORIZATION,
AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD));
try (Response response = request.put(Entity.json(invalidRequestJson()))) {
assertEquals(422, response.getStatus());
}
}
@Test
void deviceMessageTooLarge() throws Exception {
reset(changeNumberManager);
when(changeNumberManager.updatePniKeys(any(), any(), any(), any(), any(), any(), any()))
.thenThrow(MessageTooLargeException.class);
try (final Response response = resources.getJerseyTest()
.target("/v2/accounts/phone_number_identity_key_distribution")
.request()
.header(HttpHeaders.AUTHORIZATION,
AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(requestJson()))) {
assertEquals(413, response.getStatus());
}
}
/**
* Valid request JSON for a {@link org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest}
*/
private static String requestJson() {
final ECSignedPreKey pniSignedPreKey = KeysHelper.signedECPreKey(1, IDENTITY_KEY_PAIR);
final KEMSignedPreKey pniLastResortPreKey = KeysHelper.signedKEMPreKey(2, IDENTITY_KEY_PAIR);
return String.format("""
{
"pniIdentityKey": "%s",
"deviceMessages": [],
"devicePniSignedPrekeys": {},
"devicePniSignedPrekeys": {"1": {"keyId": %d, "publicKey": "%s", "signature": "%s"}},
"devicePniPqLastResortPrekeys": {"1": {"keyId": %d, "publicKey": "%s", "signature": "%s"}},
"pniRegistrationIds": {"1": 17}
}
""", Base64.getEncoder().encodeToString(IDENTITY_KEY.serialize()),
pniSignedPreKey.keyId(), Base64.getEncoder().encodeToString(pniSignedPreKey.serializedPublicKey()), Base64.getEncoder().encodeToString(pniSignedPreKey.signature()),
pniLastResortPreKey.keyId(), Base64.getEncoder().encodeToString(pniLastResortPreKey.serializedPublicKey()), Base64.getEncoder().encodeToString(pniLastResortPreKey.signature()));
}
/**
* Request JSON in the shape of {@link org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest}, but that
* fails validation
*/
private static String invalidRequestJson() {
return """
{
"pniIdentityKey": null,
"deviceMessages": [],
"devicePniSignedPrekeys": {},
"pniRegistrationIds": {}
}
""";
}
/**
* Request JSON that cannot be marshalled into
* {@link org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest}
*/
private static String unprocessableJson() {
return """
{
"pniIdentityKey": []
}
""";
}
}
@Nested
class PhoneNumberDiscoverability {