From c3c88c387bcf7c416a43a89b024c49fae79d9a3f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 31 Jan 2020 19:54:04 +0100 Subject: [PATCH] Improve Rx chain and cleanup --- .../main/java/im/vector/matrix/rx/RxRoom.kt | 54 ++++++++++++------- .../java/im/vector/matrix/rx/RxSession.kt | 20 +++---- .../api/session/crypto/CryptoService.kt | 5 +- .../crosssigning/CrossSigningService.kt | 3 +- .../internal/crypto/DefaultCryptoService.kt | 9 +++- .../DefaultCrossSigningService.kt | 24 ++++++--- .../internal/crypto/store/IMXCryptoStore.kt | 3 ++ .../crypto/store/db/RealmCryptoStore.kt | 16 ++++++ 8 files changed, 93 insertions(+), 41 deletions(-) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index 8ca19c5f5c..9cf382cfd2 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -17,7 +17,6 @@ package im.vector.matrix.rx import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel -import im.vector.matrix.android.api.extensions.orFalse import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.Room @@ -31,7 +30,6 @@ import im.vector.matrix.android.api.session.room.send.UserDraft import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.api.util.toOptional -import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import io.reactivex.Observable import io.reactivex.Single import io.reactivex.functions.BiFunction @@ -39,32 +37,50 @@ import io.reactivex.functions.BiFunction class RxRoom(private val room: Room, private val session: Session) { fun liveRoomSummary(): Observable> { - val summaryObservable = room.getRoomSummaryLive().asObservable() + val summaryObservable = room.getRoomSummaryLive() + .asObservable() .startWith(room.roomSummary().toOptional()) - val memberChangeObserver = summaryObservable.map { - it.getOrNull()?.otherMemberIds ?: emptyList() - }.distinctUntilChanged() - - val keyObservable = session.getLiveCryptoDeviceInfo().asObservable() - - val subObserver = Observable - .combineLatest, List, RoomEncryptionTrustLevel>( - memberChangeObserver, - keyObservable, - BiFunction { userList, _ -> - session.getCrossSigningService().getTrustLevelForUsers(userList) + val memberIdsChangeObservable = summaryObservable + .map { + it.getOrNull()?.let { roomSummary -> + if (roomSummary.isEncrypted) { + // Return the list of other users + roomSummary.otherMemberIds + } else { + // Return an empty list, the room is not encrypted + emptyList() } - ) + }.orEmpty() + }.distinctUntilChanged() + // Observe the device info of the users in the room + val cryptoDeviceInfoObservable = memberIdsChangeObservable + .switchMap { otherUserIds -> + session.getLiveCryptoDeviceInfo(otherUserIds) + .asObservable() + .map { + // If any key change, emit the userIds list + otherUserIds + } + } + + val roomEncryptionTrustLevelObservable = cryptoDeviceInfoObservable + .map { otherUserIds -> + if (otherUserIds.isEmpty()) { + Optional(null) + } else { + session.getCrossSigningService().getTrustLevelForUsers(otherUserIds).toOptional() + } + } return Observable - .combineLatest, RoomEncryptionTrustLevel, Optional>( + .combineLatest, Optional, Optional>( summaryObservable, - subObserver, + roomEncryptionTrustLevelObservable, BiFunction { summary, level -> summary.getOrNull()?.copy( - roomEncryptionTrustLevel = if (summary.getOrNull()?.isEncrypted.orFalse()) level else null + roomEncryptionTrustLevel = level.getOrNull() ).toOptional() } ) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 11083ca35e..f9021dde45 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -38,22 +38,24 @@ import io.reactivex.functions.BiFunction class RxSession(private val session: Session) { fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable> { - val summaryObservable = session.getRoomSummariesLive(queryParams).asObservable() + val summariesObservable = session.getRoomSummariesLive(queryParams).asObservable() .startWith(session.getRoomSummaries(queryParams)) - val keyObservable = session.getLiveCryptoDeviceInfo().asObservable() + val cryptoDeviceInfoObservable = session.getLiveCryptoDeviceInfo().asObservable() return Observable .combineLatest, List, List>( - summaryObservable, - keyObservable, + summariesObservable, + cryptoDeviceInfoObservable, BiFunction { summaries, _ -> summaries.map { - if (it.isEncrypted) it.copy( - roomEncryptionTrustLevel = session.getCrossSigningService().getTrustLevelForUsers( - it.otherMemberIds - ) - ) else it + if (it.isEncrypted) { + it.copy( + roomEncryptionTrustLevel = session.getCrossSigningService().getTrustLevelForUsers(it.otherMemberIds) + ) + } else { + it + } } } ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt index 799fcdcd7b..46539d9029 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/CryptoService.kt @@ -120,9 +120,12 @@ interface CryptoService { fun getCryptoDeviceInfo(userId: String): List - fun getLiveCryptoDeviceInfo(userId: String): LiveData> fun getLiveCryptoDeviceInfo(): LiveData> + fun getLiveCryptoDeviceInfo(userId: String): LiveData> + + fun getLiveCryptoDeviceInfo(userIds: List): LiveData> + fun addNewSessionListener(newSessionListener: NewSessionListener) fun removeSessionListener(listener: NewSessionListener) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt index 8d65b9e55a..a9d7a9e241 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/crypto/crosssigning/CrossSigningService.kt @@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.crypto.crosssigning import androidx.lifecycle.LiveData import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel -import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustResult import im.vector.matrix.android.internal.crypto.crosssigning.UserTrustResult @@ -65,5 +64,5 @@ interface CrossSigningService { otherDeviceId: String, locallyTrusted: Boolean?): DeviceTrustResult - fun getTrustLevelForUsers(userList: List): RoomEncryptionTrustLevel + fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt index 3099c2c417..7c4cc7460f 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt @@ -403,11 +403,16 @@ internal class DefaultCryptoService @Inject constructor( return cryptoStore.getUserDevices(userId)?.map { it.value } ?: emptyList() } + override fun getLiveCryptoDeviceInfo(): LiveData> { + return cryptoStore.getLiveDeviceList() + } + override fun getLiveCryptoDeviceInfo(userId: String): LiveData> { return cryptoStore.getLiveDeviceList(userId) } - override fun getLiveCryptoDeviceInfo(): LiveData> { - return cryptoStore.getLiveDeviceList() + + override fun getLiveCryptoDeviceInfo(userIds: List): LiveData> { + return cryptoStore.getLiveDeviceList(userIds) } /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt index 26c222f302..d01ebb7ea4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -658,25 +658,33 @@ internal class DefaultCrossSigningService @Inject constructor( } } - override fun getTrustLevelForUsers(userList: List): RoomEncryptionTrustLevel { - val atLeastOneTrusted = userList + override fun getTrustLevelForUsers(userIds: List): RoomEncryptionTrustLevel { + val atLeastOneTrusted = userIds .filter { it != userId } .map { getUserCrossSigningKeys(it) } .any { it?.isTrusted() == true } - if (!atLeastOneTrusted) { - return RoomEncryptionTrustLevel.Default + return if (!atLeastOneTrusted) { + RoomEncryptionTrustLevel.Default } else { // I have verified at least one other user - val allDevices = userList.mapNotNull { + val allDevices = userIds.mapNotNull { cryptoStore.getUserDeviceList(it) }.flatten() if (getMyCrossSigningKeys() != null) { val hasWarning = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() } - return if (hasWarning) RoomEncryptionTrustLevel.Warning else RoomEncryptionTrustLevel.Trusted + if (hasWarning) { + RoomEncryptionTrustLevel.Warning + } else { + RoomEncryptionTrustLevel.Trusted + } } else { - val hasWarningLegacy = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() } - return if (hasWarningLegacy) RoomEncryptionTrustLevel.Warning else RoomEncryptionTrustLevel.Trusted + val hasWarningLegacy = allDevices.any { !it.isVerified } + if (hasWarningLegacy) { + RoomEncryptionTrustLevel.Warning + } else { + RoomEncryptionTrustLevel.Trusted + } } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt index dfefc3b749..59abeb5465 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt @@ -200,6 +200,9 @@ internal interface IMXCryptoStore { fun getUserDeviceList(userId: String): List? fun getLiveDeviceList(userId: String): LiveData> + + fun getLiveDeviceList(userIds: List): LiveData> + //TODO temp fun getLiveDeviceList(): LiveData> /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt index 767a945272..51adc46900 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt @@ -398,6 +398,22 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati } } + override fun getLiveDeviceList(userIds: List): LiveData> { + val liveData = monarchy.findAllMappedWithChanges( + { realm: Realm -> + realm + .where() + .`in`(UserEntityFields.USER_ID, userIds.toTypedArray()) + }, + { entity -> + entity.devices.map { CryptoMapper.mapToModel(it) } + } + ) + return Transformations.map(liveData) { + it.firstOrNull() ?: emptyList() + } + } + override fun getLiveDeviceList(): LiveData> { val liveData = monarchy.findAllMappedWithChanges( { realm: Realm ->