Better cleanup of the Crypto database.

This commit is contained in:
Benoit Marty 2024-08-27 10:23:41 +02:00 committed by Benoit Marty
parent 5908cd54f0
commit 15c86f3fe3
29 changed files with 54 additions and 1306 deletions

View file

@ -41,15 +41,11 @@ import org.matrix.android.sdk.internal.crypto.store.db.doRealmTransactionAsync
import org.matrix.android.sdk.internal.crypto.store.db.doWithRealm
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CryptoRoomInfoMapper
import org.matrix.android.sdk.internal.crypto.store.db.mapper.MyDeviceLastSeenInfoEntityMapper
import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.query.getById
import org.matrix.android.sdk.internal.crypto.store.db.query.getOrCreate
import org.matrix.android.sdk.internal.di.CryptoDatabase
@ -82,7 +78,6 @@ internal class RustCryptoStore @Inject constructor(
// still needed on rust due to the global crypto settings
init {
// Ensure CryptoMetadataEntity is inserted in DB
// TODO BMA
doRealmTransaction("init", realmConfiguration) { realm ->
var currentMetadata = realm.where<CryptoMetadataEntity>().findFirst()
@ -146,30 +141,7 @@ internal class RustCryptoStore @Inject constructor(
// nop
}
override fun tidyUpDataBase() {
// These entities are not used in rust actually, but as they are not yet cleaned up, this will do it with time
val prevWeekTs = clock.epochMillis() - 7 * 24 * 60 * 60 * 1_000
doRealmTransaction("tidyUpDataBase", realmConfiguration) { realm ->
// Clean the old ones?
realm.where<OutgoingKeyRequestEntity>()
.lessThan(OutgoingKeyRequestEntityFields.CREATION_TIME_STAMP, prevWeekTs)
.findAll()
.also { Timber.i("## Crypto Clean up ${it.size} OutgoingKeyRequestEntity") }
.deleteAllFromRealm()
// Only keep one month history
val prevMonthTs = clock.epochMillis() - 4 * 7 * 24 * 60 * 60 * 1_000L
realm.where<AuditTrailEntity>()
.lessThan(AuditTrailEntityFields.AGE_LOCAL_TS, prevMonthTs)
.findAll()
.also { Timber.i("## Crypto Clean up ${it.size} AuditTrailEntity") }
.deleteAllFromRealm()
// Can we do something for WithHeldSessionEntity?
}
}
override fun tidyUpDataBase() = Unit
override fun close() {
val tasks = monarchyWriteAsyncExecutor.shutdownNow()

View file

@ -1,31 +0,0 @@
/*
* 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.internal.crypto.store
import org.matrix.android.sdk.api.session.crypto.crosssigning.UserIdentity
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
internal data class UserDataToStore(
/**
* Map of userId -> (Map of deviceId -> [CryptoDeviceInfo]).
*/
val userDevices: MutableMap<String, Map<String, CryptoDeviceInfo>> = mutableMapOf(),
/**
* Map of userId -> [UserIdentity].
*/
val userIdentities: MutableMap<String, UserIdentity> = mutableMapOf(),
)

View file

@ -16,15 +16,9 @@
package org.matrix.android.sdk.internal.crypto.store.db
import android.util.Base64
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmObject
import timber.log.Timber
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import kotlin.system.measureTimeMillis
/**
@ -36,24 +30,6 @@ internal fun <T> doWithRealm(realmConfiguration: RealmConfiguration, action: (Re
}
}
/**
* Get realm, do the query, copy from realm, close realm, and return the copied result.
*/
internal fun <T : RealmObject> doRealmQueryAndCopy(realmConfiguration: RealmConfiguration, action: (Realm) -> T?): T? {
return Realm.getInstance(realmConfiguration).use { realm ->
action.invoke(realm)?.let { realm.copyFromRealm(it) }
}
}
/**
* Get realm, do the list query, copy from realm, close realm, and return the copied result.
*/
internal fun <T : RealmObject> doRealmQueryAndCopyList(realmConfiguration: RealmConfiguration, action: (Realm) -> Iterable<T>): Iterable<T> {
return Realm.getInstance(realmConfiguration).use { realm ->
action.invoke(realm).let { realm.copyFromRealm(it) }
}
}
/**
* Get realm instance, invoke the action in a transaction and close realm.
*/
@ -70,38 +46,3 @@ internal fun doRealmTransactionAsync(realmConfiguration: RealmConfiguration, act
realm.executeTransactionAsync { action.invoke(it) }
}
}
/**
* Serialize any Serializable object, zip it and convert to Base64 String.
*/
internal fun serializeForRealm(o: Any?): String? {
if (o == null) {
return null
}
val baos = ByteArrayOutputStream()
val gzis = GZIPOutputStream(baos)
val out = ObjectOutputStream(gzis)
out.use {
it.writeObject(o)
}
return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT)
}
/**
* Do the opposite of serializeForRealm.
*/
@Suppress("UNCHECKED_CAST")
internal fun <T> deserializeFromRealm(string: String?): T? {
if (string == null) {
return null
}
val decodedB64 = Base64.decode(string.toByteArray(), Base64.DEFAULT)
val bais = decodedB64.inputStream()
val gzis = GZIPInputStream(bais)
val ois = SafeObjectInputStream(gzis)
return ois.use {
it.readObject() as T
}
}

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.crypto.store.db
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo024
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
import javax.inject.Inject
@ -25,6 +26,7 @@ import javax.inject.Inject
* 0, 1, 2: legacy Riot-Android;
* 3: migrate to RiotX schema;
* 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6).
* 24: Delete nearly all the crypto DB
*/
internal class RealmCryptoStoreMigration @Inject constructor(
) : MatrixRealmMigration(
@ -39,8 +41,6 @@ internal class RealmCryptoStoreMigration @Inject constructor(
override fun hashCode() = 5000
override fun doMigrate(realm: DynamicRealm, oldVersion: Long) {
// Delete the whole DB
// TODO BMA
realm.deleteAll()
if (oldVersion < 24) MigrateCryptoTo024(realm).perform()
}
}

View file

@ -17,23 +17,9 @@
package org.matrix.android.sdk.internal.crypto.store.db
import io.realm.annotations.RealmModule
import org.matrix.android.sdk.internal.crypto.store.db.model.AuditTrailEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.KeyInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.KeyRequestReplyEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingKeyRequestEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity
/**
* Realm module for Crypto store classes.
@ -43,21 +29,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEnti
classes = [
CryptoMetadataEntity::class,
CryptoRoomEntity::class,
DeviceInfoEntity::class,
KeysBackupDataEntity::class,
OlmInboundGroupSessionEntity::class,
OlmSessionEntity::class,
UserEntity::class,
KeyInfoEntity::class,
CrossSigningInfoEntity::class,
TrustLevelEntity::class,
AuditTrailEntity::class,
OutgoingKeyRequestEntity::class,
KeyRequestReplyEntity::class,
MyDeviceLastSeenInfoEntity::class,
WithHeldSessionEntity::class,
SharedSessionEntity::class,
OutboundGroupSessionInfoEntity::class
]
)
internal class RealmCryptoStoreModule

View file

@ -1,44 +0,0 @@
/*
* Copyright 2020 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.store.db
import java.io.IOException
import java.io.InputStream
import java.io.ObjectInputStream
import java.io.ObjectStreamClass
/**
* Package has been renamed from `im.vector.matrix.android` to `org.matrix.android.sdk`
* so ensure deserialization of previously stored objects still works
*
* Ref: https://stackoverflow.com/questions/3884492/how-can-i-change-package-for-a-bunch-of-java-serializable-classes
*/
internal class SafeObjectInputStream(inputStream: InputStream) : ObjectInputStream(inputStream) {
init {
enableResolveObject(true)
}
@Throws(IOException::class, ClassNotFoundException::class)
override fun readClassDescriptor(): ObjectStreamClass {
val read = super.readClassDescriptor()
if (read.name.startsWith("im.vector.matrix.android.")) {
return ObjectStreamClass.lookup(Class.forName(read.name.replace("im.vector.matrix.android.", "org.matrix.android.sdk.")))
}
return read
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2024 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.store.db.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.util.database.RealmMigrator
internal class MigrateCryptoTo024(realm: DynamicRealm) : RealmMigrator(realm, 24) {
/**
* Delete the whole DB, except tables that are still used to store data:
* - CryptoMetadataEntity
* - MyDeviceLastSeenInfoEntity
* - CryptoRoomEntity (but remove unused member 'outboundSessionInfo: OutboundGroupSessionInfoEntity')
*/
override fun doMigrate(realm: DynamicRealm) {
with(realm.schema) {
get("CryptoRoomEntity")?.removeField("outboundSessionInfo")
// Warning: order is important, first remove classes that depends on others.
remove("UserEntity")
remove("DeviceInfoEntity")
remove("CrossSigningInfoEntity")
remove("KeyInfoEntity")
remove("TrustLevelEntity")
remove("KeysBackupDataEntity")
remove("OlmInboundGroupSessionEntity")
remove("OlmSessionEntity")
remove("AuditTrailEntity")
remove("OutgoingKeyRequestEntity")
remove("KeyRequestReplyEntity")
remove("WithHeldSessionEntity")
remove("SharedSessionEntity")
remove("OutboundGroupSessionInfoEntity")
}
}
}

View file

@ -1,28 +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.crypto.store.db.model
import io.realm.RealmObject
import io.realm.annotations.Index
internal open class AuditTrailEntity(
var ageLocalTs: Long? = null,
@Index var type: String? = null,
var contentJson: String? = null
) : RealmObject() {
companion object
}

View file

@ -1,82 +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.crypto.store.db.model
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.model.AuditTrail
import org.matrix.android.sdk.api.session.crypto.model.ForwardInfo
import org.matrix.android.sdk.api.session.crypto.model.IncomingKeyRequestInfo
import org.matrix.android.sdk.api.session.crypto.model.TrailType
import org.matrix.android.sdk.api.session.crypto.model.UnknownInfo
import org.matrix.android.sdk.api.session.crypto.model.WithheldInfo
import org.matrix.android.sdk.internal.di.MoshiProvider
internal object AuditTrailMapper {
fun map(entity: AuditTrailEntity): AuditTrail? {
val contentJson = entity.contentJson ?: return null
return when (entity.type) {
TrailType.OutgoingKeyForward.name -> {
val info = tryOrNull {
MoshiProvider.providesMoshi().adapter(ForwardInfo::class.java).fromJson(contentJson)
} ?: return null
AuditTrail(
ageLocalTs = entity.ageLocalTs ?: 0,
type = TrailType.OutgoingKeyForward,
info = info
)
}
TrailType.OutgoingKeyWithheld.name -> {
val info = tryOrNull {
MoshiProvider.providesMoshi().adapter(WithheldInfo::class.java).fromJson(contentJson)
} ?: return null
AuditTrail(
ageLocalTs = entity.ageLocalTs ?: 0,
type = TrailType.OutgoingKeyWithheld,
info = info
)
}
TrailType.IncomingKeyRequest.name -> {
val info = tryOrNull {
MoshiProvider.providesMoshi().adapter(IncomingKeyRequestInfo::class.java).fromJson(contentJson)
} ?: return null
AuditTrail(
ageLocalTs = entity.ageLocalTs ?: 0,
type = TrailType.IncomingKeyRequest,
info = info
)
}
TrailType.IncomingKeyForward.name -> {
val info = tryOrNull {
MoshiProvider.providesMoshi().adapter(ForwardInfo::class.java).fromJson(contentJson)
} ?: return null
AuditTrail(
ageLocalTs = entity.ageLocalTs ?: 0,
type = TrailType.IncomingKeyForward,
info = info
)
}
else -> {
AuditTrail(
ageLocalTs = entity.ageLocalTs ?: 0,
type = TrailType.Unknown,
info = UnknownInfo
)
}
}
}
}

View file

@ -1,65 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import org.matrix.android.sdk.api.session.crypto.crosssigning.KeyUsage
import org.matrix.android.sdk.internal.extensions.clearWith
internal open class CrossSigningInfoEntity(
@PrimaryKey
var userId: String? = null,
var wasUserVerifiedOnce: Boolean = false,
var crossSigningKeys: RealmList<KeyInfoEntity> = RealmList()
) : RealmObject() {
companion object
fun getMasterKey() = crossSigningKeys.firstOrNull { it.usages.contains(KeyUsage.MASTER.value) }
fun setMasterKey(info: KeyInfoEntity?) {
crossSigningKeys
.filter { it.usages.contains(KeyUsage.MASTER.value) }
.forEach { crossSigningKeys.remove(it) }
info?.let { crossSigningKeys.add(it) }
}
fun getSelfSignedKey() = crossSigningKeys.firstOrNull { it.usages.contains(KeyUsage.SELF_SIGNING.value) }
fun setSelfSignedKey(info: KeyInfoEntity?) {
crossSigningKeys
.filter { it.usages.contains(KeyUsage.SELF_SIGNING.value) }
.forEach { crossSigningKeys.remove(it) }
info?.let { crossSigningKeys.add(it) }
}
fun getUserSigningKey() = crossSigningKeys.firstOrNull { it.usages.contains(KeyUsage.USER_SIGNING.value) }
fun setUserSignedKey(info: KeyInfoEntity?) {
crossSigningKeys
.filter { it.usages.contains(KeyUsage.USER_SIGNING.value) }
.forEach { crossSigningKeys.remove(it) }
info?.let { crossSigningKeys.add(it) }
}
}
internal fun CrossSigningInfoEntity.deleteOnCascade() {
crossSigningKeys.clearWith { it.deleteOnCascade() }
deleteFromRealm()
}

View file

@ -1,123 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.di.SerializeNulls
import timber.log.Timber
internal object CryptoMapper {
private val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build()
private val listMigrationAdapter = moshi.adapter<List<String>>(
Types.newParameterizedType(
List::class.java,
String::class.java,
Any::class.java
)
)
private val mapMigrationAdapter = moshi.adapter<JsonDict>(
Types.newParameterizedType(
Map::class.java,
String::class.java,
Any::class.java
)
)
private val mapOfStringMigrationAdapter = moshi.adapter<Map<String, Map<String, String>>>(
Types.newParameterizedType(
Map::class.java,
String::class.java,
Any::class.java
)
)
internal fun mapToEntity(deviceInfo: CryptoDeviceInfo): DeviceInfoEntity {
return DeviceInfoEntity(primaryKey = DeviceInfoEntity.createPrimaryKey(deviceInfo.userId, deviceInfo.deviceId))
.also { updateDeviceInfoEntity(it, deviceInfo) }
}
internal fun updateDeviceInfoEntity(entity: DeviceInfoEntity, deviceInfo: CryptoDeviceInfo) {
entity.userId = deviceInfo.userId
entity.deviceId = deviceInfo.deviceId
entity.algorithmListJson = listMigrationAdapter.toJson(deviceInfo.algorithms)
entity.keysMapJson = mapMigrationAdapter.toJson(deviceInfo.keys)
entity.signatureMapJson = mapMigrationAdapter.toJson(deviceInfo.signatures)
entity.isBlocked = deviceInfo.isBlocked
val deviceInfoTrustLevel = deviceInfo.trustLevel
if (deviceInfoTrustLevel == null) {
entity.trustLevelEntity?.deleteFromRealm()
entity.trustLevelEntity = null
} else {
if (entity.trustLevelEntity == null) {
// Create a new TrustLevelEntity object
entity.trustLevelEntity = TrustLevelEntity()
}
// Update the existing TrustLevelEntity object
entity.trustLevelEntity?.crossSignedVerified = deviceInfoTrustLevel.crossSigningVerified
entity.trustLevelEntity?.locallyVerified = deviceInfoTrustLevel.locallyVerified
}
// We store the device name if present now
entity.unsignedMapJson = deviceInfo.unsigned?.deviceDisplayName
}
internal fun mapToModel(deviceInfoEntity: DeviceInfoEntity): CryptoDeviceInfo {
return CryptoDeviceInfo(
userId = deviceInfoEntity.userId ?: "",
deviceId = deviceInfoEntity.deviceId ?: "",
isBlocked = deviceInfoEntity.isBlocked ?: false,
trustLevel = deviceInfoEntity.trustLevelEntity?.let {
DeviceTrustLevel(it.crossSignedVerified ?: false, it.locallyVerified)
},
unsigned = deviceInfoEntity.unsignedMapJson?.let { UnsignedDeviceInfo(deviceDisplayName = it) },
signatures = deviceInfoEntity.signatureMapJson?.let {
try {
mapOfStringMigrationAdapter.fromJson(it)
} catch (failure: Throwable) {
Timber.e(failure)
null
}
},
keys = deviceInfoEntity.keysMapJson?.let {
try {
moshi.adapter<Map<String, String>>(
Types.newParameterizedType(
Map::class.java,
String::class.java,
Any::class.java
)
).fromJson(it)
} catch (failure: Throwable) {
Timber.e(failure)
null
}
},
algorithms = deviceInfoEntity.algorithmListJson?.let {
try {
listMigrationAdapter.fromJson(it)
} catch (failure: Throwable) {
Timber.e(failure)
null
}
},
firstTimeSeenLocalTs = deviceInfoEntity.firstTimeSeenLocalTs
)
}
}

View file

@ -26,10 +26,6 @@ internal open class CryptoRoomEntity(
var blacklistUnverifiedDevices: Boolean = false,
// Determines whether or not room history should be shared on new member invites
var shouldShareHistory: Boolean = false,
// Store the current outbound session for this room,
// to avoid re-create and re-share at each startup (if rotation not needed..)
// This is specific to megolm but not sure how to model it better
var outboundSessionInfo: OutboundGroupSessionInfoEntity? = null,
// a security to ensure that a room will never revert to not encrypted
// even if a new state event with empty encryption, or state is reset somehow
var wasEncryptedOnce: Boolean? = false,

View file

@ -1,54 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
internal fun DeviceInfoEntity.Companion.createPrimaryKey(userId: String, deviceId: String) = "$userId|$deviceId"
internal open class DeviceInfoEntity(
@PrimaryKey var primaryKey: String = "",
var deviceId: String? = null,
var identityKey: String? = null,
var userId: String? = null,
var isBlocked: Boolean? = null,
var algorithmListJson: String? = null,
var keysMapJson: String? = null,
var signatureMapJson: String? = null,
// Will contain the device name from unsigned data if present
var unsignedMapJson: String? = null,
var trustLevelEntity: TrustLevelEntity? = null,
/**
* We use that to make distinction between old devices (there before mine)
* and new ones. Used for example to detect new unverified login
*/
var firstTimeSeenLocalTs: Long? = null
) : RealmObject() {
@LinkingObjects("devices")
val users: RealmResults<UserEntity>? = null
companion object
}
internal fun DeviceInfoEntity.deleteOnCascade() {
trustLevelEntity?.deleteFromRealm()
deleteFromRealm()
}

View file

@ -1,37 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmList
import io.realm.RealmObject
internal open class KeyInfoEntity(
var publicKeyBase64: String? = null,
// var isTrusted: Boolean = false,
var usages: RealmList<String> = RealmList(),
/**
* The signature of this MXDeviceInfo.
* A map from "<userId>" to a map from "<key type>:<Publickey>" to "<signature>"
*/
var signatures: String? = null,
var trustLevelEntity: TrustLevelEntity? = null
) : RealmObject()
internal fun KeyInfoEntity.deleteOnCascade() {
trustLevelEntity?.deleteFromRealm()
deleteFromRealm()
}

View file

@ -1,35 +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.crypto.store.db.model
import io.realm.RealmObject
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.internal.di.MoshiProvider
internal open class KeyRequestReplyEntity(
var senderId: String? = null,
var fromDevice: String? = null,
var eventJson: String? = null
) : RealmObject() {
companion object
fun getEvent(): Event? {
return eventJson?.let {
MoshiProvider.providesMoshi().adapter(Event::class.java).fromJson(it)
}
}
}

View file

@ -1,30 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
internal open class KeysBackupDataEntity(
// Primary key to update this object. There is only one object, so it's a constant, please do not set it
@PrimaryKey
var primaryKey: Int = 0,
// The last known hash of the backed up keys on the server
var backupLastServerHash: String? = null,
// The last known number of backed up keys on the server
var backupLastServerNumberOfKeys: Int? = null
) : RealmObject()

View file

@ -1,71 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import org.matrix.android.sdk.internal.crypto.model.InboundGroupSessionData
import org.matrix.android.sdk.internal.di.MoshiProvider
internal fun OlmInboundGroupSessionEntity.Companion.createPrimaryKey(sessionId: String?, senderKey: String?) = "$sessionId|$senderKey"
internal open class OlmInboundGroupSessionEntity(
// Combined value to build a primary key
@PrimaryKey var primaryKey: String? = null,
// denormalization for faster querying (these fields are in the inboundGroupSessionDataJson)
var sessionId: String? = null,
var senderKey: String? = null,
var roomId: String? = null,
// Deprecated, used for migration / olmInboundGroupSessionData contains Json
// keep it in case of problem to have a chance to recover
var olmInboundGroupSessionData: String? = null,
// Stores the session data in an extensible format
// to allow to store data not yet supported for later use
var inboundGroupSessionDataJson: String? = null,
// The pickled session
var serializedOlmInboundGroupSession: String? = null,
// Flag that indicates whether or not the current inboundSession will be shared to
// invited users to decrypt past messages
var sharedHistory: Boolean = false,
// Indicate if the key has been backed up to the homeserver
var backedUp: Boolean = false
) :
RealmObject() {
// fun getInboundGroupSession(): OlmInboundGroupSessionWrapper2? {
// return try {
// deserializeFromRealm<OlmInboundGroupSessionWrapper2?>(olmInboundGroupSessionData)
// } catch (failure: Throwable) {
// Timber.e(failure, "## Deserialization failure")
// return null
// }
// }
//
// fun putInboundGroupSession(olmInboundGroupSessionWrapper: OlmInboundGroupSessionWrapper2?) {
// olmInboundGroupSessionData = serializeForRealm(olmInboundGroupSessionWrapper)
// }
companion object {
private val adapter = MoshiProvider.providesMoshi()
.adapter(InboundGroupSessionData::class.java)
}
}

View file

@ -1,35 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
internal fun OlmSessionEntity.Companion.createPrimaryKey(sessionId: String, deviceKey: String) = "$sessionId|$deviceKey"
// olmSessionData is a serialized OlmSession
internal open class OlmSessionEntity(
@PrimaryKey var primaryKey: String = "",
var sessionId: String? = null,
var deviceKey: String? = null,
var olmSessionData: String? = null,
var lastReceivedMessageTs: Long = 0
) :
RealmObject() {
companion object
}

View file

@ -1,28 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
internal open class OutboundGroupSessionInfoEntity(
var serializedOutboundSessionData: String? = null,
var creationTime: Long? = null,
var shouldShareHistory: Boolean = false
) : RealmObject() {
companion object
}

View file

@ -1,136 +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.store.db.model
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Types
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Index
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest
import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState
import org.matrix.android.sdk.api.session.crypto.RequestReply
import org.matrix.android.sdk.api.session.crypto.RequestResult
import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody
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.content.RoomKeyWithHeldContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.internal.di.MoshiProvider
internal open class OutgoingKeyRequestEntity(
@Index var requestId: String? = null,
var requestedIndex: Int? = null,
var recipientsData: String? = null,
var requestedInfoStr: String? = null,
var creationTimeStamp: Long? = null,
// de-normalization for better query (if not have to query all and parse json)
@Index var roomId: String? = null,
@Index var megolmSessionId: String? = null,
var replies: RealmList<KeyRequestReplyEntity> = RealmList()
) : RealmObject() {
@Index private var requestStateStr: String = OutgoingRoomKeyRequestState.UNSENT.name
companion object {
private val recipientsDataMapper: JsonAdapter<Map<String, List<String>>> =
MoshiProvider
.providesMoshi()
.adapter(
Types.newParameterizedType(Map::class.java, String::class.java, List::class.java)
)
}
private fun getRequestedKeyInfo(): RoomKeyRequestBody? = RoomKeyRequestBody.fromJson(requestedInfoStr)
fun setRequestBody(body: RoomKeyRequestBody) {
requestedInfoStr = body.toJson()
roomId = body.roomId
megolmSessionId = body.sessionId
}
var requestState: OutgoingRoomKeyRequestState
get() {
return tryOrNull { OutgoingRoomKeyRequestState.valueOf(requestStateStr) }
?: OutgoingRoomKeyRequestState.UNSENT
}
set(value) {
requestStateStr = value.name
}
private fun getRecipients(): Map<String, List<String>>? {
return this.recipientsData?.let { recipientsDataMapper.fromJson(it) }
}
fun setRecipients(recipients: Map<String, List<String>>) {
this.recipientsData = recipientsDataMapper.toJson(recipients)
}
fun addReply(userId: String, fromDevice: String?, event: Event) {
val newReply = KeyRequestReplyEntity(
senderId = userId,
fromDevice = fromDevice,
eventJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJson(event)
)
replies.add(newReply)
}
fun toOutgoingKeyRequest(): OutgoingKeyRequest {
return OutgoingKeyRequest(
requestBody = getRequestedKeyInfo(),
recipients = getRecipients().orEmpty(),
requestId = requestId ?: "",
fromIndex = requestedIndex ?: 0,
state = requestState,
results = replies.mapNotNull { entity ->
val userId = entity.senderId ?: return@mapNotNull null
val result = entity.eventJson?.let {
MoshiProvider.providesMoshi().adapter(Event::class.java).fromJson(it)
}?.let { event ->
eventToResult(event)
} ?: return@mapNotNull null
RequestReply(
userId = userId,
fromDevice = entity.fromDevice,
result = result
)
}
)
}
private fun eventToResult(event: Event): RequestResult? {
return when (event.getClearType()) {
in EventType.ROOM_KEY_WITHHELD.values -> {
event.content.toModel<RoomKeyWithHeldContent>()?.code?.let {
RequestResult.Failure(it)
}
}
EventType.FORWARDED_ROOM_KEY -> {
RequestResult.Success((event.content?.get("chain_index") as? Number)?.toInt() ?: 0)
}
else -> null
}
}
}
internal fun OutgoingKeyRequestEntity.deleteOnCascade() {
replies.deleteAllFromRealm()
deleteFromRealm()
}

View file

@ -1,38 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
import io.realm.annotations.Index
/**
* Keep a record of to whom (user/device) a given session should have been shared.
* It will be used to reply to keyshare requests from other users, in order to see if
* this session was originaly shared with a given user
*/
internal open class SharedSessionEntity(
var roomId: String? = null,
var algorithm: String? = null,
@Index var sessionId: String? = null,
@Index var userId: String? = null,
@Index var deviceId: String? = null,
@Index var deviceIdentityKey: String? = null,
var chainIndex: Int? = null
) : RealmObject() {
companion object
}

View file

@ -1,29 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
internal open class TrustLevelEntity(
var crossSignedVerified: Boolean? = null,
var locallyVerified: Boolean? = null
) : RealmObject() {
companion object
fun isVerified(): Boolean = crossSignedVerified == true || locallyVerified == true
}

View file

@ -1,38 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import org.matrix.android.sdk.internal.extensions.clearWith
internal open class UserEntity(
@PrimaryKey var userId: String? = null,
var devices: RealmList<DeviceInfoEntity> = RealmList(),
var crossSigningInfoEntity: CrossSigningInfoEntity? = null,
var deviceTrackingStatus: Int = 0
) : RealmObject() {
companion object
}
internal fun UserEntity.deleteOnCascade() {
devices.clearWith { it.deleteOnCascade() }
crossSigningInfoEntity?.deleteOnCascade()
deleteFromRealm()
}

View file

@ -1,48 +0,0 @@
/*
* Copyright 2020 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.store.db.model
import io.realm.RealmObject
import io.realm.annotations.Index
import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
/**
* When an encrypted message is sent in a room, the megolm key might not be sent to all devices present in the room.
* Sometimes this may be inadvertent (for example, if the sending device is not aware of some devices that have joined),
* but some times, this may be purposeful.
* For example, the sender may have blacklisted certain devices or users,
* or may be choosing to not send the megolm key to devices that they have not verified yet.
*/
internal open class WithHeldSessionEntity(
var roomId: String? = null,
var algorithm: String? = null,
@Index var sessionId: String? = null,
@Index var senderKey: String? = null,
var codeString: String? = null,
var reason: String? = null
) : RealmObject() {
var code: WithHeldCode?
get() {
return WithHeldCode.fromCode(codeString)
}
set(code) {
codeString = code?.value
}
companion object
}

View file

@ -1,36 +0,0 @@
/*
* Copyright 2020 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.store.db.query
import io.realm.Realm
import io.realm.kotlin.createObject
import io.realm.kotlin.where
import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
internal fun CrossSigningInfoEntity.Companion.getOrCreate(realm: Realm, userId: String): CrossSigningInfoEntity {
return realm.where<CrossSigningInfoEntity>()
.equalTo(UserEntityFields.USER_ID, userId)
.findFirst()
?: realm.createObject(userId)
}
internal fun CrossSigningInfoEntity.Companion.get(realm: Realm, userId: String): CrossSigningInfoEntity? {
return realm.where<CrossSigningInfoEntity>()
.equalTo(UserEntityFields.USER_ID, userId)
.findFirst()
}

View file

@ -1,39 +0,0 @@
/*
* Copyright 2020 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.store.db.query
import io.realm.Realm
import io.realm.kotlin.createObject
import io.realm.kotlin.where
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.createPrimaryKey
/**
* Get or create a device info.
*/
internal fun DeviceInfoEntity.Companion.getOrCreate(realm: Realm, userId: String, deviceId: String): DeviceInfoEntity {
val key = DeviceInfoEntity.createPrimaryKey(userId, deviceId)
return realm.where<DeviceInfoEntity>()
.equalTo(DeviceInfoEntityFields.PRIMARY_KEY, key)
.findFirst()
?: realm.createObject<DeviceInfoEntity>(key)
.apply {
this.deviceId = deviceId
}
}

View file

@ -1,71 +0,0 @@
/*
* Copyright 2020 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.store.db.query
import io.realm.Realm
import io.realm.RealmResults
import io.realm.kotlin.createObject
import io.realm.kotlin.where
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
internal fun SharedSessionEntity.Companion.get(
realm: Realm,
roomId: String?,
sessionId: String,
userId: String,
deviceId: String,
deviceIdentityKey: String?
): SharedSessionEntity? {
return realm.where<SharedSessionEntity>()
.equalTo(SharedSessionEntityFields.ROOM_ID, roomId)
.equalTo(SharedSessionEntityFields.SESSION_ID, sessionId)
.equalTo(SharedSessionEntityFields.ALGORITHM, MXCRYPTO_ALGORITHM_MEGOLM)
.equalTo(SharedSessionEntityFields.USER_ID, userId)
.equalTo(SharedSessionEntityFields.DEVICE_ID, deviceId)
.equalTo(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, deviceIdentityKey)
.findFirst()
}
internal fun SharedSessionEntity.Companion.get(realm: Realm, roomId: String?, sessionId: String): RealmResults<SharedSessionEntity> {
return realm.where<SharedSessionEntity>()
.equalTo(SharedSessionEntityFields.ROOM_ID, roomId)
.equalTo(SharedSessionEntityFields.SESSION_ID, sessionId)
.equalTo(SharedSessionEntityFields.ALGORITHM, MXCRYPTO_ALGORITHM_MEGOLM)
.findAll()
}
internal fun SharedSessionEntity.Companion.create(
realm: Realm,
roomId: String?,
sessionId: String,
userId: String,
deviceId: String,
deviceIdentityKey: String,
chainIndex: Int
): SharedSessionEntity {
return realm.createObject<SharedSessionEntity>().apply {
this.roomId = roomId
this.algorithm = MXCRYPTO_ALGORITHM_MEGOLM
this.sessionId = sessionId
this.userId = userId
this.deviceId = deviceId
this.deviceIdentityKey = deviceIdentityKey
this.chainIndex = chainIndex
}
}

View file

@ -1,44 +0,0 @@
/*
* Copyright 2020 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.store.db.query
import io.realm.Realm
import io.realm.kotlin.createObject
import io.realm.kotlin.where
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.deleteOnCascade
/**
* Get or create a user.
*/
internal fun UserEntity.Companion.getOrCreate(realm: Realm, userId: String): UserEntity {
return realm.where<UserEntity>()
.equalTo(UserEntityFields.USER_ID, userId)
.findFirst()
?: realm.createObject(userId)
}
/**
* Delete a user.
*/
internal fun UserEntity.Companion.delete(realm: Realm, userId: String) {
realm.where<UserEntity>()
.equalTo(UserEntityFields.USER_ID, userId)
.findFirst()
?.deleteOnCascade()
}

View file

@ -1,41 +0,0 @@
/*
* Copyright 2020 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.store.db.query
import io.realm.Realm
import io.realm.kotlin.createObject
import io.realm.kotlin.where
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntityFields
internal fun WithHeldSessionEntity.Companion.get(realm: Realm, roomId: String, sessionId: String): WithHeldSessionEntity? {
return realm.where<WithHeldSessionEntity>()
.equalTo(WithHeldSessionEntityFields.ROOM_ID, roomId)
.equalTo(WithHeldSessionEntityFields.SESSION_ID, sessionId)
.equalTo(WithHeldSessionEntityFields.ALGORITHM, MXCRYPTO_ALGORITHM_MEGOLM)
.findFirst()
}
internal fun WithHeldSessionEntity.Companion.getOrCreate(realm: Realm, roomId: String, sessionId: String): WithHeldSessionEntity? {
return get(realm, roomId, sessionId)
?: realm.createObject<WithHeldSessionEntity>().apply {
this.roomId = roomId
this.algorithm = MXCRYPTO_ALGORITHM_MEGOLM
this.sessionId = sessionId
}
}