From 6c6dbfd357d3d17f8fbb566e81e7e2a27e3d8727 Mon Sep 17 00:00:00 2001 From: Nico Alt Date: Fri, 25 Sep 2020 18:30:44 +0200 Subject: [PATCH 1/2] Add method to delete all private messages to REST API Needed for https://code.briarproject.org/briar/briar-gtk/-/issues/11. Fixes #1782 --- briar-headless/README.md | 6 +++++ .../org/briarproject/briar/headless/Router.kt | 3 +++ .../headless/messaging/MessagingController.kt | 2 ++ .../messaging/MessagingControllerImpl.kt | 10 ++++++++ .../messaging/MessagingControllerImplTest.kt | 25 +++++++++++++++++++ 5 files changed, 46 insertions(+) diff --git a/briar-headless/README.md b/briar-headless/README.md index 69b5c6137..eda86afbe 100644 --- a/briar-headless/README.md +++ b/briar-headless/README.md @@ -247,6 +247,12 @@ needs to be provided in the request body as follows: } ``` +### Deleting all private messages + +`DELETE /v1/messages/{contactId}/all` + +It returns with a status code `200`, if removal was successful. + ### Listing blog posts `GET /v1/blogs/posts` diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt index 4d226a559..a268607b0 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt @@ -89,6 +89,9 @@ constructor( path("/messages/:contactId/read") { post { ctx -> messagingController.markMessageRead(ctx) } } + path("/messages/:contactId/all") { + delete { ctx -> messagingController.deleteAllMessages(ctx) } + } path("/forums") { get { ctx -> forumController.list(ctx) } post { ctx -> forumController.create(ctx) } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt index 6fe4f23fa..ae6616d0b 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt @@ -10,4 +10,6 @@ interface MessagingController { fun markMessageRead(ctx: Context): Context + fun deleteAllMessages(ctx: Context): Context + } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt index 533e519e6..b0b6c3586 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt @@ -106,6 +106,16 @@ constructor( return MessageId(idBytes) } + override fun deleteAllMessages(ctx: Context): Context { + val contactId = ctx.getContactIdFromPathParam() + try { + conversationManager.deleteAllMessages(contactId) + } catch (e: NoSuchContactException) { + throw NotFoundResponse() + } + return ctx + } + override fun eventOccurred(e: Event) { when (e) { is ConversationMessageReceivedEvent<*> -> { diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt index d827e50e6..2cecd7b1c 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt @@ -17,6 +17,7 @@ import org.briarproject.bramble.test.ImmediateExecutor import org.briarproject.bramble.test.TestUtils.getRandomId import org.briarproject.bramble.util.StringUtils.getRandomString import org.briarproject.briar.api.client.SessionId +import org.briarproject.briar.api.conversation.DeletionResult import org.briarproject.briar.api.introduction.IntroductionRequest import org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH import org.briarproject.briar.api.messaging.MessagingManager @@ -343,6 +344,30 @@ internal class MessagingControllerImplTest : ControllerTest() { assertJsonEquals(json, request.output(contact.id)) } + @Test + fun testDeleteAllMessages() { + every { ctx.pathParam("contactId") } returns "1" + every { conversationManager.deleteAllMessages(ContactId(1)) } returns DeletionResult() + controller.deleteAllMessages(ctx) + } + + @Test + fun testDeleteAllMessagesInvalidContactId() { + every { ctx.pathParam("contactId") } returns "foo" + assertThrows(NotFoundResponse::class.java) { + controller.deleteAllMessages(ctx) + } + } + + @Test + fun testDeleteAllMessagesNonexistentContactId() { + every { ctx.pathParam("contactId") } returns "1" + every { conversationManager.deleteAllMessages(ContactId(1)) } throws NoSuchContactException() + assertThrows(NotFoundResponse::class.java) { + controller.deleteAllMessages(ctx) + } + } + private fun expectGetContact() { every { ctx.pathParam("contactId") } returns contact.id.int.toString() every { contactManager.getContact(contact.id) } returns contact From c017a813b0363a695b815f5d148f06dd9e2665ea Mon Sep 17 00:00:00 2001 From: Nico Alt Date: Thu, 8 Oct 2020 14:42:40 +0200 Subject: [PATCH 2/2] Add output of DeletionResult to deleteAllMessages call --- .../messaging/MessagingControllerImpl.kt | 4 +-- .../messaging/OutputConversationMessage.kt | 10 +++++++ .../messaging/MessagingControllerImplTest.kt | 26 ++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt index b0b6c3586..c3bdb96ee 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingControllerImpl.kt @@ -109,11 +109,11 @@ constructor( override fun deleteAllMessages(ctx: Context): Context { val contactId = ctx.getContactIdFromPathParam() try { - conversationManager.deleteAllMessages(contactId) + val result = conversationManager.deleteAllMessages(contactId) + return ctx.json(result.output()) } catch (e: NoSuchContactException) { throw NotFoundResponse() } - return ctx } override fun eventOccurred(e: Event) { diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputConversationMessage.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputConversationMessage.kt index 3c42a39d0..487bcdbb0 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputConversationMessage.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputConversationMessage.kt @@ -5,6 +5,7 @@ import org.briarproject.bramble.api.sync.MessageId import org.briarproject.bramble.api.sync.event.MessagesAckedEvent import org.briarproject.bramble.api.sync.event.MessagesSentEvent import org.briarproject.briar.api.conversation.ConversationMessageHeader +import org.briarproject.briar.api.conversation.DeletionResult import org.briarproject.briar.api.messaging.PrivateMessage import org.briarproject.briar.api.messaging.PrivateMessageHeader import org.briarproject.briar.headless.json.JsonDict @@ -47,6 +48,15 @@ internal fun PrivateMessage.output(contactId: ContactId, text: String) = JsonDic "text" to text ) +internal fun DeletionResult.output() = JsonDict( + "allDeleted" to allDeleted(), + "hasIntroductionSessionInProgress" to hasIntroductionSessionInProgress(), + "hasInvitationSessionInProgress" to hasInvitationSessionInProgress(), + "hasNotAllIntroductionSelected" to hasNotAllIntroductionSelected(), + "hasNotAllInvitationSelected" to hasNotAllInvitationSelected(), + "hasNotFullyDownloaded" to hasNotFullyDownloaded() +) + internal fun MessagesAckedEvent.output() = JsonDict( "contactId" to contactId.int, "messageIds" to messageIds.toJson() diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt index 2cecd7b1c..84c7c5ec2 100644 --- a/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/messaging/MessagingControllerImplTest.kt @@ -33,6 +33,7 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Test import org.spongycastle.util.encoders.Base64 +import kotlin.random.Random internal class MessagingControllerImplTest : ControllerTest() { @@ -346,8 +347,10 @@ internal class MessagingControllerImplTest : ControllerTest() { @Test fun testDeleteAllMessages() { + val result = DeletionResult() every { ctx.pathParam("contactId") } returns "1" - every { conversationManager.deleteAllMessages(ContactId(1)) } returns DeletionResult() + every { conversationManager.deleteAllMessages(ContactId(1)) } returns result + every { ctx.json(result.output()) } returns ctx controller.deleteAllMessages(ctx) } @@ -368,6 +371,27 @@ internal class MessagingControllerImplTest : ControllerTest() { } } + @Test + fun testOutputDeletionResult() { + val result = DeletionResult() + if (Random.nextBoolean()) result.addInvitationNotAllSelected() + if (Random.nextBoolean()) result.addInvitationSessionInProgress() + if (Random.nextBoolean()) result.addIntroductionNotAllSelected() + if (Random.nextBoolean()) result.addIntroductionSessionInProgress() + if (Random.nextBoolean()) result.addNotFullyDownloaded() + val json = """ + { + "allDeleted": ${result.allDeleted()}, + "hasIntroductionSessionInProgress": ${result.hasIntroductionSessionInProgress()}, + "hasInvitationSessionInProgress": ${result.hasInvitationSessionInProgress()}, + "hasNotAllIntroductionSelected": ${result.hasNotAllIntroductionSelected()}, + "hasNotAllInvitationSelected": ${result.hasNotAllInvitationSelected()}, + "hasNotFullyDownloaded": ${result.hasNotFullyDownloaded()} + } + """ + assertJsonEquals(json, result.output()) + } + private fun expectGetContact() { every { ctx.pathParam("contactId") } returns contact.id.int.toString() every { contactManager.getContact(contact.id) } returns contact