Skip to content

Commit

Permalink
Merge pull request #3743 from vector-im/florian14/dm_email_invite
Browse files Browse the repository at this point in the history
Update Account Data with user matrix id for invited user by email
  • Loading branch information
bmarty authored Aug 23, 2021
2 parents 49f2ac2 + 0a08746 commit 4a33fbb
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 13 deletions.
1 change: 1 addition & 0 deletions changelog.d/3743.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update the AccountData with the users' matrix Id instead of their email for those invited by email in a direct chat
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ internal class DefaultCreateRoomTask @Inject constructor(
this.isDirect = true
}
}
val directChats = directChatsHelper.getLocalUserAccount()
val directChats = directChatsHelper.getLocalDirectMessages()
updateUserAccountDataTask.execute(UpdateUserAccountDataTask.DirectChatParams(directMessages = directChats))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,30 @@ import io.realm.Realm
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.model.RoomMemberContent
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent
import org.matrix.android.sdk.internal.session.sync.SyncResponsePostTreatmentAggregator
import org.matrix.android.sdk.internal.session.user.UserEntityFactory
import javax.inject.Inject

internal class RoomMemberEventHandler @Inject constructor() {
internal class RoomMemberEventHandler @Inject constructor(
@UserId private val myUserId: String
) {

fun handle(realm: Realm, roomId: String, event: Event): Boolean {
fun handle(realm: Realm, roomId: String, event: Event, aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean {
if (event.type != EventType.STATE_ROOM_MEMBER) {
return false
}
val userId = event.stateKey ?: return false
val roomMember = event.getFixedRoomMemberContent()
return handle(realm, roomId, userId, roomMember)
return handle(realm, roomId, userId, roomMember, aggregator)
}

fun handle(realm: Realm, roomId: String, userId: String, roomMember: RoomMemberContent?): Boolean {
fun handle(realm: Realm,
roomId: String,
userId: String,
roomMember: RoomMemberContent?,
aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean {
if (roomMember == null) {
return false
}
Expand All @@ -45,6 +53,14 @@ internal class RoomMemberEventHandler @Inject constructor() {
val userEntity = UserEntityFactory.create(userId, roomMember)
realm.insertOrUpdate(userEntity)
}

// check whether this new room member event may be used to update the directs dictionary in account data
// this is required to handle correctly invite by email in DM
val mxId = roomMember.thirdPartyInvite?.signed?.mxid
if (mxId != null && mxId != myUserId) {
aggregator?.directChatsToCheck?.put(roomId, mxId)
}

return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
}
// Give info to crypto module
cryptoService.onStateEvent(roomId, event)
roomMemberEventHandler.handle(realm, roomId, event)
roomMemberEventHandler.handle(realm, roomId, event, aggregator)
}
}
if (roomSync.timeline?.events?.isNotEmpty() == true) {
Expand All @@ -233,7 +233,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
roomSync.timeline.prevToken,
roomSync.timeline.limited,
insertType,
syncLocalTimestampMillis
syncLocalTimestampMillis,
aggregator
)
roomEntity.addIfNecessary(chunkEntity)
}
Expand Down Expand Up @@ -337,7 +338,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
prevToken: String? = null,
isLimited: Boolean = true,
insertType: EventInsertType,
syncLocalTimestampMillis: Long): ChunkEntity {
syncLocalTimestampMillis: Long,
aggregator: SyncResponsePostTreatmentAggregator): ChunkEntity {
val lastChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomEntity.roomId)
val chunkEntity = if (!isLimited && lastChunk != null) {
lastChunk
Expand Down Expand Up @@ -371,7 +373,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
if (event.type == EventType.STATE_ROOM_MEMBER) {
val fixedContent = event.getFixedRoomMemberContent()
roomMemberContentsByUser[event.stateKey] = fixedContent
roomMemberEventHandler.handle(realm, roomEntity.roomId, event.stateKey, fixedContent)
roomMemberEventHandler.handle(realm, roomEntity.roomId, event.stateKey, fixedContent, aggregator)
}
}
roomMemberContentsByUser.getOrPut(event.senderId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ package org.matrix.android.sdk.internal.session.sync
internal class SyncResponsePostTreatmentAggregator {
// List of RoomId
val ephemeralFilesToDelete = mutableListOf<String>()
// Map of roomId to directUserId
val directChatsToCheck = mutableMapOf<String, String>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,54 @@

package org.matrix.android.sdk.internal.session.sync

import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.internal.session.sync.model.accountdata.toMutable
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
import javax.inject.Inject

internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor(
private val ephemeralTemporaryStore: RoomSyncEphemeralTemporaryStore
private val directChatsHelper: DirectChatsHelper,
private val ephemeralTemporaryStore: RoomSyncEphemeralTemporaryStore,
private val updateUserAccountDataTask: UpdateUserAccountDataTask
) {
fun handle(synResHaResponsePostTreatmentAggregator: SyncResponsePostTreatmentAggregator) {
suspend fun handle(synResHaResponsePostTreatmentAggregator: SyncResponsePostTreatmentAggregator) {
cleanupEphemeralFiles(synResHaResponsePostTreatmentAggregator.ephemeralFilesToDelete)
updateDirectUserIds(synResHaResponsePostTreatmentAggregator.directChatsToCheck)
}

private fun cleanupEphemeralFiles(ephemeralFilesToDelete: List<String>) {
ephemeralFilesToDelete.forEach {
ephemeralTemporaryStore.delete(it)
}
}

private suspend fun updateDirectUserIds(directUserIdsToUpdate: Map<String, String>) {
val directChats = directChatsHelper.getLocalDirectMessages().toMutable()
var hasUpdate = false
directUserIdsToUpdate.forEach { (roomId, candidateUserId) ->
// consider room is a DM if referenced in the DM dictionary
val currentDirectUserId = directChats.firstNotNullOfOrNull { (userId, roomIds) -> userId.takeIf { roomId in roomIds } }
// update directUserId with the given candidateUserId if it mismatches the current one
if (currentDirectUserId != null && !MatrixPatterns.isUserId(currentDirectUserId)) {
// link roomId with the matrix id
directChats
.getOrPut(candidateUserId) { arrayListOf() }
.apply {
if (!contains(roomId)) {
hasUpdate = true
add(roomId)
}
}

// remove roomId from currentDirectUserId entry
hasUpdate = hasUpdate or(directChats[currentDirectUserId]?.remove(roomId) == true)
// remove currentDirectUserId entry if there is no attached room anymore
hasUpdate = hasUpdate or(directChats.takeIf { it[currentDirectUserId].isNullOrEmpty() }?.remove(currentDirectUserId) != null)
}
}
if (hasUpdate) {
updateUserAccountDataTask.execute(UpdateUserAccountDataTask.DirectChatParams(directMessages = directChats))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import org.matrix.android.sdk.internal.session.sync.model.accountdata.Breadcrumb
import org.matrix.android.sdk.internal.session.sync.model.accountdata.DirectMessagesContent
import org.matrix.android.sdk.internal.session.sync.model.accountdata.IgnoredUsersContent
import org.matrix.android.sdk.internal.session.sync.model.accountdata.UserAccountDataSync
import org.matrix.android.sdk.internal.session.sync.model.accountdata.toMutable
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
import timber.log.Timber
Expand Down Expand Up @@ -83,7 +84,7 @@ internal class UserAccountDataSyncHandler @Inject constructor(
// If we get some direct chat invites, we synchronize the user account data including those.
suspend fun synchronizeWithServerIfNeeded(invites: Map<String, InvitedRoomSync>) {
if (invites.isNullOrEmpty()) return
val directChats = directChatsHelper.getLocalUserAccount()
val directChats = directChatsHelper.getLocalDirectMessages().toMutable()
var hasUpdate = false
monarchy.doWithRealm { realm ->
invites.forEach { (roomId, _) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ package org.matrix.android.sdk.internal.session.sync.model.accountdata
* Keys are userIds, values are list of roomIds
*/
internal typealias DirectMessagesContent = Map<String, List<String>>

/**
* Returns a new [MutableMap] with all elements of this collection.
*/
internal fun DirectMessagesContent.toMutable(): MutableMap<String, MutableList<String>> {
return map { it.key to it.value.toMutableList() }
.toMap()
.toMutableMap()
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.matrix.android.sdk.internal.database.query.getDirectRooms
import org.matrix.android.sdk.internal.di.SessionDatabase
import io.realm.Realm
import io.realm.RealmConfiguration
import org.matrix.android.sdk.internal.session.sync.model.accountdata.DirectMessagesContent
import javax.inject.Inject

internal class DirectChatsHelper @Inject constructor(@SessionDatabase
Expand All @@ -29,7 +30,7 @@ internal class DirectChatsHelper @Inject constructor(@SessionDatabase
/**
* @return a map of userId <-> list of roomId
*/
fun getLocalUserAccount(filterRoomId: String? = null): MutableMap<String, MutableList<String>> {
fun getLocalDirectMessages(filterRoomId: String? = null): DirectMessagesContent {
return Realm.getInstance(realmConfiguration).use { realm ->
// Makes sure we have the latest realm updates, this is important as we sent this information to the server.
realm.refresh()
Expand Down

0 comments on commit 4a33fbb

Please sign in to comment.