From c095cc73cec34516673e275aad86d7d3d5c999e9 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Fri, 1 Jul 2022 17:07:40 +0200 Subject: [PATCH] Introducing use case to check if an event can be redacted --- .../action/CheckIfCanRedactEventUseCase.kt | 38 ++++++ .../action/MessageActionsViewModel.kt | 8 +- .../CheckIfCanRedactEventUseCaseTest.kt | 115 ++++++++++++++++++ 3 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCase.kt create mode 100644 vector/src/test/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCaseTest.kt diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCase.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCase.kt new file mode 100644 index 0000000000..222df8f914 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCase.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.detail.timeline.action + +import im.vector.app.core.di.ActiveSessionHolder +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent +import javax.inject.Inject + +class CheckIfCanRedactEventUseCase @Inject constructor( + private val activeSessionHolder: ActiveSessionHolder +) { + + fun execute(event: TimelineEvent, actionPermissions: ActionPermissions): Boolean { + // Only some event types are supported for the moment + val canRedactEventTypes = listOf(EventType.MESSAGE, EventType.STICKER) + + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO + if (event.root.getClearType() !in canRedactEventTypes) return false + // Message sent by the current user can always be redacted + if (event.root.senderId == activeSessionHolder.getActiveSession().myUserId) return true + // Check permission for messages sent by other users + return actionPermissions.canRedact + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index 30786dc77a..3dfb6744e0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -82,6 +82,7 @@ class MessageActionsViewModel @AssistedInject constructor( private val pillsPostProcessorFactory: PillsPostProcessor.Factory, private val vectorPreferences: VectorPreferences, private val checkIfCanReplyEventUseCase: CheckIfCanReplyEventUseCase, + private val checkIfCanRedactEventUseCase: CheckIfCanRedactEventUseCase, ) : VectorViewModel(initialState) { private val informationData = initialState.informationData @@ -518,12 +519,7 @@ class MessageActionsViewModel @AssistedInject constructor( } private fun canRedact(event: TimelineEvent, actionPermissions: ActionPermissions): Boolean { - // Only event of type EventType.MESSAGE, EventType.STICKER and EventType.POLL_START are supported for the moment - if (event.root.getClearType() !in listOf(EventType.MESSAGE, EventType.STICKER) + EventType.POLL_START) return false - // Message sent by the current user can always be redacted - if (event.root.senderId == session.myUserId) return true - // Check permission for messages sent by other users - return actionPermissions.canRedact + return checkIfCanRedactEventUseCase.execute(event, actionPermissions) } private fun canRetry(event: TimelineEvent, actionPermissions: ActionPermissions): Boolean { diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCaseTest.kt new file mode 100644 index 0000000000..08dd5dac5b --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/action/CheckIfCanRedactEventUseCaseTest.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.detail.timeline.action + +import im.vector.app.test.fakes.FakeActiveSessionHolder +import io.mockk.mockk +import org.amshove.kluent.shouldBe +import org.junit.Test +import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent + +class CheckIfCanRedactEventUseCaseTest { + + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + + private val checkIfCanRedactEventUseCase = CheckIfCanRedactEventUseCase( + activeSessionHolder = fakeActiveSessionHolder.instance + ) + + @Test + fun `given an event which can be redacted and owned by user when use case executes then the result is true`() { + val canRedactEventTypes = listOf(EventType.MESSAGE, EventType.STICKER) + + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO + + canRedactEventTypes.forEach { eventType -> + val event = givenAnEvent( + eventType = eventType, + senderId = fakeActiveSessionHolder.fakeSession.myUserId + ) + + val actionPermissions = givenActionPermissions(canRedact = false) + + val result = checkIfCanRedactEventUseCase.execute(event, actionPermissions) + + result shouldBe true + } + } + + @Test + fun `given redact permission and an event which can be redacted and sent by another user when use case executes then the result is true`() { + val event = givenAnEvent( + eventType = EventType.MESSAGE, + senderId = "user-id" + ) + + val actionPermissions = givenActionPermissions(canRedact = true) + + val result = checkIfCanRedactEventUseCase.execute(event, actionPermissions) + + result shouldBe true + } + + @Test + fun `given an event which cannot be redacted when use case executes then the result is false`() { + val event = givenAnEvent( + eventType = EventType.CALL_ANSWER, + senderId = fakeActiveSessionHolder.fakeSession.myUserId + ) + + val actionPermissions = givenActionPermissions(canRedact = false) + + val result = checkIfCanRedactEventUseCase.execute(event, actionPermissions) + + result shouldBe false + } + + @Test + fun `given missing redact permission and an event which can be redacted and sent by another user when use case executes then the result is false`() { + val event = givenAnEvent( + eventType = EventType.MESSAGE, + senderId = "user-id" + ) + + val actionPermissions = givenActionPermissions(canRedact = false) + + val result = checkIfCanRedactEventUseCase.execute(event, actionPermissions) + + result shouldBe false + } + + private fun givenAnEvent(eventType: String, senderId: String): TimelineEvent { + val eventId = "event-id" + return TimelineEvent( + root = Event( + eventId = eventId, + type = eventType, + senderId = senderId + ), + localId = 123L, + eventId = eventId, + displayIndex = 1, + ownedByThreadChunk = false, + senderInfo = mockk() + ) + } + + private fun givenActionPermissions(canRedact: Boolean): ActionPermissions { + return ActionPermissions(canRedact = canRedact) + } +}