diff --git a/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java b/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java index a9750bc3c..0491fcd05 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java +++ b/src/main/java/org/whispersystems/textsecuregcm/controllers/MessageController.java @@ -160,12 +160,14 @@ public class MessageController { @Timed @DELETE - @Path("/{message_id}") - public void removePendingMessage(@Auth Account account, @PathParam("message_id") long id) + @Path("/{source}/{timestamp}") + public void removePendingMessage(@Auth Account account, + @PathParam("source") String source, + @PathParam("timestamp") long timestamp) throws IOException { try { - Optional message = messagesManager.delete(account.getNumber(), id); + Optional message = messagesManager.delete(account.getNumber(), source, timestamp); if (message.isPresent() && message.get().getType() != OutgoingMessageSignal.Type.RECEIPT_VALUE) { receiptSender.sendReceipt(account, diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/Messages.java b/src/main/java/org/whispersystems/textsecuregcm/storage/Messages.java index db9c02de9..99e97d10a 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/Messages.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/Messages.java @@ -47,12 +47,12 @@ public abstract class Messages { @Bind("destination_device") long destinationDevice); @Mapper(MessageMapper.class) - @SqlQuery("DELETE FROM messages WHERE " + ID + " IN (SELECT " + ID + " FROM messages WHERE " + DESTINATION + " = :destination AND " + TIMESTAMP + " = :timestamp ORDER BY " + ID + " LIMIT 1) RETURNING *") - abstract OutgoingMessageEntity remove(@Bind("destination") String destination, @Bind("timestamp") long timestamp); + @SqlQuery("DELETE FROM messages WHERE " + ID + " IN (SELECT " + ID + " FROM messages WHERE " + DESTINATION + " = :destination AND " + SOURCE + " = :source AND " + TIMESTAMP + " = :timestamp ORDER BY " + ID + " LIMIT 1) RETURNING *") + abstract OutgoingMessageEntity remove(@Bind("destination") String destination, @Bind("source") String source, @Bind("timestamp") long timestamp); @Mapper(MessageMapper.class) - @SqlUpdate("DELETE FROM messages WHERE " + ID + " = :id") - abstract void remove(@Bind("id") long id); + @SqlUpdate("DELETE FROM messages WHERE " + ID + " = :id AND " + DESTINATION + " = :destination") + abstract void remove(@Bind("destination") String destination, @Bind("id") long id); @SqlUpdate("DELETE FROM messages WHERE " + DESTINATION + " = :destination") abstract void clear(@Bind("destination") String destination); diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java b/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java index 0e3144fa2..e163a922c 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java @@ -28,11 +28,11 @@ public class MessagesManager { this.messages.clear(destination); } - public Optional delete(String destination, long timestamp) { - return Optional.fromNullable(this.messages.remove(destination, timestamp)); + public Optional delete(String destination, String source, long timestamp) { + return Optional.fromNullable(this.messages.remove(destination, source, timestamp)); } - public void delete(long id) { - this.messages.remove(id); + public void delete(String destination, long id) { + this.messages.remove(destination, id); } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java b/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java index 40a55f3e6..457582507 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java +++ b/src/main/java/org/whispersystems/textsecuregcm/websocket/WebSocketConnection.java @@ -101,7 +101,7 @@ public class WebSocketConnection implements DispatchChannel { boolean isReceipt = message.getType() == OutgoingMessageSignal.Type.RECEIPT_VALUE; if (isSuccessResponse(response)) { - if (storedMessageId.isPresent()) messagesManager.delete(storedMessageId.get()); + if (storedMessageId.isPresent()) messagesManager.delete(account.getNumber(), storedMessageId.get()); if (!isReceipt) sendDeliveryReceiptFor(message); } else if (!isSuccessResponse(response) && !storedMessageId.isPresent()) { requeueMessage(message); diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java index 734a3e7aa..94c5d79e4 100644 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java +++ b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java @@ -218,37 +218,37 @@ public class MessageControllerTest { @Test public synchronized void testDeleteMessages() throws Exception { long timestamp = System.currentTimeMillis(); - when(messagesManager.delete(AuthHelper.VALID_NUMBER, 31337)) + when(messagesManager.delete(AuthHelper.VALID_NUMBER, "+14152222222", 31337)) .thenReturn(Optional.of(new OutgoingMessageEntity(31337L, MessageProtos.OutgoingMessageSignal.Type.CIPHERTEXT_VALUE, null, timestamp, "+14152222222", 1, "hi".getBytes()))); - when(messagesManager.delete(AuthHelper.VALID_NUMBER, 31338)) + when(messagesManager.delete(AuthHelper.VALID_NUMBER, "+14152222222", 31338)) .thenReturn(Optional.of(new OutgoingMessageEntity(31337L, MessageProtos.OutgoingMessageSignal.Type.RECEIPT_VALUE, null, System.currentTimeMillis(), "+14152222222", 1, null))); - when(messagesManager.delete(AuthHelper.VALID_NUMBER, 31339)) + when(messagesManager.delete(AuthHelper.VALID_NUMBER, "+14152222222", 31339)) .thenReturn(Optional.absent()); - ClientResponse response = resources.client().resource(String.format("/v1/messages/%d", 31337)) + ClientResponse response = resources.client().resource(String.format("/v1/messages/%s/%d", "+14152222222", 31337)) .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD)) .delete(ClientResponse.class); assertThat("Good Response Code", response.getStatus(), is(equalTo(204))); verify(receiptSender).sendReceipt(any(Account.class), eq("+14152222222"), eq(timestamp), eq(Optional.absent())); - response = resources.client().resource(String.format("/v1/messages/%d", 31338)) + response = resources.client().resource(String.format("/v1/messages/%s/%d", "+14152222222", 31338)) .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD)) .delete(ClientResponse.class); assertThat("Good Response Code", response.getStatus(), is(equalTo(204))); verifyNoMoreInteractions(receiptSender); - response = resources.client().resource(String.format("/v1/messages/%d", 31339)) + response = resources.client().resource(String.format("/v1/messages/%s/%d", "+14152222222", 31339)) .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD)) .delete(ClientResponse.class); diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/websocket/WebSocketConnectionTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/websocket/WebSocketConnectionTest.java index a37c59f34..4b561c9cb 100644 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/websocket/WebSocketConnectionTest.java +++ b/src/test/java/org/whispersystems/textsecuregcm/tests/websocket/WebSocketConnectionTest.java @@ -162,7 +162,7 @@ public class WebSocketConnectionTest { // add(createMessage("sender2", 3333, false, "third")); // }}; - verify(storedMessages, times(1)).delete(eq(2L)); + verify(storedMessages, times(1)).delete(eq(account.getNumber()), eq(2L)); // verify(pushSender, times(1)).sendMessage(eq(sender1), eq(sender1device), any(OutgoingMessageSignal.class));