Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect redactions #168

Merged
merged 2 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,27 @@ internal class RoomPersistence(
private val coroutineDispatchers: CoroutineDispatchers,
) : RoomStore {

override suspend fun persist(roomId: RoomId, state: RoomState) {
override suspend fun persist(roomId: RoomId, events: List<RoomEvent>) {
coroutineDispatchers.withIoContext {
database.transaction {
state.events.forEach {
events.forEach {
database.roomEventQueries.insertRoomEvent(roomId, it)
}
}
}
}

override suspend fun remove(rooms: List<RoomId>) {
coroutineDispatchers
database.roomEventQueries.transaction {
rooms.forEach { database.roomEventQueries.remove(it.value) }
coroutineDispatchers.withIoContext {
database.roomEventQueries.transaction {
rooms.forEach { database.roomEventQueries.remove(it.value) }
}
}
}

override suspend fun remove(eventId: EventId) {
coroutineDispatchers.withIoContext {
database.roomEventQueries.removeEvent(eventId.value)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ LIMIT 100;

remove:
DELETE FROM dbRoomEvent
WHERE room_id = ?;
WHERE room_id = ?;

removeEvent:
DELETE FROM dbRoomEvent
WHERE event_id = ?;
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ sealed class RoomEvent {
@SerialName("meta") override val meta: MessageMeta,
@SerialName("encrypted_content") val encryptedContent: MegOlmV1? = null,
@SerialName("edited") val edited: Boolean = false,
@SerialName("redacted") val redacted: Boolean = false,
) : RoomEvent() {

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import kotlinx.coroutines.flow.Flow

interface RoomStore {

suspend fun persist(roomId: RoomId, state: RoomState)
suspend fun persist(roomId: RoomId, events: List<RoomEvent>)
suspend fun remove(rooms: List<RoomId>)
suspend fun remove(eventId: EventId)
suspend fun retrieve(roomId: RoomId): RoomState?
fun latest(roomId: RoomId): Flow<RoomState>
suspend fun insertUnread(roomId: RoomId, eventIds: List<EventId>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ internal sealed class ApiTimelineEvent {
)
}


@Serializable
@SerialName("m.room.member")
internal data class RoomMember(
Expand All @@ -109,6 +108,15 @@ internal sealed class ApiTimelineEvent {
}
}

@Serializable
@SerialName("m.room.redaction")
internal data class RoomRedcation(
@SerialName("event_id") val id: EventId,
@SerialName("redacts") val redactedId: EventId,
@SerialName("origin_server_ts") val utcTimestamp: Long,
@SerialName("sender") val senderId: UserId,
) : ApiTimelineEvent()

@Serializable
internal data class DecryptionStatus(
@SerialName("is_verified") val isVerified: Boolean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package app.dapk.st.matrix.sync.internal.sync

import app.dapk.st.matrix.common.MatrixLogTag
import app.dapk.st.matrix.common.MatrixLogger
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.matrix.common.matrixLog
import app.dapk.st.matrix.common.*
import app.dapk.st.matrix.sync.RoomEvent
import app.dapk.st.matrix.sync.RoomState
import app.dapk.st.matrix.sync.RoomStore

Expand All @@ -26,12 +24,43 @@ class RoomDataSource(
logger.matrixLog(MatrixLogTag.SYNC, "no changes, not persisting")
} else {
roomCache[roomId] = newState
roomStore.persist(roomId, newState)
roomStore.persist(roomId, newState.events)
}
}

suspend fun remove(roomsLeft: List<RoomId>) {
roomsLeft.forEach { roomCache.remove(it) }
roomStore.remove(roomsLeft)
}

suspend fun redact(roomId: RoomId, event: EventId) {
val eventToRedactFromCache = roomCache[roomId]?.events?.find { it.eventId == event }
val redactedEvent = when {
eventToRedactFromCache != null -> {
eventToRedactFromCache.redact().also { redacted ->
val cachedRoomState = roomCache[roomId]
requireNotNull(cachedRoomState)
roomCache[roomId] = cachedRoomState.replaceEvent(eventToRedactFromCache, redacted)
}
}

else -> roomStore.findEvent(event)?.redact()
}

redactedEvent?.let { roomStore.persist(roomId, listOf(it)) }
}
}

private fun RoomEvent.redact() = when (this) {
is RoomEvent.Image -> RoomEvent.Message(this.eventId, this.utcTimestamp, "Redacted", this.author, this.meta, redacted = true)
is RoomEvent.Message -> RoomEvent.Message(this.eventId, this.utcTimestamp, "Redacted", this.author, this.meta, redacted = true)
is RoomEvent.Reply -> RoomEvent.Message(this.eventId, this.utcTimestamp, "Redacted", this.author, this.meta, redacted = true)
}

private fun RoomState.replaceEvent(old: RoomEvent, new: RoomEvent): RoomState {
val updatedEvents = this.events.toMutableList().apply {
remove(old)
add(new)
}
return this.copy(events = updatedEvents)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ internal class RoomProcessor(
val members = roomToProcess.apiSyncRoom.collectMembers(roomToProcess.userCredentials)
roomMembersService.insert(roomToProcess.roomId, members)

roomToProcess.apiSyncRoom.timeline.apiTimelineEvents.filterIsInstance<ApiTimelineEvent.RoomRedcation>().forEach {
roomDataSource.redact(roomToProcess.roomId, it.redactedId)
}

val previousState = roomDataSource.read(roomToProcess.roomId)

val (newEvents, distinctEvents) = timelineEventsProcessor.process(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ internal class SyncReducer(
}
}

roomDataSource.remove(roomsLeft)

return ReducerResult(
newRooms,
(apiRoomsToProcess + roomsWithSideEffects).awaitAll().filterNotNull(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal class TimelineEventsProcessor(
is ApiTimelineEvent.TimelineMessage -> event.toRoomEvent(roomToProcess.userCredentials, roomToProcess.roomId) { eventId ->
eventLookupUseCase.lookup(eventId, decryptedTimeline, decryptedPreviousEvents)
}
is ApiTimelineEvent.RoomRedcation -> null
is ApiTimelineEvent.Encryption -> null
is ApiTimelineEvent.RoomAvatar -> null
is ApiTimelineEvent.RoomCreate -> null
Expand Down