From db1152cb72ad387ce25dc7ffd6e08e725507bd9b Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Wed, 26 Jan 2022 17:50:31 +0300 Subject: [PATCH 1/2] Allow ending polls if user created it. --- changelog.d/5067.bugfix | 1 + .../EventRelationsAggregationProcessor.kt | 31 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 changelog.d/5067.bugfix diff --git a/changelog.d/5067.bugfix b/changelog.d/5067.bugfix new file mode 100644 index 0000000000..7ad88b608d --- /dev/null +++ b/changelog.d/5067.bugfix @@ -0,0 +1 @@ +Poll cannot end in some unencrypted rooms \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt index 1577f3057f..d23e3f0d91 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt @@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponse import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent @@ -344,15 +345,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor( val targetEventId = relatedEventId ?: content.relatesTo?.eventId ?: return val eventTimestamp = event.originServerTs ?: return - val session = sessionManager.getSessionComponent(sessionId)?.session() - - val targetPollEvent = session?.getRoom(roomId)?.getTimeLineEvent(targetEventId) ?: return Unit.also { - Timber.v("## POLL target poll event $targetEventId not found in room $roomId") - } - - val targetPollContent = targetPollEvent.getLastMessageContent() as? MessagePollContent ?: return Unit.also { - Timber.v("## POLL target poll event $targetEventId content is malformed") - } + val targetPollContent = getPollContent(roomId, targetEventId) ?: return // ok, this is a poll response var existing = EventAnnotationsSummaryEntity.where(realm, roomId, targetEventId).findFirst() @@ -470,10 +463,13 @@ internal class EventRelationsAggregationProcessor @Inject constructor( return } + val pollOwnerId = getPollEvent(roomId, pollEventId)?.root?.senderId + val isPollOwner = pollOwnerId == sessionManager.getSessionComponent(sessionId)?.session()?.myUserId + val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) ?.content?.toModel() ?.let { PowerLevelsHelper(it) } - if (!powerLevelsHelper?.isUserAbleToRedact(event.senderId ?: "").orFalse()) { + if (!isPollOwner && !powerLevelsHelper?.isUserAbleToRedact(event.senderId ?: "").orFalse()) { Timber.v("## Received poll.end event $pollEventId but user ${event.senderId} doesn't have enough power level in room $roomId") return } @@ -491,6 +487,21 @@ internal class EventRelationsAggregationProcessor @Inject constructor( existingPollSummary.closedTime = event.originServerTs } + private fun getPollEvent(roomId: String, eventId: String): TimelineEvent? { + val session = sessionManager.getSessionComponent(sessionId)?.session() + return session?.getRoom(roomId)?.getTimeLineEvent(eventId) ?: return null.also { + Timber.v("## POLL target poll event $eventId not found in room $roomId") + } + } + + private fun getPollContent(roomId: String, eventId: String): MessagePollContent? { + val pollEvent = getPollEvent(roomId, eventId) ?: return null + + return pollEvent.getLastMessageContent() as? MessagePollContent ?: return null.also { + Timber.v("## POLL target poll event $eventId content is malformed") + } + } + private fun handleInitialAggregatedRelations(realm: Realm, event: Event, roomId: String, From 2ad7a020cf00dddb3a12ea9b88e171b6a3f94acd Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Thu, 27 Jan 2022 00:00:29 +0300 Subject: [PATCH 2/2] Current user is not a king to end polls, check event sender id instead. --- .../EventRelationsAggregationProcessor.kt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt index d23e3f0d91..3cc08df0e8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt @@ -446,6 +446,17 @@ internal class EventRelationsAggregationProcessor @Inject constructor( isLocalEcho: Boolean) { val pollEventId = content.relatesTo?.eventId ?: return + val pollOwnerId = getPollEvent(roomId, pollEventId)?.root?.senderId + val isPollOwner = pollOwnerId == event.senderId + + val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) + ?.content?.toModel() + ?.let { PowerLevelsHelper(it) } + if (!isPollOwner && !powerLevelsHelper?.isUserAbleToRedact(event.senderId ?: "").orFalse()) { + Timber.v("## Received poll.end event $pollEventId but user ${event.senderId} doesn't have enough power level in room $roomId") + return + } + var existing = EventAnnotationsSummaryEntity.where(realm, roomId, pollEventId).findFirst() if (existing == null) { Timber.v("## POLL creating new relation summary for $pollEventId") @@ -463,17 +474,6 @@ internal class EventRelationsAggregationProcessor @Inject constructor( return } - val pollOwnerId = getPollEvent(roomId, pollEventId)?.root?.senderId - val isPollOwner = pollOwnerId == sessionManager.getSessionComponent(sessionId)?.session()?.myUserId - - val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) - ?.content?.toModel() - ?.let { PowerLevelsHelper(it) } - if (!isPollOwner && !powerLevelsHelper?.isUserAbleToRedact(event.senderId ?: "").orFalse()) { - Timber.v("## Received poll.end event $pollEventId but user ${event.senderId} doesn't have enough power level in room $roomId") - return - } - val txId = event.unsignedData?.transactionId // is it a remote echo? if (!isLocalEcho && existingPollSummary.sourceLocalEchoEvents.contains(txId)) {