mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-16 20:10:04 +03:00
Replace usage of new UnableToDecryptEventEntity by usage of existing EventInsertEntity
This commit is contained in:
parent
fd58875c31
commit
8b051c5b86
21 changed files with 252 additions and 603 deletions
|
@ -62,9 +62,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
|
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
|
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
|
import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.CreateUnableToDecryptEventEntityTask
|
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice
|
import org.matrix.android.sdk.internal.crypto.tasks.DefaultClaimOneTimeKeysForUsersDevice
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.DefaultCreateUnableToDecryptEventEntityTask
|
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.DefaultDeleteDeviceTask
|
import org.matrix.android.sdk.internal.crypto.tasks.DefaultDeleteDeviceTask
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.DefaultDownloadKeysForUsers
|
import org.matrix.android.sdk.internal.crypto.tasks.DefaultDownloadKeysForUsers
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.DefaultEncryptEventTask
|
import org.matrix.android.sdk.internal.crypto.tasks.DefaultEncryptEventTask
|
||||||
|
@ -255,7 +253,4 @@ internal abstract class CryptoModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindSendEventTask(task: DefaultSendEventTask): SendEventTask
|
abstract fun bindSendEventTask(task: DefaultSendEventTask): SendEventTask
|
||||||
|
|
||||||
@Binds
|
|
||||||
abstract fun bindCreateUnableToDecryptEventEntityTask(task: DefaultCreateUnableToDecryptEventEntityTask): CreateUnableToDecryptEventEntityTask
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||||
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
||||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.CreateUnableToDecryptEventEntityTask
|
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
||||||
import org.matrix.android.sdk.internal.extensions.foldToCallback
|
import org.matrix.android.sdk.internal.extensions.foldToCallback
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
|
@ -61,7 +60,6 @@ internal class EventDecryptor @Inject constructor(
|
||||||
private val deviceListManager: DeviceListManager,
|
private val deviceListManager: DeviceListManager,
|
||||||
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
|
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
|
||||||
private val cryptoStore: IMXCryptoStore,
|
private val cryptoStore: IMXCryptoStore,
|
||||||
private val createUnableToDecryptEventEntityTask: CreateUnableToDecryptEventEntityTask,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,7 +136,6 @@ internal class EventDecryptor @Inject constructor(
|
||||||
val eventContent = event.content
|
val eventContent = event.content
|
||||||
if (eventContent == null) {
|
if (eventContent == null) {
|
||||||
Timber.tag(loggerTag.value).e("decryptEvent : empty event content")
|
Timber.tag(loggerTag.value).e("decryptEvent : empty event content")
|
||||||
createUnableToDecryptEventEntity(event.eventId)
|
|
||||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)
|
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)
|
||||||
} else if (event.isRedacted()) {
|
} else if (event.isRedacted()) {
|
||||||
// we shouldn't attempt to decrypt a redacted event because the content is cleared and decryption will fail because of null algorithm
|
// we shouldn't attempt to decrypt a redacted event because the content is cleared and decryption will fail because of null algorithm
|
||||||
|
@ -156,7 +153,6 @@ internal class EventDecryptor @Inject constructor(
|
||||||
if (alg == null) {
|
if (alg == null) {
|
||||||
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, algorithm)
|
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, algorithm)
|
||||||
Timber.tag(loggerTag.value).e("decryptEvent() : $reason")
|
Timber.tag(loggerTag.value).e("decryptEvent() : $reason")
|
||||||
createUnableToDecryptEventEntity(event.eventId)
|
|
||||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, reason)
|
throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, reason)
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
@ -175,20 +171,12 @@ internal class EventDecryptor @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
createUnableToDecryptEventEntity(event.eventId)
|
|
||||||
throw mxCryptoError
|
throw mxCryptoError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun createUnableToDecryptEventEntity(eventId: String?) {
|
|
||||||
eventId?.let {
|
|
||||||
val params = CreateUnableToDecryptEventEntityTask.Params(eventId = it)
|
|
||||||
createUnableToDecryptEventEntityTask.execute(params)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun markOlmSessionForUnwedging(senderId: String, senderKey: String) {
|
private suspend fun markOlmSessionForUnwedging(senderId: String, senderKey: String) {
|
||||||
wedgedMutex.withLock {
|
wedgedMutex.withLock {
|
||||||
val info = WedgedDeviceInfo(senderId, senderKey)
|
val info = WedgedDeviceInfo(senderId, senderKey)
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto.tasks
|
|
||||||
|
|
||||||
import io.realm.RealmConfiguration
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.db.doRealmTransactionAsync
|
|
||||||
import org.matrix.android.sdk.internal.database.model.UnableToDecryptEventEntity
|
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This task create a dedicated entity for UTD events so that it can be processed later.
|
|
||||||
*/
|
|
||||||
internal interface CreateUnableToDecryptEventEntityTask : Task<CreateUnableToDecryptEventEntityTask.Params, Unit> {
|
|
||||||
data class Params(
|
|
||||||
val eventId: String,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class DefaultCreateUnableToDecryptEventEntityTask @Inject constructor(
|
|
||||||
@SessionDatabase val realmConfiguration: RealmConfiguration,
|
|
||||||
) : CreateUnableToDecryptEventEntityTask {
|
|
||||||
|
|
||||||
override suspend fun execute(params: CreateUnableToDecryptEventEntityTask.Params) {
|
|
||||||
val utdEventEntity = UnableToDecryptEventEntity(eventId = params.eventId)
|
|
||||||
doRealmTransactionAsync(realmConfiguration) { realm ->
|
|
||||||
realm.insert(utdEventEntity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,6 +22,7 @@ import io.realm.RealmResults
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventInsertEntity
|
import org.matrix.android.sdk.internal.database.model.EventInsertEntity
|
||||||
|
@ -34,7 +35,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
internal class EventInsertLiveObserver @Inject constructor(
|
internal class EventInsertLiveObserver @Inject constructor(
|
||||||
@SessionDatabase realmConfiguration: RealmConfiguration,
|
@SessionDatabase realmConfiguration: RealmConfiguration,
|
||||||
private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>
|
private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>,
|
||||||
) :
|
) :
|
||||||
RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) {
|
RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) {
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ internal class EventInsertLiveObserver @Inject constructor(
|
||||||
return@withLock
|
return@withLock
|
||||||
}
|
}
|
||||||
val idsToDeleteAfterProcess = ArrayList<String>()
|
val idsToDeleteAfterProcess = ArrayList<String>()
|
||||||
|
val idsOfEncryptedEvents = ArrayList<String>()
|
||||||
val filteredEvents = ArrayList<EventInsertEntity>(results.size)
|
val filteredEvents = ArrayList<EventInsertEntity>(results.size)
|
||||||
Timber.v("EventInsertEntity updated with ${results.size} results in db")
|
Timber.v("EventInsertEntity updated with ${results.size} results in db")
|
||||||
results.forEach {
|
results.forEach {
|
||||||
|
@ -64,8 +66,12 @@ internal class EventInsertLiveObserver @Inject constructor(
|
||||||
}
|
}
|
||||||
filteredEvents.add(copiedEvent)
|
filteredEvents.add(copiedEvent)
|
||||||
}
|
}
|
||||||
|
if (it.eventType == EventType.ENCRYPTED) {
|
||||||
|
idsOfEncryptedEvents.add(it.eventId)
|
||||||
|
} else {
|
||||||
idsToDeleteAfterProcess.add(it.eventId)
|
idsToDeleteAfterProcess.add(it.eventId)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
awaitTransaction(realmConfiguration) { realm ->
|
awaitTransaction(realmConfiguration) { realm ->
|
||||||
Timber.v("##Transaction: There are ${filteredEvents.size} events to process ")
|
Timber.v("##Transaction: There are ${filteredEvents.size} events to process ")
|
||||||
filteredEvents.forEach { eventInsert ->
|
filteredEvents.forEach { eventInsert ->
|
||||||
|
@ -86,6 +92,12 @@ internal class EventInsertLiveObserver @Inject constructor(
|
||||||
.`in`(EventInsertEntityFields.EVENT_ID, idsToDeleteAfterProcess.toTypedArray())
|
.`in`(EventInsertEntityFields.EVENT_ID, idsToDeleteAfterProcess.toTypedArray())
|
||||||
.findAll()
|
.findAll()
|
||||||
.deleteAllFromRealm()
|
.deleteAllFromRealm()
|
||||||
|
|
||||||
|
// make the encrypted events not processable: they will be processed again after decryption
|
||||||
|
realm.where(EventInsertEntity::class.java)
|
||||||
|
.`in`(EventInsertEntityFields.EVENT_ID, idsOfEncryptedEvents.toTypedArray())
|
||||||
|
.findAll()
|
||||||
|
.forEach { it.canBeProcessed = false }
|
||||||
}
|
}
|
||||||
processors.forEach { it.onPostProcess() }
|
processors.forEach { it.onPostProcess() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.database
|
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
|
||||||
import io.realm.RealmConfiguration
|
|
||||||
import io.realm.RealmResults
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
|
||||||
import org.matrix.android.sdk.internal.database.model.UnableToDecryptEventEntity
|
|
||||||
import org.matrix.android.sdk.internal.database.model.UnableToDecryptEventEntityFields
|
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
|
||||||
import org.matrix.android.sdk.internal.session.UnableToDecryptEventLiveProcessor
|
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
internal class UnableToDecryptEventLiveObserver @Inject constructor(
|
|
||||||
@SessionDatabase realmConfiguration: RealmConfiguration,
|
|
||||||
private val processors: Set<@JvmSuppressWildcards UnableToDecryptEventLiveProcessor>
|
|
||||||
) :
|
|
||||||
RealmLiveEntityObserver<UnableToDecryptEventEntity>(realmConfiguration) {
|
|
||||||
|
|
||||||
private val lock = Mutex()
|
|
||||||
|
|
||||||
override val query = Monarchy.Query {
|
|
||||||
it.where(UnableToDecryptEventEntity::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onChange(results: RealmResults<UnableToDecryptEventEntity>) {
|
|
||||||
observerScope.launch {
|
|
||||||
lock.withLock {
|
|
||||||
if (!results.isLoaded || results.isEmpty()) {
|
|
||||||
return@withLock
|
|
||||||
}
|
|
||||||
val copiedEvents = ArrayList<UnableToDecryptEventEntity>(results.size)
|
|
||||||
Timber.v("UnableToDecryptEventEntity updated with ${results.size} results in db")
|
|
||||||
results.forEach {
|
|
||||||
// don't use copy from realm over there
|
|
||||||
val copiedEvent = UnableToDecryptEventEntity(eventId = it.eventId)
|
|
||||||
copiedEvents.add(copiedEvent)
|
|
||||||
}
|
|
||||||
awaitTransaction(realmConfiguration) { realm ->
|
|
||||||
Timber.v("##Transaction: There are ${copiedEvents.size} events to process ")
|
|
||||||
copiedEvents.forEach { utdEvent ->
|
|
||||||
val eventId = utdEvent.eventId
|
|
||||||
val event = EventEntity.where(realm, eventId).findFirst()
|
|
||||||
if (event == null) {
|
|
||||||
Timber.v("Event $eventId not found")
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
val domainEvent = event.asDomain()
|
|
||||||
processors.forEach {
|
|
||||||
it.process(realm, domainEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.where(UnableToDecryptEventEntity::class.java)
|
|
||||||
.`in`(UnableToDecryptEventEntityFields.EVENT_ID, copiedEvents.map { it.eventId }.toTypedArray())
|
|
||||||
.findAll()
|
|
||||||
.deleteAllFromRealm()
|
|
||||||
}
|
|
||||||
processors.forEach { it.onPostProcess() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,21 +18,15 @@ package org.matrix.android.sdk.internal.database.migration
|
||||||
|
|
||||||
import io.realm.DynamicRealm
|
import io.realm.DynamicRealm
|
||||||
import org.matrix.android.sdk.internal.database.model.PollResponseAggregatedSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.PollResponseAggregatedSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.model.UnableToDecryptEventEntityFields
|
|
||||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adding a new field in poll summary to keep track of non decrypted related events.
|
* Adding a new field in poll summary to keep track of non decrypted related events.
|
||||||
* Adding a new entity UnableToDecryptEventEntity.
|
|
||||||
*/
|
*/
|
||||||
internal class MigrateSessionTo048(realm: DynamicRealm) : RealmMigrator(realm, 47) {
|
internal class MigrateSessionTo048(realm: DynamicRealm) : RealmMigrator(realm, 48) {
|
||||||
|
|
||||||
override fun doMigrate(realm: DynamicRealm) {
|
override fun doMigrate(realm: DynamicRealm) {
|
||||||
realm.schema.get("PollResponseAggregatedSummaryEntity")
|
realm.schema.get("PollResponseAggregatedSummaryEntity")
|
||||||
?.addRealmListField(PollResponseAggregatedSummaryEntityFields.ENCRYPTED_RELATED_EVENT_IDS.`$`, String::class.java)
|
?.addRealmListField(PollResponseAggregatedSummaryEntityFields.ENCRYPTED_RELATED_EVENT_IDS.`$`, String::class.java)
|
||||||
|
|
||||||
realm.schema.create("UnableToDecryptEventEntity")
|
|
||||||
?.addField(UnableToDecryptEventEntityFields.EVENT_ID, String::class.java)
|
|
||||||
?.setRequired(UnableToDecryptEventEntityFields.EVENT_ID, true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ internal open class EventInsertEntity(
|
||||||
var eventType: String = "",
|
var eventType: String = "",
|
||||||
/**
|
/**
|
||||||
* This flag will be used to filter EventInsertEntity in EventInsertLiveObserver.
|
* This flag will be used to filter EventInsertEntity in EventInsertLiveObserver.
|
||||||
* Currently it's set to false when the event content is encrypted.
|
* Currently it's set to false after an event with encrypted content has been processed.
|
||||||
*/
|
*/
|
||||||
var canBeProcessed: Boolean = true
|
var canBeProcessed: Boolean = true
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
|
@ -73,7 +73,6 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit
|
||||||
UserPresenceEntity::class,
|
UserPresenceEntity::class,
|
||||||
ThreadSummaryEntity::class,
|
ThreadSummaryEntity::class,
|
||||||
ThreadListPageEntity::class,
|
ThreadListPageEntity::class,
|
||||||
UnableToDecryptEventEntity::class,
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
internal class SessionRealmModule
|
internal class SessionRealmModule
|
||||||
|
|
|
@ -20,7 +20,6 @@ import io.realm.Realm
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.model.EventInsertEntity
|
import org.matrix.android.sdk.internal.database.model.EventInsertEntity
|
||||||
|
@ -32,10 +31,9 @@ internal fun EventEntity.copyToRealmOrIgnore(realm: Realm, insertType: EventInse
|
||||||
.equalTo(EventEntityFields.ROOM_ID, roomId)
|
.equalTo(EventEntityFields.ROOM_ID, roomId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
return if (eventEntity == null) {
|
return if (eventEntity == null) {
|
||||||
val canBeProcessed = type != EventType.ENCRYPTED || decryptionResultJson != null
|
val insertEntity = EventInsertEntity(eventId = eventId, eventType = type, canBeProcessed = true)
|
||||||
val insertEntity = EventInsertEntity(eventId = eventId, eventType = type, canBeProcessed = canBeProcessed).apply {
|
insertEntity.insertType = insertType
|
||||||
this.insertType = insertType
|
|
||||||
}
|
|
||||||
realm.insert(insertEntity)
|
realm.insert(insertEntity)
|
||||||
// copy this event entity and return it
|
// copy this event entity and return it
|
||||||
realm.copyToRealm(this)
|
realm.copyToRealm(this)
|
||||||
|
|
|
@ -50,7 +50,6 @@ import org.matrix.android.sdk.internal.crypto.tasks.RedactEventTask
|
||||||
import org.matrix.android.sdk.internal.database.EventInsertLiveObserver
|
import org.matrix.android.sdk.internal.database.EventInsertLiveObserver
|
||||||
import org.matrix.android.sdk.internal.database.RealmSessionProvider
|
import org.matrix.android.sdk.internal.database.RealmSessionProvider
|
||||||
import org.matrix.android.sdk.internal.database.SessionRealmConfigurationFactory
|
import org.matrix.android.sdk.internal.database.SessionRealmConfigurationFactory
|
||||||
import org.matrix.android.sdk.internal.database.UnableToDecryptEventLiveObserver
|
|
||||||
import org.matrix.android.sdk.internal.di.Authenticated
|
import org.matrix.android.sdk.internal.di.Authenticated
|
||||||
import org.matrix.android.sdk.internal.di.CacheDirectory
|
import org.matrix.android.sdk.internal.di.CacheDirectory
|
||||||
import org.matrix.android.sdk.internal.di.DeviceId
|
import org.matrix.android.sdk.internal.di.DeviceId
|
||||||
|
@ -85,7 +84,6 @@ import org.matrix.android.sdk.internal.session.identity.DefaultIdentityService
|
||||||
import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManager
|
import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManager
|
||||||
import org.matrix.android.sdk.internal.session.openid.DefaultOpenIdService
|
import org.matrix.android.sdk.internal.session.openid.DefaultOpenIdService
|
||||||
import org.matrix.android.sdk.internal.session.permalinks.DefaultPermalinkService
|
import org.matrix.android.sdk.internal.session.permalinks.DefaultPermalinkService
|
||||||
import org.matrix.android.sdk.internal.session.room.EncryptedEventRelationsAggregationProcessor
|
|
||||||
import org.matrix.android.sdk.internal.session.room.EventRelationsAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.EventRelationsAggregationProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.DefaultPollAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.poll.DefaultPollAggregationProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
||||||
|
@ -348,10 +346,6 @@ internal abstract class SessionModule {
|
||||||
@IntoSet
|
@IntoSet
|
||||||
abstract fun bindEventInsertObserver(observer: EventInsertLiveObserver): SessionLifecycleObserver
|
abstract fun bindEventInsertObserver(observer: EventInsertLiveObserver): SessionLifecycleObserver
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoSet
|
|
||||||
abstract fun bindUnableToDecryptEventObserver(observer: UnableToDecryptEventLiveObserver): SessionLifecycleObserver
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
abstract fun bindIntegrationManager(manager: IntegrationManager): SessionLifecycleObserver
|
abstract fun bindIntegrationManager(manager: IntegrationManager): SessionLifecycleObserver
|
||||||
|
@ -411,8 +405,4 @@ internal abstract class SessionModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindPollAggregationProcessor(processor: DefaultPollAggregationProcessor): PollAggregationProcessor
|
abstract fun bindPollAggregationProcessor(processor: DefaultPollAggregationProcessor): PollAggregationProcessor
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoSet
|
|
||||||
abstract fun bindEncryptedEventRelationsAggregationProcessor(processor: EncryptedEventRelationsAggregationProcessor): UnableToDecryptEventLiveProcessor
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.session
|
|
||||||
|
|
||||||
import io.realm.Realm
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
|
||||||
|
|
||||||
internal interface UnableToDecryptEventLiveProcessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the given event.
|
|
||||||
* @param realm a realm instance
|
|
||||||
* @param event the event to be processed
|
|
||||||
* @return true if it has been processed, false if it was ignored.
|
|
||||||
*/
|
|
||||||
fun process(realm: Realm, event: Event): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after transaction.
|
|
||||||
* Maybe you prefer to process the events outside of the realm transaction.
|
|
||||||
*/
|
|
||||||
suspend fun onPostProcess() {
|
|
||||||
// Noop by default
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.room
|
|
||||||
|
|
||||||
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.events.model.LocalEcho
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
|
||||||
import org.matrix.android.sdk.internal.session.UnableToDecryptEventLiveProcessor
|
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.utd.EncryptedReferenceAggregationProcessor
|
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
internal class EncryptedEventRelationsAggregationProcessor @Inject constructor(
|
|
||||||
private val encryptedReferenceAggregationProcessor: EncryptedReferenceAggregationProcessor,
|
|
||||||
) : UnableToDecryptEventLiveProcessor {
|
|
||||||
|
|
||||||
override fun process(realm: Realm, event: Event): Boolean {
|
|
||||||
val roomId = event.roomId
|
|
||||||
return if (roomId == null) {
|
|
||||||
Timber.w("Event has no room id ${event.eventId}")
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
val isLocalEcho = LocalEcho.isLocalEchoId(event.eventId ?: "")
|
|
||||||
|
|
||||||
return when (event.getClearType()) {
|
|
||||||
EventType.ENCRYPTED -> {
|
|
||||||
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()
|
|
||||||
processEncryptedContent(
|
|
||||||
encryptedEventContent = encryptedEventContent,
|
|
||||||
realm = realm,
|
|
||||||
event = event,
|
|
||||||
roomId = roomId,
|
|
||||||
isLocalEcho = isLocalEcho,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processEncryptedContent(
|
|
||||||
encryptedEventContent: EncryptedEventContent?,
|
|
||||||
realm: Realm,
|
|
||||||
event: Event,
|
|
||||||
roomId: String,
|
|
||||||
isLocalEcho: Boolean,
|
|
||||||
): Boolean {
|
|
||||||
return when (encryptedEventContent?.relatesTo?.type) {
|
|
||||||
RelationType.REPLACE -> {
|
|
||||||
Timber.w("## UTD replace in room $roomId for event ${event.eventId}")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
RelationType.RESPONSE -> {
|
|
||||||
// can we / should we do we something for UTD response??
|
|
||||||
Timber.w("## UTD response in room $roomId related to ${encryptedEventContent.relatesTo.eventId}")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
RelationType.REFERENCE -> {
|
|
||||||
// can we / should we do we something for UTD reference??
|
|
||||||
Timber.w("## UTD reference in room $roomId related to ${encryptedEventContent.relatesTo.eventId}")
|
|
||||||
val result = encryptedReferenceAggregationProcessor.handle(
|
|
||||||
realm = realm,
|
|
||||||
event = event,
|
|
||||||
isLocalEcho = isLocalEcho,
|
|
||||||
relatedEventId = encryptedEventContent.relatesTo.eventId,
|
|
||||||
)
|
|
||||||
result
|
|
||||||
}
|
|
||||||
RelationType.ANNOTATION -> {
|
|
||||||
// can we / should we do we something for UTD annotation??
|
|
||||||
Timber.w("## UTD annotation in room $roomId related to ${encryptedEventContent.relatesTo.eventId}")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,6 +23,7 @@ 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.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
import org.matrix.android.sdk.api.session.events.model.RelationType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.getRelationContent
|
import org.matrix.android.sdk.api.session.events.model.getRelationContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
@ -60,6 +61,7 @@ import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
|
import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
||||||
|
import org.matrix.android.sdk.internal.session.room.aggregation.utd.EncryptedReferenceAggregationProcessor
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||||
import org.matrix.android.sdk.internal.util.time.Clock
|
import org.matrix.android.sdk.internal.util.time.Clock
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -72,6 +74,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
||||||
private val sessionManager: SessionManager,
|
private val sessionManager: SessionManager,
|
||||||
private val liveLocationAggregationProcessor: LiveLocationAggregationProcessor,
|
private val liveLocationAggregationProcessor: LiveLocationAggregationProcessor,
|
||||||
private val pollAggregationProcessor: PollAggregationProcessor,
|
private val pollAggregationProcessor: PollAggregationProcessor,
|
||||||
|
private val encryptedReferenceAggregationProcessor: EncryptedReferenceAggregationProcessor,
|
||||||
private val editValidator: EventEditValidator,
|
private val editValidator: EventEditValidator,
|
||||||
private val clock: Clock,
|
private val clock: Clock,
|
||||||
) : EventInsertLiveProcessor {
|
) : EventInsertLiveProcessor {
|
||||||
|
@ -139,6 +142,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
||||||
Timber.v("###REACTION in room $roomId , reaction eventID ${event.eventId}")
|
Timber.v("###REACTION in room $roomId , reaction eventID ${event.eventId}")
|
||||||
handleReaction(realm, event, roomId, isLocalEcho)
|
handleReaction(realm, event, roomId, isLocalEcho)
|
||||||
}
|
}
|
||||||
|
EventType.ENCRYPTED -> {
|
||||||
|
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()
|
||||||
|
processEncryptedContent(
|
||||||
|
encryptedEventContent = encryptedEventContent,
|
||||||
|
realm = realm,
|
||||||
|
event = event,
|
||||||
|
roomId = roomId,
|
||||||
|
isLocalEcho = isLocalEcho,
|
||||||
|
)
|
||||||
|
}
|
||||||
EventType.MESSAGE -> {
|
EventType.MESSAGE -> {
|
||||||
if (event.unsignedData?.relations?.annotations != null) {
|
if (event.unsignedData?.relations?.annotations != null) {
|
||||||
Timber.v("###REACTION Aggregation in room $roomId for event ${event.eventId}")
|
Timber.v("###REACTION Aggregation in room $roomId for event ${event.eventId}")
|
||||||
|
@ -223,6 +236,36 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun processEncryptedContent(
|
||||||
|
encryptedEventContent: EncryptedEventContent?,
|
||||||
|
realm: Realm,
|
||||||
|
event: Event,
|
||||||
|
roomId: String,
|
||||||
|
isLocalEcho: Boolean,
|
||||||
|
) {
|
||||||
|
when (encryptedEventContent?.relatesTo?.type) {
|
||||||
|
RelationType.REPLACE -> {
|
||||||
|
Timber.w("## UTD replace in room $roomId for event ${event.eventId}")
|
||||||
|
}
|
||||||
|
RelationType.RESPONSE -> {
|
||||||
|
Timber.w("## UTD response in room $roomId related to ${encryptedEventContent.relatesTo.eventId}")
|
||||||
|
}
|
||||||
|
RelationType.REFERENCE -> {
|
||||||
|
Timber.w("## UTD reference in room $roomId related to ${encryptedEventContent.relatesTo.eventId}")
|
||||||
|
encryptedReferenceAggregationProcessor.handle(
|
||||||
|
realm = realm,
|
||||||
|
event = event,
|
||||||
|
isLocalEcho = isLocalEcho,
|
||||||
|
relatedEventId = encryptedEventContent.relatesTo.eventId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
RelationType.ANNOTATION -> {
|
||||||
|
Timber.w("## UTD annotation in room $roomId related to ${encryptedEventContent.relatesTo.eventId}")
|
||||||
|
}
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// OPT OUT serer aggregation until API mature enough
|
// OPT OUT serer aggregation until API mature enough
|
||||||
private val SHOULD_HANDLE_SERVER_AGREGGATION = false // should be true to work with e2e
|
private val SHOULD_HANDLE_SERVER_AGREGGATION = false // should be true to work with e2e
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto.tasks
|
|
||||||
|
|
||||||
import io.mockk.unmockkAll
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.realm.RealmModel
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Test
|
|
||||||
import org.matrix.android.sdk.internal.database.model.UnableToDecryptEventEntity
|
|
||||||
import org.matrix.android.sdk.test.fakes.FakeRealm
|
|
||||||
import org.matrix.android.sdk.test.fakes.FakeRealmConfiguration
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
internal class DefaultCreateUnableToDecryptEventEntityTaskTest {
|
|
||||||
|
|
||||||
private val fakeRealmConfiguration = FakeRealmConfiguration()
|
|
||||||
|
|
||||||
private val defaultCreateUnableToDecryptEventEntityTask = DefaultCreateUnableToDecryptEventEntityTask(
|
|
||||||
realmConfiguration = fakeRealmConfiguration.instance,
|
|
||||||
)
|
|
||||||
|
|
||||||
@After
|
|
||||||
fun tearDown() {
|
|
||||||
unmockkAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given an event id when execute then insert entity into database`() = runTest {
|
|
||||||
// Given
|
|
||||||
val anEventId = "event-id"
|
|
||||||
val params = CreateUnableToDecryptEventEntityTask.Params(
|
|
||||||
eventId = anEventId,
|
|
||||||
)
|
|
||||||
val fakeRealm = FakeRealm()
|
|
||||||
fakeRealm.givenExecuteTransactionAsync()
|
|
||||||
fakeRealmConfiguration.givenGetRealmInstance(fakeRealm.instance)
|
|
||||||
|
|
||||||
// When
|
|
||||||
defaultCreateUnableToDecryptEventEntityTask.execute(params)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify {
|
|
||||||
fakeRealm.instance.insert(match<RealmModel> {
|
|
||||||
it is UnableToDecryptEventEntity && it.eventId == anEventId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,209 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.room
|
|
||||||
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import org.amshove.kluent.shouldBeEqualTo
|
|
||||||
import org.amshove.kluent.shouldBeFalse
|
|
||||||
import org.junit.Test
|
|
||||||
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.events.model.RelationType
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
|
||||||
import org.matrix.android.sdk.test.fakes.FakeRealm
|
|
||||||
import org.matrix.android.sdk.test.fakes.internal.session.room.aggregation.utd.FakeEncryptedReferenceAggregationProcessor
|
|
||||||
|
|
||||||
class EncryptedEventRelationsAggregationProcessorTest {
|
|
||||||
|
|
||||||
private val fakeEncryptedReferenceAggregationProcessor = FakeEncryptedReferenceAggregationProcessor()
|
|
||||||
private val fakeRealm = FakeRealm()
|
|
||||||
|
|
||||||
private val encryptedEventRelationsAggregationProcessor = EncryptedEventRelationsAggregationProcessor(
|
|
||||||
encryptedReferenceAggregationProcessor = fakeEncryptedReferenceAggregationProcessor.instance,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given no room Id when process then result is false`() {
|
|
||||||
// Given
|
|
||||||
val anEvent = givenAnEvent(
|
|
||||||
eventId = "event-id",
|
|
||||||
roomId = null,
|
|
||||||
eventType = EventType.ENCRYPTED,
|
|
||||||
)
|
|
||||||
|
|
||||||
// When
|
|
||||||
val result = encryptedEventRelationsAggregationProcessor.process(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
result.shouldBeFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given an encrypted reference event when process then reference is processed`() {
|
|
||||||
// Given
|
|
||||||
val anEvent = givenAnEvent(
|
|
||||||
eventId = "event-id",
|
|
||||||
roomId = "room-id",
|
|
||||||
eventType = EventType.ENCRYPTED,
|
|
||||||
)
|
|
||||||
val relatedEventId = "related-event-id"
|
|
||||||
val encryptedEventContent = givenEncryptedEventContent(
|
|
||||||
relationType = RelationType.REFERENCE,
|
|
||||||
relatedEventId = relatedEventId,
|
|
||||||
)
|
|
||||||
every { anEvent.content } returns encryptedEventContent.toContent()
|
|
||||||
val resultOfReferenceProcess = false
|
|
||||||
fakeEncryptedReferenceAggregationProcessor.givenHandleReturns(resultOfReferenceProcess)
|
|
||||||
|
|
||||||
// When
|
|
||||||
val result = encryptedEventRelationsAggregationProcessor.process(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
result shouldBeEqualTo resultOfReferenceProcess
|
|
||||||
fakeEncryptedReferenceAggregationProcessor.verifyHandle(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
isLocalEcho = false,
|
|
||||||
relatedEventId = relatedEventId,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given an encrypted replace event when process then result is false`() {
|
|
||||||
// Given
|
|
||||||
val anEvent = givenAnEvent(
|
|
||||||
eventId = "event-id",
|
|
||||||
roomId = "room-id",
|
|
||||||
eventType = EventType.ENCRYPTED,
|
|
||||||
)
|
|
||||||
val relatedEventId = "related-event-id"
|
|
||||||
val encryptedEventContent = givenEncryptedEventContent(
|
|
||||||
relationType = RelationType.REPLACE,
|
|
||||||
relatedEventId = relatedEventId,
|
|
||||||
)
|
|
||||||
every { anEvent.content } returns encryptedEventContent.toContent()
|
|
||||||
|
|
||||||
// When
|
|
||||||
val result = encryptedEventRelationsAggregationProcessor.process(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
result.shouldBeFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given an encrypted response event when process then result is false`() {
|
|
||||||
// Given
|
|
||||||
val anEvent = givenAnEvent(
|
|
||||||
eventId = "event-id",
|
|
||||||
roomId = "room-id",
|
|
||||||
eventType = EventType.ENCRYPTED,
|
|
||||||
)
|
|
||||||
val relatedEventId = "related-event-id"
|
|
||||||
val encryptedEventContent = givenEncryptedEventContent(
|
|
||||||
relationType = RelationType.RESPONSE,
|
|
||||||
relatedEventId = relatedEventId,
|
|
||||||
)
|
|
||||||
every { anEvent.content } returns encryptedEventContent.toContent()
|
|
||||||
|
|
||||||
// When
|
|
||||||
val result = encryptedEventRelationsAggregationProcessor.process(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
result.shouldBeFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given an encrypted annotation event when process then result is false`() {
|
|
||||||
// Given
|
|
||||||
val anEvent = givenAnEvent(
|
|
||||||
eventId = "event-id",
|
|
||||||
roomId = "room-id",
|
|
||||||
eventType = EventType.ENCRYPTED,
|
|
||||||
)
|
|
||||||
val relatedEventId = "related-event-id"
|
|
||||||
val encryptedEventContent = givenEncryptedEventContent(
|
|
||||||
relationType = RelationType.ANNOTATION,
|
|
||||||
relatedEventId = relatedEventId,
|
|
||||||
)
|
|
||||||
every { anEvent.content } returns encryptedEventContent.toContent()
|
|
||||||
|
|
||||||
// When
|
|
||||||
val result = encryptedEventRelationsAggregationProcessor.process(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
result.shouldBeFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given a non encrypted event when process then result is false`() {
|
|
||||||
// Given
|
|
||||||
val anEvent = givenAnEvent(
|
|
||||||
eventId = "event-id",
|
|
||||||
roomId = "room-id",
|
|
||||||
eventType = EventType.MESSAGE,
|
|
||||||
)
|
|
||||||
|
|
||||||
// When
|
|
||||||
val result = encryptedEventRelationsAggregationProcessor.process(
|
|
||||||
realm = fakeRealm.instance,
|
|
||||||
event = anEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Then
|
|
||||||
result.shouldBeFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun givenAnEvent(
|
|
||||||
eventId: String,
|
|
||||||
roomId: String?,
|
|
||||||
eventType: String,
|
|
||||||
): Event {
|
|
||||||
return mockk<Event>().also {
|
|
||||||
every { it.eventId } returns eventId
|
|
||||||
every { it.roomId } returns roomId
|
|
||||||
every { it.getClearType() } returns eventType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun givenEncryptedEventContent(relationType: String, relatedEventId: String): EncryptedEventContent {
|
|
||||||
val relationContent = RelationDefaultContent(
|
|
||||||
eventId = relatedEventId,
|
|
||||||
type = relationType,
|
|
||||||
)
|
|
||||||
return EncryptedEventContent(
|
|
||||||
relatesTo = relationContent,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.junit.Test
|
||||||
|
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.events.model.RelationType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
|
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity
|
||||||
|
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntityFields
|
||||||
|
import org.matrix.android.sdk.test.fakes.FakeClock
|
||||||
|
import org.matrix.android.sdk.test.fakes.FakeRealm
|
||||||
|
import org.matrix.android.sdk.test.fakes.FakeStateEventDataSource
|
||||||
|
import org.matrix.android.sdk.test.fakes.givenEqualTo
|
||||||
|
import org.matrix.android.sdk.test.fakes.givenFindFirst
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.FakeEventEditValidator
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.FakeLiveLocationAggregationProcessor
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.FakePollAggregationProcessor
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.FakeSessionManager
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.session.room.aggregation.utd.FakeEncryptedReferenceAggregationProcessor
|
||||||
|
|
||||||
|
private const val A_ROOM_ID = "room-id"
|
||||||
|
private const val AN_EVENT_ID = "event-id"
|
||||||
|
|
||||||
|
internal class EventRelationsAggregationProcessorTest {
|
||||||
|
|
||||||
|
private val fakeStateEventDataSource = FakeStateEventDataSource()
|
||||||
|
private val fakeSessionManager = FakeSessionManager()
|
||||||
|
private val fakeLiveLocationAggregationProcessor = FakeLiveLocationAggregationProcessor()
|
||||||
|
private val fakePollAggregationProcessor = FakePollAggregationProcessor()
|
||||||
|
private val fakeEncryptedReferenceAggregationProcessor = FakeEncryptedReferenceAggregationProcessor()
|
||||||
|
private val fakeEventEditValidator = FakeEventEditValidator()
|
||||||
|
private val fakeClock = FakeClock()
|
||||||
|
private val fakeRealm = FakeRealm()
|
||||||
|
|
||||||
|
private val encryptedEventRelationsAggregationProcessor = EventRelationsAggregationProcessor(
|
||||||
|
userId = "userId",
|
||||||
|
stateEventDataSource = fakeStateEventDataSource.instance,
|
||||||
|
sessionId = "sessionId",
|
||||||
|
sessionManager = fakeSessionManager.instance,
|
||||||
|
liveLocationAggregationProcessor = fakeLiveLocationAggregationProcessor.instance,
|
||||||
|
pollAggregationProcessor = fakePollAggregationProcessor.instance,
|
||||||
|
encryptedReferenceAggregationProcessor = fakeEncryptedReferenceAggregationProcessor.instance,
|
||||||
|
editValidator = fakeEventEditValidator.instance,
|
||||||
|
clock = fakeClock,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given an encrypted reference event when process then reference is processed`() {
|
||||||
|
// Given
|
||||||
|
val anEvent = givenAnEvent(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
eventType = EventType.ENCRYPTED,
|
||||||
|
)
|
||||||
|
val relatedEventId = "related-event-id"
|
||||||
|
val encryptedEventContent = givenEncryptedEventContent(
|
||||||
|
relationType = RelationType.REFERENCE,
|
||||||
|
relatedEventId = relatedEventId,
|
||||||
|
)
|
||||||
|
every { anEvent.content } returns encryptedEventContent.toContent()
|
||||||
|
val resultOfReferenceProcess = false
|
||||||
|
fakeEncryptedReferenceAggregationProcessor.givenHandleReturns(resultOfReferenceProcess)
|
||||||
|
givenEventAnnotationsSummary(roomId = A_ROOM_ID, eventId = AN_EVENT_ID, annotationsSummary = null)
|
||||||
|
|
||||||
|
// When
|
||||||
|
encryptedEventRelationsAggregationProcessor.process(
|
||||||
|
realm = fakeRealm.instance,
|
||||||
|
event = anEvent,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
fakeEncryptedReferenceAggregationProcessor.verifyHandle(
|
||||||
|
realm = fakeRealm.instance,
|
||||||
|
event = anEvent,
|
||||||
|
isLocalEcho = false,
|
||||||
|
relatedEventId = relatedEventId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenAnEvent(
|
||||||
|
eventId: String,
|
||||||
|
roomId: String?,
|
||||||
|
eventType: String,
|
||||||
|
): Event {
|
||||||
|
return mockk<Event>().also {
|
||||||
|
every { it.eventId } returns eventId
|
||||||
|
every { it.roomId } returns roomId
|
||||||
|
every { it.getClearType() } returns eventType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenEncryptedEventContent(relationType: String, relatedEventId: String): EncryptedEventContent {
|
||||||
|
val relationContent = RelationDefaultContent(
|
||||||
|
eventId = relatedEventId,
|
||||||
|
type = relationType,
|
||||||
|
)
|
||||||
|
return EncryptedEventContent(
|
||||||
|
relatesTo = relationContent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenEventAnnotationsSummary(
|
||||||
|
roomId: String,
|
||||||
|
eventId: String,
|
||||||
|
annotationsSummary: EventAnnotationsSummaryEntity?
|
||||||
|
) {
|
||||||
|
fakeRealm.givenWhere<EventAnnotationsSummaryEntity>()
|
||||||
|
.givenEqualTo(EventAnnotationsSummaryEntityFields.ROOM_ID, roomId)
|
||||||
|
.givenEqualTo(EventAnnotationsSummaryEntityFields.EVENT_ID, eventId)
|
||||||
|
.givenFindFirst(annotationsSummary)
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,6 @@ import io.mockk.mockk
|
||||||
import io.mockk.runs
|
import io.mockk.runs
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.Realm.Transaction
|
|
||||||
import io.realm.RealmModel
|
import io.realm.RealmModel
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
|
@ -43,13 +42,6 @@ internal class FakeRealm {
|
||||||
inline fun <reified T : RealmModel> verifyInsertOrUpdate(crossinline verification: MockKVerificationScope.() -> T) {
|
inline fun <reified T : RealmModel> verifyInsertOrUpdate(crossinline verification: MockKVerificationScope.() -> T) {
|
||||||
verify { instance.insertOrUpdate(verification()) }
|
verify { instance.insertOrUpdate(verification()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun givenExecuteTransactionAsync() {
|
|
||||||
every { instance.executeTransactionAsync(any()) } answers {
|
|
||||||
firstArg<Transaction>().execute(instance)
|
|
||||||
mockk()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : RealmModel> RealmQuery<T>.givenFindFirst(
|
inline fun <reified T : RealmModel> RealmQuery<T>.givenFindFirst(
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.matrix.android.sdk.test.fakes
|
package org.matrix.android.sdk.test.fakes
|
||||||
|
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
@ -37,9 +36,4 @@ internal class FakeRealmConfiguration {
|
||||||
secondArg<(Realm) -> T>().invoke(realm)
|
secondArg<(Realm) -> T>().invoke(realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun givenGetRealmInstance(realm: Realm) {
|
|
||||||
mockkStatic(Realm::class)
|
|
||||||
every { Realm.getInstance(instance) } returns realm
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,14 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.database.model
|
package org.matrix.android.sdk.test.fakes.internal
|
||||||
|
|
||||||
import io.realm.RealmObject
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.internal.session.room.EventEditValidator
|
||||||
|
|
||||||
/**
|
internal class FakeEventEditValidator {
|
||||||
* This class is used to get notification on new UTD events. Since these events cannot be processed
|
|
||||||
* in EventInsertEntity, we should introduce a dedicated entity for that.
|
val instance: EventEditValidator = mockk()
|
||||||
*/
|
}
|
||||||
internal open class UnableToDecryptEventEntity(
|
|
||||||
var eventId: String = "",
|
|
||||||
) : RealmObject()
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.test.fakes.internal
|
||||||
|
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
|
||||||
|
|
||||||
|
internal class FakeLiveLocationAggregationProcessor {
|
||||||
|
|
||||||
|
val instance: LiveLocationAggregationProcessor = mockk()
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.test.fakes.internal
|
||||||
|
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
||||||
|
|
||||||
|
internal class FakePollAggregationProcessor {
|
||||||
|
|
||||||
|
val instance: PollAggregationProcessor = mockk()
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue