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.doWithRealm
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CryptoRoomInfoMapper 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.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.CryptoMetadataEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity 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.CryptoRoomEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntity 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.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.getById
import org.matrix.android.sdk.internal.crypto.store.db.query.getOrCreate import org.matrix.android.sdk.internal.crypto.store.db.query.getOrCreate
import org.matrix.android.sdk.internal.di.CryptoDatabase 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 // still needed on rust due to the global crypto settings
init { init {
// Ensure CryptoMetadataEntity is inserted in DB // Ensure CryptoMetadataEntity is inserted in DB
// TODO BMA
doRealmTransaction("init", realmConfiguration) { realm -> doRealmTransaction("init", realmConfiguration) { realm ->
var currentMetadata = realm.where<CryptoMetadataEntity>().findFirst() var currentMetadata = realm.where<CryptoMetadataEntity>().findFirst()
@ -146,30 +141,7 @@ internal class RustCryptoStore @Inject constructor(
// nop // nop
} }
override fun tidyUpDataBase() { override fun tidyUpDataBase() = Unit
// 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 close() { override fun close() {
val tasks = monarchyWriteAsyncExecutor.shutdownNow() 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 package org.matrix.android.sdk.internal.crypto.store.db
import android.util.Base64
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.RealmObject
import timber.log.Timber 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 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. * 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) } 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 package org.matrix.android.sdk.internal.crypto.store.db
import io.realm.DynamicRealm 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 org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
import javax.inject.Inject import javax.inject.Inject
@ -25,6 +26,7 @@ import javax.inject.Inject
* 0, 1, 2: legacy Riot-Android; * 0, 1, 2: legacy Riot-Android;
* 3: migrate to RiotX schema; * 3: migrate to RiotX schema;
* 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6). * 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( internal class RealmCryptoStoreMigration @Inject constructor(
) : MatrixRealmMigration( ) : MatrixRealmMigration(
@ -39,8 +41,6 @@ internal class RealmCryptoStoreMigration @Inject constructor(
override fun hashCode() = 5000 override fun hashCode() = 5000
override fun doMigrate(realm: DynamicRealm, oldVersion: Long) { override fun doMigrate(realm: DynamicRealm, oldVersion: Long) {
// Delete the whole DB if (oldVersion < 24) MigrateCryptoTo024(realm).perform()
// TODO BMA
realm.deleteAll()
} }
} }

View file

@ -17,23 +17,9 @@
package org.matrix.android.sdk.internal.crypto.store.db package org.matrix.android.sdk.internal.crypto.store.db
import io.realm.annotations.RealmModule 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.CryptoMetadataEntity
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntity 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.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. * Realm module for Crypto store classes.
@ -43,21 +29,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEnti
classes = [ classes = [
CryptoMetadataEntity::class, CryptoMetadataEntity::class,
CryptoRoomEntity::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, MyDeviceLastSeenInfoEntity::class,
WithHeldSessionEntity::class,
SharedSessionEntity::class,
OutboundGroupSessionInfoEntity::class
] ]
) )
internal class RealmCryptoStoreModule 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, var blacklistUnverifiedDevices: Boolean = false,
// Determines whether or not room history should be shared on new member invites // Determines whether or not room history should be shared on new member invites
var shouldShareHistory: Boolean = false, 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 // 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 // even if a new state event with empty encryption, or state is reset somehow
var wasEncryptedOnce: Boolean? = false, 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
}
}