Improve Rx chain and cleanup
This commit is contained in:
parent
51e0f945a7
commit
c3c88c387b
@ -17,7 +17,6 @@
|
|||||||
package im.vector.matrix.rx
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel
|
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.Session
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.Room
|
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.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.api.util.Optional
|
import im.vector.matrix.android.api.util.Optional
|
||||||
import im.vector.matrix.android.api.util.toOptional
|
import im.vector.matrix.android.api.util.toOptional
|
||||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.functions.BiFunction
|
import io.reactivex.functions.BiFunction
|
||||||
@ -39,32 +37,50 @@ import io.reactivex.functions.BiFunction
|
|||||||
class RxRoom(private val room: Room, private val session: Session) {
|
class RxRoom(private val room: Room, private val session: Session) {
|
||||||
|
|
||||||
fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
|
fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
|
||||||
val summaryObservable = room.getRoomSummaryLive().asObservable()
|
val summaryObservable = room.getRoomSummaryLive()
|
||||||
|
.asObservable()
|
||||||
.startWith(room.roomSummary().toOptional())
|
.startWith(room.roomSummary().toOptional())
|
||||||
|
|
||||||
val memberChangeObserver = summaryObservable.map {
|
val memberIdsChangeObservable = summaryObservable
|
||||||
it.getOrNull()?.otherMemberIds ?: emptyList()
|
.map {
|
||||||
}.distinctUntilChanged()
|
it.getOrNull()?.let { roomSummary ->
|
||||||
|
if (roomSummary.isEncrypted) {
|
||||||
val keyObservable = session.getLiveCryptoDeviceInfo().asObservable()
|
// Return the list of other users
|
||||||
|
roomSummary.otherMemberIds
|
||||||
val subObserver = Observable
|
} else {
|
||||||
.combineLatest<List<String>, List<CryptoDeviceInfo>, RoomEncryptionTrustLevel>(
|
// Return an empty list, the room is not encrypted
|
||||||
memberChangeObserver,
|
emptyList()
|
||||||
keyObservable,
|
|
||||||
BiFunction { userList, _ ->
|
|
||||||
session.getCrossSigningService().getTrustLevelForUsers(userList)
|
|
||||||
}
|
}
|
||||||
)
|
}.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<RoomEncryptionTrustLevel>(null)
|
||||||
|
} else {
|
||||||
|
session.getCrossSigningService().getTrustLevelForUsers(otherUserIds).toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Observable
|
return Observable
|
||||||
.combineLatest<Optional<RoomSummary>, RoomEncryptionTrustLevel, Optional<RoomSummary>>(
|
.combineLatest<Optional<RoomSummary>, Optional<RoomEncryptionTrustLevel>, Optional<RoomSummary>>(
|
||||||
summaryObservable,
|
summaryObservable,
|
||||||
subObserver,
|
roomEncryptionTrustLevelObservable,
|
||||||
BiFunction { summary, level ->
|
BiFunction { summary, level ->
|
||||||
summary.getOrNull()?.copy(
|
summary.getOrNull()?.copy(
|
||||||
roomEncryptionTrustLevel = if (summary.getOrNull()?.isEncrypted.orFalse()) level else null
|
roomEncryptionTrustLevel = level.getOrNull()
|
||||||
).toOptional()
|
).toOptional()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -38,22 +38,24 @@ import io.reactivex.functions.BiFunction
|
|||||||
class RxSession(private val session: Session) {
|
class RxSession(private val session: Session) {
|
||||||
|
|
||||||
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
|
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
|
||||||
val summaryObservable = session.getRoomSummariesLive(queryParams).asObservable()
|
val summariesObservable = session.getRoomSummariesLive(queryParams).asObservable()
|
||||||
.startWith(session.getRoomSummaries(queryParams))
|
.startWith(session.getRoomSummaries(queryParams))
|
||||||
|
|
||||||
val keyObservable = session.getLiveCryptoDeviceInfo().asObservable()
|
val cryptoDeviceInfoObservable = session.getLiveCryptoDeviceInfo().asObservable()
|
||||||
|
|
||||||
return Observable
|
return Observable
|
||||||
.combineLatest<List<RoomSummary>, List<CryptoDeviceInfo>, List<RoomSummary>>(
|
.combineLatest<List<RoomSummary>, List<CryptoDeviceInfo>, List<RoomSummary>>(
|
||||||
summaryObservable,
|
summariesObservable,
|
||||||
keyObservable,
|
cryptoDeviceInfoObservable,
|
||||||
BiFunction { summaries, _ ->
|
BiFunction { summaries, _ ->
|
||||||
summaries.map {
|
summaries.map {
|
||||||
if (it.isEncrypted) it.copy(
|
if (it.isEncrypted) {
|
||||||
roomEncryptionTrustLevel = session.getCrossSigningService().getTrustLevelForUsers(
|
it.copy(
|
||||||
it.otherMemberIds
|
roomEncryptionTrustLevel = session.getCrossSigningService().getTrustLevelForUsers(it.otherMemberIds)
|
||||||
)
|
)
|
||||||
) else it
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -120,9 +120,12 @@ interface CryptoService {
|
|||||||
|
|
||||||
fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo>
|
fun getCryptoDeviceInfo(userId: String): List<CryptoDeviceInfo>
|
||||||
|
|
||||||
fun getLiveCryptoDeviceInfo(userId: String): LiveData<List<CryptoDeviceInfo>>
|
|
||||||
fun getLiveCryptoDeviceInfo(): LiveData<List<CryptoDeviceInfo>>
|
fun getLiveCryptoDeviceInfo(): LiveData<List<CryptoDeviceInfo>>
|
||||||
|
|
||||||
|
fun getLiveCryptoDeviceInfo(userId: String): LiveData<List<CryptoDeviceInfo>>
|
||||||
|
|
||||||
|
fun getLiveCryptoDeviceInfo(userIds: List<String>): LiveData<List<CryptoDeviceInfo>>
|
||||||
|
|
||||||
fun addNewSessionListener(newSessionListener: NewSessionListener)
|
fun addNewSessionListener(newSessionListener: NewSessionListener)
|
||||||
|
|
||||||
fun removeSessionListener(listener: NewSessionListener)
|
fun removeSessionListener(listener: NewSessionListener)
|
||||||
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.crypto.crosssigning
|
|||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel
|
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.api.util.Optional
|
||||||
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustResult
|
import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustResult
|
||||||
import im.vector.matrix.android.internal.crypto.crosssigning.UserTrustResult
|
import im.vector.matrix.android.internal.crypto.crosssigning.UserTrustResult
|
||||||
@ -65,5 +64,5 @@ interface CrossSigningService {
|
|||||||
otherDeviceId: String,
|
otherDeviceId: String,
|
||||||
locallyTrusted: Boolean?): DeviceTrustResult
|
locallyTrusted: Boolean?): DeviceTrustResult
|
||||||
|
|
||||||
fun getTrustLevelForUsers(userList: List<String>): RoomEncryptionTrustLevel
|
fun getTrustLevelForUsers(userIds: List<String>): RoomEncryptionTrustLevel
|
||||||
}
|
}
|
||||||
|
@ -403,11 +403,16 @@ internal class DefaultCryptoService @Inject constructor(
|
|||||||
return cryptoStore.getUserDevices(userId)?.map { it.value } ?: emptyList()
|
return cryptoStore.getUserDevices(userId)?.map { it.value } ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLiveCryptoDeviceInfo(): LiveData<List<CryptoDeviceInfo>> {
|
||||||
|
return cryptoStore.getLiveDeviceList()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getLiveCryptoDeviceInfo(userId: String): LiveData<List<CryptoDeviceInfo>> {
|
override fun getLiveCryptoDeviceInfo(userId: String): LiveData<List<CryptoDeviceInfo>> {
|
||||||
return cryptoStore.getLiveDeviceList(userId)
|
return cryptoStore.getLiveDeviceList(userId)
|
||||||
}
|
}
|
||||||
override fun getLiveCryptoDeviceInfo(): LiveData<List<CryptoDeviceInfo>> {
|
|
||||||
return cryptoStore.getLiveDeviceList()
|
override fun getLiveCryptoDeviceInfo(userIds: List<String>): LiveData<List<CryptoDeviceInfo>> {
|
||||||
|
return cryptoStore.getLiveDeviceList(userIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -658,25 +658,33 @@ internal class DefaultCrossSigningService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTrustLevelForUsers(userList: List<String>): RoomEncryptionTrustLevel {
|
override fun getTrustLevelForUsers(userIds: List<String>): RoomEncryptionTrustLevel {
|
||||||
val atLeastOneTrusted = userList
|
val atLeastOneTrusted = userIds
|
||||||
.filter { it != userId }
|
.filter { it != userId }
|
||||||
.map { getUserCrossSigningKeys(it) }
|
.map { getUserCrossSigningKeys(it) }
|
||||||
.any { it?.isTrusted() == true }
|
.any { it?.isTrusted() == true }
|
||||||
|
|
||||||
if (!atLeastOneTrusted) {
|
return if (!atLeastOneTrusted) {
|
||||||
return RoomEncryptionTrustLevel.Default
|
RoomEncryptionTrustLevel.Default
|
||||||
} else {
|
} else {
|
||||||
// I have verified at least one other user
|
// I have verified at least one other user
|
||||||
val allDevices = userList.mapNotNull {
|
val allDevices = userIds.mapNotNull {
|
||||||
cryptoStore.getUserDeviceList(it)
|
cryptoStore.getUserDeviceList(it)
|
||||||
}.flatten()
|
}.flatten()
|
||||||
if (getMyCrossSigningKeys() != null) {
|
if (getMyCrossSigningKeys() != null) {
|
||||||
val hasWarning = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() }
|
val hasWarning = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() }
|
||||||
return if (hasWarning) RoomEncryptionTrustLevel.Warning else RoomEncryptionTrustLevel.Trusted
|
if (hasWarning) {
|
||||||
|
RoomEncryptionTrustLevel.Warning
|
||||||
|
} else {
|
||||||
|
RoomEncryptionTrustLevel.Trusted
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val hasWarningLegacy = allDevices.any { !it.trustLevel?.crossSigningVerified.orFalse() }
|
val hasWarningLegacy = allDevices.any { !it.isVerified }
|
||||||
return if (hasWarningLegacy) RoomEncryptionTrustLevel.Warning else RoomEncryptionTrustLevel.Trusted
|
if (hasWarningLegacy) {
|
||||||
|
RoomEncryptionTrustLevel.Warning
|
||||||
|
} else {
|
||||||
|
RoomEncryptionTrustLevel.Trusted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,6 +200,9 @@ internal interface IMXCryptoStore {
|
|||||||
fun getUserDeviceList(userId: String): List<CryptoDeviceInfo>?
|
fun getUserDeviceList(userId: String): List<CryptoDeviceInfo>?
|
||||||
|
|
||||||
fun getLiveDeviceList(userId: String): LiveData<List<CryptoDeviceInfo>>
|
fun getLiveDeviceList(userId: String): LiveData<List<CryptoDeviceInfo>>
|
||||||
|
|
||||||
|
fun getLiveDeviceList(userIds: List<String>): LiveData<List<CryptoDeviceInfo>>
|
||||||
|
|
||||||
//TODO temp
|
//TODO temp
|
||||||
fun getLiveDeviceList(): LiveData<List<CryptoDeviceInfo>>
|
fun getLiveDeviceList(): LiveData<List<CryptoDeviceInfo>>
|
||||||
/**
|
/**
|
||||||
|
@ -398,6 +398,22 @@ internal class RealmCryptoStore(private val realmConfiguration: RealmConfigurati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLiveDeviceList(userIds: List<String>): LiveData<List<CryptoDeviceInfo>> {
|
||||||
|
val liveData = monarchy.findAllMappedWithChanges(
|
||||||
|
{ realm: Realm ->
|
||||||
|
realm
|
||||||
|
.where<UserEntity>()
|
||||||
|
.`in`(UserEntityFields.USER_ID, userIds.toTypedArray())
|
||||||
|
},
|
||||||
|
{ entity ->
|
||||||
|
entity.devices.map { CryptoMapper.mapToModel(it) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return Transformations.map(liveData) {
|
||||||
|
it.firstOrNull() ?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getLiveDeviceList(): LiveData<List<CryptoDeviceInfo>> {
|
override fun getLiveDeviceList(): LiveData<List<CryptoDeviceInfo>> {
|
||||||
val liveData = monarchy.findAllMappedWithChanges(
|
val liveData = monarchy.findAllMappedWithChanges(
|
||||||
{ realm: Realm ->
|
{ realm: Realm ->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user