Require some tree head sizes in key transparency search and monitor requests

This commit is contained in:
Katherine 2024-10-31 10:54:55 -04:00 committed by GitHub
parent 9b5a62e60f
commit e627d4e2c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 61 additions and 62 deletions

View File

@ -36,12 +36,10 @@ public record KeyTransparencyMonitorRequest(
Optional<@Valid UsernameHashMonitor> usernameHash, Optional<@Valid UsernameHashMonitor> usernameHash,
@Schema(description = "The tree head size to prove consistency against.") @Schema(description = "The tree head size to prove consistency against.")
@NotNull @Positive long lastNonDistinguishedTreeHeadSize,
Optional<@Positive Long> lastNonDistinguishedTreeHeadSize,
@Schema(description = "The distinguished tree head size to prove consistency against.") @Schema(description = "The distinguished tree head size to prove consistency against.")
@NotNull @Positive long lastDistinguishedTreeHeadSize
Optional<@Positive Long> lastDistinguishedTreeHeadSize
) { ) {
public record AciMonitor( public record AciMonitor(

View File

@ -51,8 +51,9 @@ public record KeyTransparencySearchRequest(
@Schema(description = "The non-distinguished tree head size to prove consistency against.") @Schema(description = "The non-distinguished tree head size to prove consistency against.")
Optional<@Positive Long> lastTreeHeadSize, Optional<@Positive Long> lastTreeHeadSize,
@NotNull
@Schema(description = "The distinguished tree head size to prove consistency against.") @Schema(description = "The distinguished tree head size to prove consistency against.")
Optional<@Positive Long> distinguishedTreeHeadSize @Positive long distinguishedTreeHeadSize
) { ) {
@AssertTrue @AssertTrue
public boolean isUnidentifiedAccessKeyProvidedWithE164() { public boolean isUnidentifiedAccessKeyProvidedWithE164() {

View File

@ -119,7 +119,7 @@ public class KeyTransparencyServiceClient implements Managed {
final Optional<ByteString> usernameHash, final Optional<ByteString> usernameHash,
final Optional<E164SearchRequest> e164SearchRequest, final Optional<E164SearchRequest> e164SearchRequest,
final Optional<Long> lastTreeHeadSize, final Optional<Long> lastTreeHeadSize,
final Optional<Long> distinguishedTreeHeadSize, final long distinguishedTreeHeadSize,
final Duration timeout) { final Duration timeout) {
final SearchRequest.Builder searchKeysRequestBuilder = SearchRequest.newBuilder() final SearchRequest.Builder searchKeysRequestBuilder = SearchRequest.newBuilder()
.setAci(aci) .setAci(aci)
@ -128,9 +128,9 @@ public class KeyTransparencyServiceClient implements Managed {
usernameHash.ifPresent(searchKeysRequestBuilder::setUsernameHash); usernameHash.ifPresent(searchKeysRequestBuilder::setUsernameHash);
e164SearchRequest.ifPresent(searchKeysRequestBuilder::setE164SearchRequest); e164SearchRequest.ifPresent(searchKeysRequestBuilder::setE164SearchRequest);
final ConsistencyParameters.Builder consistency = ConsistencyParameters.newBuilder(); final ConsistencyParameters.Builder consistency = ConsistencyParameters.newBuilder()
.setDistinguished(distinguishedTreeHeadSize);
lastTreeHeadSize.ifPresent(consistency::setLast); lastTreeHeadSize.ifPresent(consistency::setLast);
distinguishedTreeHeadSize.ifPresent(consistency::setDistinguished);
searchKeysRequestBuilder.setConsistency(consistency.build()); searchKeysRequestBuilder.setConsistency(consistency.build());
@ -138,17 +138,17 @@ public class KeyTransparencyServiceClient implements Managed {
.search(searchKeysRequestBuilder.build()), callbackExecutor); .search(searchKeysRequestBuilder.build()), callbackExecutor);
} }
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public CompletableFuture<byte[]> monitor(final List<MonitorKey> monitorKeys, public CompletableFuture<byte[]> monitor(final List<MonitorKey> monitorKeys,
final Optional<Long> lastTreeHeadSize, final long lastTreeHeadSize,
final Optional<Long> distinguishedTreeHeadSize, final long distinguishedTreeHeadSize,
final Duration timeout) { final Duration timeout) {
final MonitorRequest.Builder monitorRequestBuilder = MonitorRequest.newBuilder() final MonitorRequest.Builder monitorRequestBuilder = MonitorRequest.newBuilder()
.addAllContactKeys(monitorKeys); .addAllContactKeys(monitorKeys);
final ConsistencyParameters.Builder consistency = ConsistencyParameters.newBuilder(); final ConsistencyParameters consistency = ConsistencyParameters.newBuilder()
lastTreeHeadSize.ifPresent(consistency::setLast); .setLast(lastTreeHeadSize)
distinguishedTreeHeadSize.ifPresent(consistency::setDistinguished); .setDistinguished(distinguishedTreeHeadSize)
.build();
monitorRequestBuilder.setConsistency(consistency); monitorRequestBuilder.setConsistency(consistency);

View File

@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
@ -154,7 +155,7 @@ public class KeyTransparencyControllerTest {
e164.ifPresent(ignored -> searchResponseBuilder.setE164(TreeSearchResponse.getDefaultInstance())); e164.ifPresent(ignored -> searchResponseBuilder.setE164(TreeSearchResponse.getDefaultInstance()));
usernameHash.ifPresent(ignored -> searchResponseBuilder.setUsernameHash(TreeSearchResponse.getDefaultInstance())); usernameHash.ifPresent(ignored -> searchResponseBuilder.setUsernameHash(TreeSearchResponse.getDefaultInstance()));
when(keyTransparencyServiceClient.search(any(), any(), any(), any(), any(), any(), any())) when(keyTransparencyServiceClient.search(any(), any(), any(), any(), any(), anyLong(), any()))
.thenReturn(CompletableFuture.completedFuture(searchResponseBuilder.build())); .thenReturn(CompletableFuture.completedFuture(searchResponseBuilder.build()));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -164,7 +165,7 @@ public class KeyTransparencyControllerTest {
final Optional<byte[]> unidentifiedAccessKey = e164.isPresent() ? Optional.of(UNIDENTIFIED_ACCESS_KEY) : Optional.empty(); final Optional<byte[]> unidentifiedAccessKey = e164.isPresent() ? Optional.of(UNIDENTIFIED_ACCESS_KEY) : Optional.empty();
final String searchJson = createRequestJson( final String searchJson = createRequestJson(
new KeyTransparencySearchRequest(ACI, e164, usernameHash, ACI_IDENTITY_KEY, new KeyTransparencySearchRequest(ACI, e164, usernameHash, ACI_IDENTITY_KEY,
unidentifiedAccessKey, Optional.of(3L), Optional.of(4L))); unidentifiedAccessKey, Optional.of(3L), 4L));
try (Response response = request.post(Entity.json(searchJson))) { try (Response response = request.post(Entity.json(searchJson))) {
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());
@ -180,7 +181,7 @@ public class KeyTransparencyControllerTest {
ArgumentCaptor<Optional<E164SearchRequest>> e164Argument = ArgumentCaptor.forClass(Optional.class); ArgumentCaptor<Optional<E164SearchRequest>> e164Argument = ArgumentCaptor.forClass(Optional.class);
verify(keyTransparencyServiceClient).search(aciArgument.capture(), aciIdentityKeyArgument.capture(), verify(keyTransparencyServiceClient).search(aciArgument.capture(), aciIdentityKeyArgument.capture(),
usernameHashArgument.capture(), e164Argument.capture(), eq(Optional.of(3L)), eq(Optional.of(4L)), usernameHashArgument.capture(), e164Argument.capture(), eq(Optional.of(3L)), eq(4L),
eq(KeyTransparencyController.KEY_TRANSPARENCY_RPC_TIMEOUT)); eq(KeyTransparencyController.KEY_TRANSPARENCY_RPC_TIMEOUT));
assertArrayEquals(ACI.toCompactByteArray(), aciArgument.getValue().toByteArray()); assertArrayEquals(ACI.toCompactByteArray(), aciArgument.getValue().toByteArray());
@ -222,7 +223,7 @@ public class KeyTransparencyControllerTest {
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)); .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD));
try (Response response = request.post( try (Response response = request.post(
Entity.json(createRequestJson(new KeyTransparencySearchRequest(ACI, Optional.empty(), Optional.empty(), Entity.json(createRequestJson(new KeyTransparencySearchRequest(ACI, Optional.empty(), Optional.empty(),
ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty()))))) { ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), 4L))))) {
assertEquals(400, response.getStatus()); assertEquals(400, response.getStatus());
} }
verifyNoInteractions(keyTransparencyServiceClient); verifyNoInteractions(keyTransparencyServiceClient);
@ -231,7 +232,7 @@ public class KeyTransparencyControllerTest {
@ParameterizedTest @ParameterizedTest
@MethodSource @MethodSource
void searchGrpcErrors(final Status grpcStatus, final int httpStatus) { void searchGrpcErrors(final Status grpcStatus, final int httpStatus) {
when(keyTransparencyServiceClient.search(any(), any(), any(), any(), any(), any(), any())) when(keyTransparencyServiceClient.search(any(), any(), any(), any(), any(), anyLong(), any()))
.thenReturn(CompletableFuture.failedFuture(new CompletionException(new StatusRuntimeException(grpcStatus)))); .thenReturn(CompletableFuture.failedFuture(new CompletionException(new StatusRuntimeException(grpcStatus))));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -239,9 +240,9 @@ public class KeyTransparencyControllerTest {
.request(); .request();
try (Response response = request.post( try (Response response = request.post(
Entity.json(createRequestJson(new KeyTransparencySearchRequest(ACI, Optional.empty(), Optional.empty(), Entity.json(createRequestJson(new KeyTransparencySearchRequest(ACI, Optional.empty(), Optional.empty(),
ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty()))))) { ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), 4L))))) {
assertEquals(httpStatus, response.getStatus()); assertEquals(httpStatus, response.getStatus());
verify(keyTransparencyServiceClient, times(1)).search(any(), any(), any(), any(), any(), any(), any()); verify(keyTransparencyServiceClient, times(1)).search(any(), any(), any(), any(), any(), anyLong(), any());
} }
} }
@ -262,7 +263,7 @@ public class KeyTransparencyControllerTest {
final Optional<String> e164, final Optional<String> e164,
final Optional<byte[]> unidentifiedAccessKey, final Optional<byte[]> unidentifiedAccessKey,
final Optional<Long> lastTreeHeadSize, final Optional<Long> lastTreeHeadSize,
final Optional<Long> distinguishedTreeHeadSize) { final long distinguishedTreeHeadSize) {
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
.target("/v1/key-transparency/search") .target("/v1/key-transparency/search")
.request(); .request();
@ -277,17 +278,17 @@ public class KeyTransparencyControllerTest {
private static Stream<Arguments> searchInvalidRequest() { private static Stream<Arguments> searchInvalidRequest() {
return Stream.of( return Stream.of(
// ACI can't be null // ACI can't be null
Arguments.of(null, ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Arguments.of(null, ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty(), 4L),
// ACI identity key can't be null // ACI identity key can't be null
Arguments.of(ACI, null, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()), Arguments.of(ACI, null, Optional.empty(), Optional.empty(), Optional.empty(), 4L),
// lastNonDistinguishedTreeHeadSize must be positive // lastNonDistinguishedTreeHeadSize must be positive
Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.of(0L), Optional.empty()), Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.of(0L), 4L),
// lastDistinguishedTreeHeadSize must be positive // lastDistinguishedTreeHeadSize must be positive
Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty(), Optional.of(0L)), Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty(), 0L),
// E164 can't be provided without an unidentified access key // E164 can't be provided without an unidentified access key
Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.of(NUMBER), Optional.empty(), Optional.empty(), Optional.empty()), Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.of(NUMBER), Optional.empty(), Optional.empty(), 4L),
// ...and an unidentified access key can't be provided without an E164 // ...and an unidentified access key can't be provided without an E164
Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.empty(), Optional.of(UNIDENTIFIED_ACCESS_KEY), Optional.empty(), Optional.empty()) Arguments.of(ACI, ACI_IDENTITY_KEY, Optional.empty(), Optional.of(UNIDENTIFIED_ACCESS_KEY), Optional.empty(), 4L)
); );
} }
@ -300,7 +301,7 @@ public class KeyTransparencyControllerTest {
.request(); .request();
try (Response response = request.post( try (Response response = request.post(
Entity.json(createRequestJson(new KeyTransparencySearchRequest(ACI, Optional.empty(), Optional.empty(), Entity.json(createRequestJson(new KeyTransparencySearchRequest(ACI, Optional.empty(), Optional.empty(),
ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), Optional.empty()))))) { ACI_IDENTITY_KEY, Optional.empty(), Optional.empty(), 4L))))) {
assertEquals(429, response.getStatus()); assertEquals(429, response.getStatus());
verifyNoInteractions(keyTransparencyServiceClient); verifyNoInteractions(keyTransparencyServiceClient);
} }
@ -308,7 +309,7 @@ public class KeyTransparencyControllerTest {
@Test @Test
void monitorSuccess() { void monitorSuccess() {
when(keyTransparencyServiceClient.monitor(any(), any(), any(), any())) when(keyTransparencyServiceClient.monitor(any(), anyLong(), anyLong(), any()))
.thenReturn(CompletableFuture.completedFuture(TestRandomUtil.nextBytes(16))); .thenReturn(CompletableFuture.completedFuture(TestRandomUtil.nextBytes(16)));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -319,7 +320,7 @@ public class KeyTransparencyControllerTest {
createRequestJson( createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), COMMITMENT_INDEX),
Optional.empty(), Optional.empty(), Optional.of(3L), Optional.of(4L)))))) { Optional.empty(), Optional.empty(), 3L, 4L))))) {
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());
final KeyTransparencyMonitorResponse keyTransparencyMonitorResponse = response.readEntity( final KeyTransparencyMonitorResponse keyTransparencyMonitorResponse = response.readEntity(
@ -327,7 +328,7 @@ public class KeyTransparencyControllerTest {
assertNotNull(keyTransparencyMonitorResponse.monitorResponse()); assertNotNull(keyTransparencyMonitorResponse.monitorResponse());
verify(keyTransparencyServiceClient, times(1)).monitor( verify(keyTransparencyServiceClient, times(1)).monitor(
any(), eq(Optional.of(3L)), eq(Optional.of(4L)), eq(KeyTransparencyController.KEY_TRANSPARENCY_RPC_TIMEOUT)); any(), eq(3L), eq(4L), eq(KeyTransparencyController.KEY_TRANSPARENCY_RPC_TIMEOUT));
} }
} }
@ -341,7 +342,7 @@ public class KeyTransparencyControllerTest {
Entity.json(createRequestJson( Entity.json(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), COMMITMENT_INDEX),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))))) { Optional.empty(), Optional.empty(), 3L, 4L))))) {
assertEquals(400, response.getStatus()); assertEquals(400, response.getStatus());
verifyNoInteractions(keyTransparencyServiceClient); verifyNoInteractions(keyTransparencyServiceClient);
} }
@ -350,7 +351,7 @@ public class KeyTransparencyControllerTest {
@ParameterizedTest @ParameterizedTest
@MethodSource @MethodSource
void monitorGrpcErrors(final Status grpcStatus, final int httpStatus) { void monitorGrpcErrors(final Status grpcStatus, final int httpStatus) {
when(keyTransparencyServiceClient.monitor(any(), any(), any(), any())) when(keyTransparencyServiceClient.monitor(any(), anyLong(), anyLong(), any()))
.thenReturn(CompletableFuture.failedFuture(new CompletionException(new StatusRuntimeException(grpcStatus)))); .thenReturn(CompletableFuture.failedFuture(new CompletionException(new StatusRuntimeException(grpcStatus))));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -360,9 +361,9 @@ public class KeyTransparencyControllerTest {
Entity.json(createRequestJson( Entity.json(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), COMMITMENT_INDEX),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))))) { Optional.empty(), Optional.empty(), 3L, 4L))))) {
assertEquals(httpStatus, response.getStatus()); assertEquals(httpStatus, response.getStatus());
verify(keyTransparencyServiceClient, times(1)).monitor(any(), any(), any(), any()); verify(keyTransparencyServiceClient, times(1)).monitor(any(), anyLong(), anyLong(), any());
} }
} }
@ -391,120 +392,119 @@ public class KeyTransparencyControllerTest {
return Stream.of( return Stream.of(
// aci monitor cannot be null // aci monitor cannot be null
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest(null, Optional.empty(), Optional.empty(), Optional.empty(), new KeyTransparencyMonitorRequest(null, Optional.empty(), Optional.empty(), 3L, 4L))),
Optional.empty()))),
// aci monitor fields can't be null // aci monitor fields can't be null
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(null, null, null), new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(null, null, null),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(null, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(null, List.of(4L), COMMITMENT_INDEX),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, null, COMMITMENT_INDEX), new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, null, COMMITMENT_INDEX),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), null), new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), null),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
// aciPositions list can't be empty // aciPositions list can't be empty
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, Collections.emptyList(), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, Collections.emptyList(), COMMITMENT_INDEX),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
// aci commitment index must be the correct size // aci commitment index must be the correct size
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), new byte[0]), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), new byte[0]),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, Collections.emptyList(), new byte[33]), new KeyTransparencyMonitorRequest.AciMonitor(ACI, Collections.emptyList(), new byte[33]),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), Optional.empty(), 3L, 4L))),
// username monitor fields cannot be null // username monitor fields cannot be null
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(),
Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(null, null, null)), Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(null, null, null)),
Optional.empty(), Optional.empty()))), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(),
Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(null, List.of(5L), COMMITMENT_INDEX)), Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(null, List.of(5L), COMMITMENT_INDEX)),
Optional.empty(), Optional.empty()))), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(),
Optional.of( Optional.of(
new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, null, COMMITMENT_INDEX)), new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, null, COMMITMENT_INDEX)),
Optional.empty(), Optional.empty()))), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(),
Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, List.of(5L), null)), Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, List.of(5L), null)),
Optional.empty(), Optional.empty()))), 3L, 4L))),
// usernameHashPositions list cannot be empty // usernameHashPositions list cannot be empty
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.empty(), Optional.empty(),
Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH,
Collections.emptyList(), COMMITMENT_INDEX)), Optional.empty(), Optional.empty()))), Collections.emptyList(), COMMITMENT_INDEX)), 3L, 4L))),
// username commitment index must be the correct size // username commitment index must be the correct size
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest( new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), new byte[0]), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), new byte[0]),
Optional.empty(), Optional.empty(),
Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH,
List.of(5L), new byte[0])), Optional.empty(), Optional.empty()))), List.of(5L), new byte[0])), 3L, 4L))),
Arguments.of(createRequestJson( Arguments.of(createRequestJson(
new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), null), new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), null),
Optional.empty(), Optional.empty(),
Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH, Optional.of(new KeyTransparencyMonitorRequest.UsernameHashMonitor(USERNAME_HASH,
List.of(5L), new byte[33])), Optional.empty(), Optional.empty()))), List.of(5L), new byte[33])), 3L, 4L))),
// e164 fields cannot be null // e164 fields cannot be null
Arguments.of( Arguments.of(
createRequestJson(new KeyTransparencyMonitorRequest( createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(null, null, null)), Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(null, null, null)),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
Arguments.of( Arguments.of(
createRequestJson(new KeyTransparencyMonitorRequest( createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(null, List.of(5L), COMMITMENT_INDEX)), Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(null, List.of(5L), COMMITMENT_INDEX)),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
Arguments.of( Arguments.of(
createRequestJson(new KeyTransparencyMonitorRequest( createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, null, COMMITMENT_INDEX)), Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, null, COMMITMENT_INDEX)),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
Arguments.of( Arguments.of(
createRequestJson(new KeyTransparencyMonitorRequest( createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, List.of(5L), null)), Optional.of(new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, List.of(5L), null)),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
// e164Positions list cannot empty // e164Positions list cannot empty
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of( Optional.of(
new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, Collections.emptyList(), COMMITMENT_INDEX)), new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, Collections.emptyList(), COMMITMENT_INDEX)),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
// e164 commitment index must be the correct size // e164 commitment index must be the correct size
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of( Optional.of(
new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, List.of(5L), new byte[0])), new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, List.of(5L), new byte[0])),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX),
Optional.of( Optional.of(
new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, List.of(5L), new byte[33])), new KeyTransparencyMonitorRequest.E164Monitor(NUMBER, List.of(5L), new byte[33])),
Optional.empty(), Optional.empty(), Optional.empty()))), Optional.empty(), 3L, 4L))),
// lastNonDistinguishedTreeHeadSize must be positive // lastNonDistinguishedTreeHeadSize must be positive
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(),
Optional.empty(), Optional.of(0L), Optional.empty()))), Optional.empty(), 0L, 4L))),
// lastDistinguishedTreeHeadSize must be positive // lastDistinguishedTreeHeadSize must be positive
Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest( Arguments.of(createRequestJson(new KeyTransparencyMonitorRequest(
new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(), new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(4L), COMMITMENT_INDEX), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.of(-1L)))) Optional.empty(), 3L, 0L)))
); );
} }
@ -519,7 +519,7 @@ public class KeyTransparencyControllerTest {
Entity.json(createRequestJson( Entity.json(createRequestJson(
new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), null), new KeyTransparencyMonitorRequest(new KeyTransparencyMonitorRequest.AciMonitor(ACI, List.of(3L), null),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty()))))) { 3L, 4L))))) {
assertEquals(429, response.getStatus()); assertEquals(429, response.getStatus());
verifyNoInteractions(keyTransparencyServiceClient); verifyNoInteractions(keyTransparencyServiceClient);
} }