Skip to content

Commit

Permalink
Lock moderated messages from editing (#122)
Browse files Browse the repository at this point in the history
Additionally clean up empty actions maps when removing actions
  • Loading branch information
wkal-pubnub authored Nov 27, 2024
1 parent a2fe6fa commit b88a242
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 182 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
*.podspec
node_modules
js-chat/dist

### IntelliJ IDEA ###
.idea/modules.xml
Expand Down
56 changes: 0 additions & 56 deletions pubnub-chat-api/pubnub_chat_api.podspec

This file was deleted.

56 changes: 0 additions & 56 deletions pubnub-chat-impl/pubnub_chat_impl.podspec

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ internal const val ORIGINAL_PUBLISHER = "originalPublisher"
internal const val ORIGINAL_CHANNEL_ID = "originalChannelId"
internal const val HTTP_ERROR_404 = 404
internal const val INTERNAL_MODERATION_PREFIX = "PUBNUB_INTERNAL_MODERATION_"
internal const val PUBNUB_INTERNAL_AUTOMODERATED = "PUBNUB_INTERNAL_AUTOMODERATED"
internal const val INTERNAL_MODERATOR_DATA_ID = "PUBNUB_INTERNAL_MODERATOR"
internal const val INTERNAL_MODERATOR_DATA_TYPE = "internal"
internal const val MESSAGE_THREAD_ID_PREFIX = "PUBNUB_INTERNAL_THREAD"
internal val MINIMAL_TYPING_INDICATOR_TIMEOUT: Duration = 1.seconds
internal const val THREAD_ROOT_ID = "threadRootId"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,4 @@ data class UserImpl(
}

internal val User.uuidFilterString get() = "uuid.id == '${this.id}'"
internal val User.isInternalModerator get() = this.id == INTERNAL_MODERATOR_DATA_ID && this.type == INTERNAL_MODERATOR_DATA_TYPE
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ internal object PubNubErrorMessage {
internal const val CANNOT_QUOTE_MESSAGE_FROM_OTHER_CHANNELS = "You cannot quote messages from other channels"
internal const val MENTION_SUGGESTION_INVALID = "This mention suggestion is no longer valid - the message draft text has been changed."
internal const val MENTION_CANNOT_INTERSECT = "Cannot intersect with existing mention:"
internal const val AUTOMODERATED_MESSAGE_CANNOT_BE_EDITED = "The automoderated message can no longer be edited"
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ import com.pubnub.chat.internal.METADATA_MENTIONED_USERS
import com.pubnub.chat.internal.METADATA_QUOTED_MESSAGE
import com.pubnub.chat.internal.METADATA_REFERENCED_CHANNELS
import com.pubnub.chat.internal.METADATA_TEXT_LINKS
import com.pubnub.chat.internal.PUBNUB_INTERNAL_AUTOMODERATED
import com.pubnub.chat.internal.THREAD_ROOT_ID
import com.pubnub.chat.internal.channel.ChannelImpl
import com.pubnub.chat.internal.error.PubNubErrorMessage
import com.pubnub.chat.internal.error.PubNubErrorMessage.AUTOMODERATED_MESSAGE_CANNOT_BE_EDITED
import com.pubnub.chat.internal.error.PubNubErrorMessage.CANNOT_STREAM_MESSAGE_UPDATES_ON_EMPTY_LIST
import com.pubnub.chat.internal.error.PubNubErrorMessage.KEY_IS_NOT_VALID_INTEGER
import com.pubnub.chat.internal.error.PubNubErrorMessage.THIS_MESSAGE_HAS_NOT_BEEN_DELETED
import com.pubnub.chat.internal.isInternalModerator
import com.pubnub.chat.internal.serialization.PNDataEncoder
import com.pubnub.chat.internal.util.logErrorAndReturnException
import com.pubnub.chat.internal.util.pnError
import com.pubnub.chat.types.EventContent
import com.pubnub.chat.types.File
Expand Down Expand Up @@ -115,6 +119,10 @@ abstract class BaseMessage<T : Message>(

override fun editText(newText: String): PNFuture<Message> {
val type = chat.editMessageActionName
if (this.meta?.containsKey(PUBNUB_INTERNAL_AUTOMODERATED) == true && !this.chat.currentUser.isInternalModerator) {
return log.logErrorAndReturnException(AUTOMODERATED_MESSAGE_CANNOT_BE_EDITED).asFuture()
}

return chat.pubNub.addMessageAction(
channelId,
PNMessageAction(
Expand Down Expand Up @@ -375,23 +383,23 @@ abstract class BaseMessage<T : Message>(
internal fun filterAction(actions: Actions?, action: PNMessageAction): Actions {
return buildMap {
actions?.entries?.forEach { entry ->
put(
entry.key,
buildMap {
entry.value.forEach { innerEntry ->
if (entry.key == action.type && innerEntry.key == action.value) {
put(
innerEntry.key,
innerEntry.value.filter {
it.actionTimetoken != action.actionTimetoken || it.uuid != action.uuid
}
)
} else {
put(innerEntry.key, innerEntry.value)
val actionMap = buildMap {
entry.value.forEach { innerEntry ->
if (entry.key == action.type && innerEntry.key == action.value) {
val actionList = innerEntry.value.filter {
it.actionTimetoken != action.actionTimetoken || it.uuid != action.uuid
}
if (actionList.isNotEmpty()) {
put(innerEntry.key, actionList)
}
} else {
put(innerEntry.key, innerEntry.value)
}
}
)
}
if (actionMap.isNotEmpty()) {
put(entry.key, actionMap)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.pubnub.kmp

import com.pubnub.api.createJsonElement
import com.pubnub.chat.internal.ChatInternal
import com.pubnub.chat.internal.INTERNAL_MODERATOR_DATA_ID
import com.pubnub.chat.internal.INTERNAL_MODERATOR_DATA_TYPE
import com.pubnub.chat.internal.PUBNUB_INTERNAL_AUTOMODERATED
import com.pubnub.chat.internal.UserImpl
import com.pubnub.chat.internal.message.MessageImpl
import com.pubnub.chat.types.EventContent
import com.pubnub.kmp.utils.BaseTest
import com.pubnub.test.await
import dev.mokkery.answering.returns
import dev.mokkery.every
import dev.mokkery.mock
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.test.assertNotEquals

class BaseMessageTest : BaseTest() {
val chat: ChatInternal = mock()

@Test
fun shouldThrowExceptionOnEditTextWhenMessageWasModerated() = runTest {
every { chat.currentUser } returns UserImpl(chat, "")
every { chat.editMessageActionName } returns "edit"
val message =
MessageImpl(
chat,
1L,
EventContent.TextMessageContent(""),
"",
"",
metaInternal = createJsonElement(mapOf(PUBNUB_INTERNAL_AUTOMODERATED to true))
)
val exception = assertFails { message.editText("aaa").await() }
assertEquals("The automoderated message can no longer be edited", exception.message)
}

@Test
fun shouldNotThrowExceptionOnEditTextWhenMessageWasNotModerated() = runTest {
every { chat.currentUser } returns UserImpl(chat, "")
every { chat.editMessageActionName } returns "edit"
val message = MessageImpl(chat, 1L, EventContent.TextMessageContent(""), "", "")
val exception = assertFails { message.editText("aaa").await() }
assertNotEquals("The automoderated message can no longer be edited", exception.message)
}

@Test
fun shouldNotThrowExceptionOnEditTextWhenUserIsModerator() = runTest {
every { chat.currentUser } returns UserImpl(chat, INTERNAL_MODERATOR_DATA_ID, type = INTERNAL_MODERATOR_DATA_TYPE)
every { chat.editMessageActionName } returns "edit"
val message =
MessageImpl(
chat,
1L,
EventContent.TextMessageContent(""),
"",
"",
metaInternal = createJsonElement(mapOf(PUBNUB_INTERNAL_AUTOMODERATED to true))
)
val exception = assertFails { message.editText("aaa").await() }
assertNotEquals("The automoderated message can no longer be edited", exception.message)
}
}
56 changes: 0 additions & 56 deletions pubnub_chat.podspec

This file was deleted.

0 comments on commit b88a242

Please sign in to comment.