diff --git a/src/main/java/org/whispersystems/textsecuregcm/controllers/DirectoryController.java b/src/main/java/org/whispersystems/textsecuregcm/controllers/DirectoryController.java index 908927047..e7ceaf99e 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/controllers/DirectoryController.java +++ b/src/main/java/org/whispersystems/textsecuregcm/controllers/DirectoryController.java @@ -18,7 +18,9 @@ package org.whispersystems.textsecuregcm.controllers; import com.google.common.base.Optional; import com.yammer.dropwizard.auth.Auth; +import com.yammer.metrics.Metrics; import com.yammer.metrics.annotation.Timed; +import com.yammer.metrics.core.Histogram; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.entities.ClientContact; @@ -46,7 +48,8 @@ import java.util.List; @Path("/v1/directory") public class DirectoryController { - private final Logger logger = LoggerFactory.getLogger(DirectoryController.class); + private final Logger logger = LoggerFactory.getLogger(DirectoryController.class); + private final Histogram contactsHistogram = Metrics.newHistogram(DirectoryController.class, "contacts"); private final RateLimiters rateLimiters; private final DirectoryManager directory; @@ -56,7 +59,7 @@ public class DirectoryController { this.rateLimiters = rateLimiters; } - @Timed() + @Timed @GET @Path("/{token}") @Produces(MediaType.APPLICATION_JSON) @@ -77,7 +80,7 @@ public class DirectoryController { } } - @Timed() + @Timed @PUT @Path("/tokens") @Produces(MediaType.APPLICATION_JSON) @@ -86,6 +89,7 @@ public class DirectoryController { throws RateLimitExceededException { rateLimiters.getContactsLimiter().validate(account.getNumber(), contacts.getContacts().size()); + contactsHistogram.update(contacts.getContacts().size()); try { List tokens = new LinkedList<>(); diff --git a/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContactTokens.java b/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContactTokens.java index 81b55125f..dcff4f324 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContactTokens.java +++ b/src/main/java/org/whispersystems/textsecuregcm/entities/ClientContactTokens.java @@ -30,4 +30,11 @@ public class ClientContactTokens { public List getContacts() { return contacts; } + + public ClientContactTokens() {} + + public ClientContactTokens(List contacts) { + this.contacts = contacts; + } + } diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DirectoryControllerTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DirectoryControllerTest.java new file mode 100644 index 000000000..48cabb162 --- /dev/null +++ b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DirectoryControllerTest.java @@ -0,0 +1,74 @@ +package org.whispersystems.textsecuregcm.tests.controllers; + +import com.sun.jersey.api.client.ClientResponse; +import com.yammer.dropwizard.testing.ResourceTest; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.whispersystems.textsecuregcm.controllers.DirectoryController; +import org.whispersystems.textsecuregcm.entities.ClientContactTokens; +import org.whispersystems.textsecuregcm.limits.RateLimiter; +import org.whispersystems.textsecuregcm.limits.RateLimiters; +import org.whispersystems.textsecuregcm.storage.DirectoryManager; +import org.whispersystems.textsecuregcm.tests.util.AuthHelper; +import org.whispersystems.textsecuregcm.util.Base64; + +import javax.ws.rs.core.MediaType; +import java.util.LinkedList; +import java.util.List; + +import static org.fest.assertions.api.Assertions.assertThat; +import static org.mockito.Matchers.anyList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DirectoryControllerTest extends ResourceTest { + + private RateLimiters rateLimiters = mock(RateLimiters.class ); + private RateLimiter rateLimiter = mock(RateLimiter.class ); + private DirectoryManager directoryManager = mock(DirectoryManager.class); + + @Override + protected void setUpResources() throws Exception { + addProvider(AuthHelper.getAuthenticator()); + + when(rateLimiters.getContactsLimiter()).thenReturn(rateLimiter); + when(directoryManager.get(anyList())).thenAnswer(new Answer>() { + @Override + public List answer(InvocationOnMock invocationOnMock) throws Throwable { + List query = (List) invocationOnMock.getArguments()[0]; + List response = new LinkedList<>(query); + response.remove(0); + return response; + } + }); + + addResource(new DirectoryController(rateLimiters, directoryManager)); + } + + @Test + public void testContactIntersection() throws Exception { + List tokens = new LinkedList() {{ + add(Base64.encodeBytes("foo".getBytes())); + add(Base64.encodeBytes("bar".getBytes())); + add(Base64.encodeBytes("baz".getBytes())); + }}; + + List expectedResponse = new LinkedList<>(tokens); + expectedResponse.remove(0); + + ClientResponse response = + client().resource("/v1/directory/tokens/") + .entity(new ClientContactTokens(tokens)) + .type(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", + AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, + AuthHelper.VALID_PASSWORD)) + .put(ClientResponse.class); + + + + assertThat(response.getStatus()).isEqualTo(200); + assertThat(response.getEntity(ClientContactTokens.class).getContacts()).isEqualTo(expectedResponse); + } +}