package org.whispersystems.textsecuregcm.tests.controllers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.sun.jersey.api.client.ClientResponse;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.whispersystems.textsecuregcm.controllers.FederationControllerV1;
import org.whispersystems.textsecuregcm.controllers.FederationControllerV2;
import org.whispersystems.textsecuregcm.controllers.KeysControllerV2;
import org.whispersystems.textsecuregcm.controllers.MessageController;
import org.whispersystems.textsecuregcm.entities.IncomingMessageList;
import org.whispersystems.textsecuregcm.entities.MessageProtos;
import org.whispersystems.textsecuregcm.entities.PreKeyResponseItemV2;
import org.whispersystems.textsecuregcm.entities.PreKeyResponseV2;
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
import org.whispersystems.textsecuregcm.federation.FederatedClientManager;
import org.whispersystems.textsecuregcm.limits.RateLimiter;
import org.whispersystems.textsecuregcm.limits.RateLimiters;
import org.whispersystems.textsecuregcm.push.PushSender;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import javax.ws.rs.core.MediaType;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import io.dropwizard.testing.junit.ResourceTestRule;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.whispersystems.textsecuregcm.tests.util.JsonHelpers.jsonFixture;
public class FederatedControllerTest {
private static final String SINGLE_DEVICE_RECIPIENT = "+14151111111";
private static final String MULTI_DEVICE_RECIPIENT = "+14152222222";
private PushSender pushSender = mock(PushSender.class );
private FederatedClientManager federatedClientManager = mock(FederatedClientManager.class);
private AccountsManager accountsManager = mock(AccountsManager.class );
private RateLimiters rateLimiters = mock(RateLimiters.class );
private RateLimiter rateLimiter = mock(RateLimiter.class );
private final SignedPreKey signedPreKey = new SignedPreKey(3333, "foo", "baar");
private final PreKeyResponseV2 preKeyResponseV2 = new PreKeyResponseV2("foo", new LinkedList<PreKeyResponseItemV2>());
private final ObjectMapper mapper = new ObjectMapper();
private final MessageController messageController = new MessageController(rateLimiters, pushSender, accountsManager, federatedClientManager);
private final KeysControllerV2 keysControllerV2 = mock(KeysControllerV2.class);
@Rule
public final ResourceTestRule resources = ResourceTestRule.builder()
.addProvider(AuthHelper.getAuthenticator())
.addResource(new FederationControllerV1(accountsManager, null, messageController, null))
.addResource(new FederationControllerV2(accountsManager, null, messageController, keysControllerV2))
.build();
@Before
public void setup() throws Exception {
Set<Device> singleDeviceList = new HashSet<Device>() {{
add(new Device(1, "foo", "bar", "baz", "isgcm", null, false, 111, null, System.currentTimeMillis()));
}};
Set<Device> multiDeviceList = new HashSet<Device>() {{
add(new Device(1, "foo", "bar", "baz", "isgcm", null, false, 222, null, System.currentTimeMillis()));
add(new Device(2, "foo", "bar", "baz", "isgcm", null, false, 333, null, System.currentTimeMillis()));
}};
Account singleDeviceAccount = new Account(SINGLE_DEVICE_RECIPIENT, false, singleDeviceList);
Account multiDeviceAccount = new Account(MULTI_DEVICE_RECIPIENT, false, multiDeviceList);
when(accountsManager.get(eq(SINGLE_DEVICE_RECIPIENT))).thenReturn(Optional.of(singleDeviceAccount));
when(accountsManager.get(eq(MULTI_DEVICE_RECIPIENT))).thenReturn(Optional.of(multiDeviceAccount));
when(rateLimiters.getMessagesLimiter()).thenReturn(rateLimiter);
when(keysControllerV2.getSignedKey(any(Account.class))).thenReturn(Optional.of(signedPreKey));
when(keysControllerV2.getDeviceKeys(any(Account.class), anyString(), anyString(), any(Optional.class)))
.thenReturn(Optional.of(preKeyResponseV2));
}
@Test
public void testSingleDeviceCurrent() throws Exception {
ClientResponse response =
resources.client().resource(String.format("/v1/federation/messages/+14152223333/1/%s", SINGLE_DEVICE_RECIPIENT))
.header("Authorization", AuthHelper.getAuthHeader("cyanogen", "foofoo"))
.entity(mapper.readValue(jsonFixture("fixtures/current_message_single_device.json"), IncomingMessageList.class))
.type(MediaType.APPLICATION_JSON_TYPE)
.put(ClientResponse.class);
assertThat("Good Response", response.getStatus(), is(equalTo(204)));
verify(pushSender).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
}
@Test
public void testSignedPreKeyV2() throws Exception {
PreKeyResponseV2 response =
resources.client().resource("/v2/federation/key/+14152223333/1")
.header("Authorization", AuthHelper.getAuthHeader("cyanogen", "foofoo"))
.get(PreKeyResponseV2.class);
assertThat("good response", response.getIdentityKey().equals(preKeyResponseV2.getIdentityKey()));
}
}