From 9738dd2838e554e1b6678ce0294580b58e332275 Mon Sep 17 00:00:00 2001 From: Nico Alt Date: Sat, 3 Oct 2020 19:29:39 +0200 Subject: [PATCH] Add method to mark message as read to REST API When exposing unread messages counters in https://code.briarproject.org/briar/briar/-/merge_requests/1283, I noticed that they were never set to 0. Fixes #1780 --- briar-headless/README.md | 13 +++++++++ .../org/briarproject/briar/headless/Router.kt | 3 ++ .../headless/messaging/MessagingController.kt | 2 ++ .../messaging/MessagingControllerImpl.kt | 23 +++++++++++++++ .../messaging/MessagingControllerImplTest.kt | 28 +++++++++++++++++++ 5 files changed, 69 insertions(+) diff --git a/briar-headless/README.md b/briar-headless/README.md index fbeb7c804..69b5c6137 100644 --- a/briar-headless/README.md +++ b/briar-headless/README.md @@ -234,6 +234,19 @@ The text of the message should be posted as JSON: } ``` +### Marking private messages as read + +`POST /v1/messages/{contactId}/read` + +The `messageId` of the message to be marked as read +needs to be provided in the request body as follows: + +```json +{ + "messageId": "+AIMMgOCPFF8HDEhiEHYjbfKrg7v0G94inKxjvjYzA8=" +} +``` + ### 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 940eac8fe..4d226a559 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 @@ -86,6 +86,9 @@ constructor( get { ctx -> messagingController.list(ctx) } post { ctx -> messagingController.write(ctx) } } + path("/messages/:contactId/read") { + post { ctx -> messagingController.markMessageRead(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 55d7024f4..6fe4f23fa 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 @@ -8,4 +8,6 @@ interface MessagingController { fun write(ctx: Context): Context + fun markMessageRead(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 df5607170..533e519e6 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 @@ -13,6 +13,7 @@ import org.briarproject.bramble.api.event.Event import org.briarproject.bramble.api.event.EventListener import org.briarproject.bramble.api.sync.event.MessagesAckedEvent import org.briarproject.bramble.api.sync.event.MessagesSentEvent +import org.briarproject.bramble.api.sync.MessageId import org.briarproject.bramble.api.system.Clock import org.briarproject.bramble.util.StringUtils.utf8IsTooLong import org.briarproject.briar.api.blog.BlogInvitationRequest @@ -35,6 +36,8 @@ import org.briarproject.briar.headless.event.output import org.briarproject.briar.headless.getContactIdFromPathParam import org.briarproject.briar.headless.getFromJson import org.briarproject.briar.headless.json.JsonDict +import org.spongycastle.util.encoders.Base64 +import org.spongycastle.util.encoders.DecoderException import java.util.concurrent.Executor import javax.annotation.concurrent.Immutable import javax.inject.Inject @@ -83,6 +86,26 @@ constructor( return ctx.json(m.output(contact.id, text)) } + override fun markMessageRead(ctx: Context): Context { + val contact = getContact(ctx) + val groupId = messagingManager.getContactGroup(contact).id + + val messageIdString = ctx.getFromJson(objectMapper, "messageId") + val messageId = deserializeMessageId(messageIdString) + messagingManager.setReadFlag(groupId, messageId, true) + return ctx.json(messageIdString) + } + + private fun deserializeMessageId(idString: String): MessageId { + val idBytes = try { + Base64.decode(idString) + } catch (e: DecoderException) { + throw NotFoundResponse() + } + if (idBytes.size != MessageId.LENGTH) throw NotFoundResponse() + return MessageId(idBytes) + } + 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 6feac73e2..d827e50e6 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 @@ -26,10 +26,12 @@ import org.briarproject.briar.api.messaging.PrivateMessageHeader import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent import org.briarproject.briar.headless.ControllerTest import org.briarproject.briar.headless.event.output +import org.briarproject.briar.headless.getFromJson import org.briarproject.briar.headless.json.JsonDict 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 internal class MessagingControllerImplTest : ControllerTest() { @@ -198,6 +200,32 @@ internal class MessagingControllerImplTest : ControllerTest() { assertThrows(BadRequestResponse::class.java) { controller.write(ctx) } } + @Test + fun markMessageRead() { + mockkStatic("org.briarproject.briar.headless.RouterKt") + mockkStatic("org.spongycastle.util.encoders.Base64") + expectGetContact() + + val messageIdString = message.id.bytes.toString() + every { messagingManager.getContactGroup(contact).id } returns group.id + every { ctx.getFromJson(objectMapper, "messageId") } returns messageIdString + every { Base64.decode(messageIdString) } returns message.id.bytes + every { messagingManager.setReadFlag(group.id, message.id, true) } just Runs + every { ctx.json(messageIdString) } returns ctx + + controller.markMessageRead(ctx) + } + + @Test + fun markMessageReadInvalidContactId() { + testInvalidContactId { controller.markMessageRead(ctx) } + } + + @Test + fun markMessageReadNonexistentId() { + testNonexistentContactId { controller.markMessageRead(ctx) } + } + @Test fun privateMessageEvent() { val event = PrivateMessageReceivedEvent(header, contact.id)