@Timed @DELETE @Path("/apn/") public void deleteApnRegistrationId(@Auth Account account) { Device device = account.getAuthenticatedDevice().get(); device.setApnId(null); accounts.update(account); }
@Timed @PUT @Consumes(MediaType.APPLICATION_JSON) @Path("/code/{verification_code}") public void verifyAccount( @PathParam("verification_code") String verificationCode, @HeaderParam("Authorization") String authorizationHeader, @Valid AccountAttributes accountAttributes) throws RateLimitExceededException { try { AuthorizationHeader header = AuthorizationHeader.fromFullHeader(authorizationHeader); String number = header.getNumber(); String password = header.getPassword(); rateLimiters.getVerifyLimiter().validate(number); Optional<String> storedVerificationCode = pendingAccounts.getCodeForNumber(number); if (!storedVerificationCode.isPresent() || !verificationCode.equals(storedVerificationCode.get())) { throw new WebApplicationException(Response.status(403).build()); } Device device = new Device(); device.setId(Device.MASTER_ID); device.setAuthenticationCredentials(new AuthenticationCredentials(password)); device.setSignalingKey(accountAttributes.getSignalingKey()); device.setFetchesMessages(accountAttributes.getFetchesMessages()); device.setRegistrationId(accountAttributes.getRegistrationId()); Account account = new Account(); account.setNumber(number); account.setSupportsSms(accountAttributes.getSupportsSms()); account.addDevice(device); accounts.create(account); pendingAccounts.remove(number); logger.debug("Stored device..."); } catch (InvalidAuthorizationHeaderException e) { logger.info("Bad Authorization Header", e); throw new WebApplicationException(Response.status(401).build()); } }
@Timed @PUT @Path("/apn/") @Consumes(MediaType.APPLICATION_JSON) public void setApnRegistrationId(@Auth Account account, @Valid ApnRegistrationId registrationId) { Device device = account.getAuthenticatedDevice().get(); device.setApnId(registrationId.getApnRegistrationId()); device.setGcmId(null); accounts.update(account); }
@Test public void testCredentials() throws Exception { MessagesManager storedMessages = mock(MessagesManager.class); WebSocketAccountAuthenticator webSocketAuthenticator = new WebSocketAccountAuthenticator(accountAuthenticator); AuthenticatedConnectListener connectListener = new AuthenticatedConnectListener( accountsManager, pushSender, receiptSender, storedMessages, pubSubManager, apnFallbackManager); WebSocketSessionContext sessionContext = mock(WebSocketSessionContext.class); when(accountAuthenticator.authenticate(eq(new BasicCredentials(VALID_USER, VALID_PASSWORD)))) .thenReturn(Optional.of(account)); when(accountAuthenticator.authenticate( eq(new BasicCredentials(INVALID_USER, INVALID_PASSWORD)))) .thenReturn(Optional.<Account>absent()); when(account.getAuthenticatedDevice()).thenReturn(Optional.of(device)); when(upgradeRequest.getParameterMap()) .thenReturn( new HashMap<String, String[]>() { { put("login", new String[] {VALID_USER}); put("password", new String[] {VALID_PASSWORD}); } }); Optional<Account> account = webSocketAuthenticator.authenticate(upgradeRequest); when(sessionContext.getAuthenticated(Account.class)).thenReturn(account); connectListener.onWebSocketConnect(sessionContext); verify(sessionContext).addListener(any(WebSocketSessionContext.WebSocketEventListener.class)); when(upgradeRequest.getParameterMap()) .thenReturn( new HashMap<String, String[]>() { { put("login", new String[] {INVALID_USER}); put("password", new String[] {INVALID_PASSWORD}); } }); account = webSocketAuthenticator.authenticate(upgradeRequest); assertFalse(account.isPresent()); }
@Test public void testOnlineSend() throws Exception { MessagesManager storedMessages = mock(MessagesManager.class); OutgoingMessageSignal firstMessage = OutgoingMessageSignal.newBuilder() .setMessage(ByteString.copyFrom("first".getBytes())) .setSource("sender1") .setTimestamp(System.currentTimeMillis()) .setSourceDevice(1) .setType(OutgoingMessageSignal.Type.CIPHERTEXT_VALUE) .build(); OutgoingMessageSignal secondMessage = OutgoingMessageSignal.newBuilder() .setMessage(ByteString.copyFrom("second".getBytes())) .setSource("sender2") .setTimestamp(System.currentTimeMillis()) .setSourceDevice(2) .setType(OutgoingMessageSignal.Type.CIPHERTEXT_VALUE) .build(); List<OutgoingMessageEntity> pendingMessages = new LinkedList<>(); when(device.getId()).thenReturn(2L); when(device.getSignalingKey()).thenReturn(Base64.encodeBytes(new byte[52])); when(account.getAuthenticatedDevice()).thenReturn(Optional.of(device)); when(account.getNumber()).thenReturn("+14152222222"); final Device sender1device = mock(Device.class); Set<Device> sender1devices = new HashSet<Device>() { { add(sender1device); } }; Account sender1 = mock(Account.class); when(sender1.getDevices()).thenReturn(sender1devices); when(accountsManager.get("sender1")).thenReturn(Optional.of(sender1)); when(accountsManager.get("sender2")).thenReturn(Optional.<Account>absent()); when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId())) .thenReturn(pendingMessages); final List<SettableFuture<WebSocketResponseMessage>> futures = new LinkedList<>(); final WebSocketClient client = mock(WebSocketClient.class); when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), any(Optional.class))) .thenAnswer( new Answer<SettableFuture<WebSocketResponseMessage>>() { @Override public SettableFuture<WebSocketResponseMessage> answer( InvocationOnMock invocationOnMock) throws Throwable { SettableFuture<WebSocketResponseMessage> future = SettableFuture.create(); futures.add(future); return future; } }); WebsocketAddress websocketAddress = new WebsocketAddress(account.getNumber(), device.getId()); WebSocketConnection connection = new WebSocketConnection(pushSender, receiptSender, storedMessages, account, device, client); connection.onDispatchSubscribed(websocketAddress.serialize()); connection.onDispatchMessage( websocketAddress.serialize(), PubSubProtos.PubSubMessage.newBuilder() .setType(PubSubProtos.PubSubMessage.Type.DELIVER) .setContent(ByteString.copyFrom(firstMessage.toByteArray())) .build() .toByteArray()); connection.onDispatchMessage( websocketAddress.serialize(), PubSubProtos.PubSubMessage.newBuilder() .setType(PubSubProtos.PubSubMessage.Type.DELIVER) .setContent(ByteString.copyFrom(secondMessage.toByteArray())) .build() .toByteArray()); verify(client, times(2)).sendRequest(eq("PUT"), eq("/api/v1/message"), any(Optional.class)); assertEquals(futures.size(), 2); WebSocketResponseMessage response = mock(WebSocketResponseMessage.class); when(response.getStatus()).thenReturn(200); futures.get(1).set(response); futures.get(0).setException(new IOException()); verify(receiptSender, times(1)) .sendReceipt( eq(account), eq("sender2"), eq(secondMessage.getTimestamp()), eq(Optional.<String>absent())); verify(pushSender, times(1)) .sendMessage(eq(account), eq(device), any(OutgoingMessageSignal.class)); connection.onDispatchUnsubscribed(websocketAddress.serialize()); verify(client).close(anyInt(), anyString()); }
@Test public void testOpen() throws Exception { MessagesManager storedMessages = mock(MessagesManager.class); List<OutgoingMessageEntity> outgoingMessages = new LinkedList<OutgoingMessageEntity>() { { add(createMessage(1L, "sender1", 1111, false, "first")); add(createMessage(2L, "sender1", 2222, false, "second")); add(createMessage(3L, "sender2", 3333, false, "third")); } }; when(device.getId()).thenReturn(2L); when(device.getSignalingKey()).thenReturn(Base64.encodeBytes(new byte[52])); when(account.getAuthenticatedDevice()).thenReturn(Optional.of(device)); when(account.getNumber()).thenReturn("+14152222222"); final Device sender1device = mock(Device.class); Set<Device> sender1devices = new HashSet<Device>() { { add(sender1device); } }; Account sender1 = mock(Account.class); when(sender1.getDevices()).thenReturn(sender1devices); when(accountsManager.get("sender1")).thenReturn(Optional.of(sender1)); when(accountsManager.get("sender2")).thenReturn(Optional.<Account>absent()); when(storedMessages.getMessagesForDevice(account.getNumber(), device.getId())) .thenReturn(outgoingMessages); final List<SettableFuture<WebSocketResponseMessage>> futures = new LinkedList<>(); final WebSocketClient client = mock(WebSocketClient.class); when(client.sendRequest(eq("PUT"), eq("/api/v1/message"), any(Optional.class))) .thenAnswer( new Answer<SettableFuture<WebSocketResponseMessage>>() { @Override public SettableFuture<WebSocketResponseMessage> answer( InvocationOnMock invocationOnMock) throws Throwable { SettableFuture<WebSocketResponseMessage> future = SettableFuture.create(); futures.add(future); return future; } }); WebsocketAddress websocketAddress = new WebsocketAddress(account.getNumber(), device.getId()); WebSocketConnection connection = new WebSocketConnection(pushSender, receiptSender, storedMessages, account, device, client); connection.onDispatchSubscribed(websocketAddress.serialize()); verify(client, times(3)).sendRequest(eq("PUT"), eq("/api/v1/message"), any(Optional.class)); assertTrue(futures.size() == 3); WebSocketResponseMessage response = mock(WebSocketResponseMessage.class); when(response.getStatus()).thenReturn(200); futures.get(1).set(response); futures.get(0).setException(new IOException()); futures.get(2).setException(new IOException()); verify(storedMessages, times(1)).delete(eq(account.getNumber()), eq(2L)); verify(receiptSender, times(1)) .sendReceipt(eq(account), eq("sender1"), eq(2222L), eq(Optional.<String>absent())); connection.onDispatchUnsubscribed(websocketAddress.serialize()); verify(client).close(anyInt(), anyString()); }