CryptoStore migration has to be object to avoid crash

Thread: main, Exception: java.lang.IllegalArgumentException: Configurations cannot be different if used to open the same file. The most likely cause is that equals() and hashCode() are not overridden in the migration class: org.matrix.android.sdk.internal.database.RealmSessionStoreMigration
This commit is contained in:
Benoit Marty 2021-07-02 15:46:04 +02:00 committed by Benoit Marty
parent 2a0230633d
commit 2513be744c
8 changed files with 21 additions and 30 deletions

1
changelog.d/3605.bugfix Normal file
View File

@ -0,0 +1 @@
CryptoStore migration has to be object to avoid crash

View File

@ -112,7 +112,6 @@ internal abstract class CryptoModule {
@SessionScope @SessionScope
fun providesRealmConfiguration(@SessionFilesDirectory directory: File, fun providesRealmConfiguration(@SessionFilesDirectory directory: File,
@UserMd5 userMd5: String, @UserMd5 userMd5: String,
realmCryptoStoreMigration: RealmCryptoStoreMigration,
realmKeysUtils: RealmKeysUtils): RealmConfiguration { realmKeysUtils: RealmKeysUtils): RealmConfiguration {
return RealmConfiguration.Builder() return RealmConfiguration.Builder()
.directory(directory) .directory(directory)
@ -123,7 +122,7 @@ internal abstract class CryptoModule {
.modules(RealmCryptoStoreModule()) .modules(RealmCryptoStoreModule())
.allowWritesOnUiThread(true) .allowWritesOnUiThread(true)
.schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION) .schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION)
.migration(realmCryptoStoreMigration) .migration(RealmCryptoStoreMigration)
.build() .build()
} }

View File

@ -18,6 +18,9 @@ package org.matrix.android.sdk.internal.crypto.store.db
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import com.squareup.moshi.Types import com.squareup.moshi.Types
import io.realm.DynamicRealm
import io.realm.RealmMigration
import io.realm.RealmObjectSchema
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo
@ -35,29 +38,24 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntit
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.OlmInboundGroupSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntityFields
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.di.SerializeNulls import org.matrix.android.sdk.internal.di.SerializeNulls
import io.realm.DynamicRealm
import io.realm.RealmMigration
import io.realm.RealmObjectSchema
import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntityFields
import org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 import org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
import org.matrix.androidsdk.crypto.data.MXDeviceInfo as LegacyMXDeviceInfo import org.matrix.androidsdk.crypto.data.MXDeviceInfo as LegacyMXDeviceInfo
internal class RealmCryptoStoreMigration @Inject constructor(private val crossSigningKeysMapper: CrossSigningKeysMapper) : RealmMigration { internal object RealmCryptoStoreMigration : RealmMigration {
companion object { // 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) const val CRYPTO_STORE_SCHEMA_VERSION = 12L
const val CRYPTO_STORE_SCHEMA_VERSION = 12L
}
private fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema { private fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema {
if (!hasField(fieldName)) { if (!hasField(fieldName)) {
@ -384,6 +382,8 @@ internal class RealmCryptoStoreMigration @Inject constructor(private val crossSi
private fun migrateTo7(realm: DynamicRealm) { private fun migrateTo7(realm: DynamicRealm) {
Timber.d("Step 6 -> 7") Timber.d("Step 6 -> 7")
Timber.d("Updating KeyInfoEntity table") Timber.d("Updating KeyInfoEntity table")
val crossSigningKeysMapper = CrossSigningKeysMapper(MoshiProvider.providesMoshi())
val keyInfoEntities = realm.where("KeyInfoEntity").findAll() val keyInfoEntities = realm.where("KeyInfoEntity").findAll()
try { try {
keyInfoEntities.forEach { keyInfoEntities.forEach {

View File

@ -43,13 +43,10 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.query.process
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
class RealmSessionStoreMigration @Inject constructor() : RealmMigration { internal object RealmSessionStoreMigration : RealmMigration {
companion object { const val SESSION_STORE_SCHEMA_VERSION = 15L
const val SESSION_STORE_SCHEMA_VERSION = 15L
}
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Timber.v("Migrating Realm Session from $oldVersion to $newVersion") Timber.v("Migrating Realm Session from $oldVersion to $newVersion")

View File

@ -43,7 +43,6 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
@SessionFilesDirectory val directory: File, @SessionFilesDirectory val directory: File,
@SessionId val sessionId: String, @SessionId val sessionId: String,
@UserMd5 val userMd5: String, @UserMd5 val userMd5: String,
val migration: RealmSessionStoreMigration,
context: Context) { context: Context) {
// Keep legacy preferences name for compatibility reason // Keep legacy preferences name for compatibility reason
@ -72,7 +71,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor(
.allowWritesOnUiThread(true) .allowWritesOnUiThread(true)
.modules(SessionRealmModule()) .modules(SessionRealmModule())
.schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION) .schemaVersion(RealmSessionStoreMigration.SESSION_STORE_SCHEMA_VERSION)
.migration(migration) .migration(RealmSessionStoreMigration)
.build() .build()
// Try creating a realm instance and if it succeeds we can clear the flag // Try creating a realm instance and if it succeeds we can clear the flag

View File

@ -42,7 +42,6 @@ import org.matrix.android.sdk.internal.legacy.riot.HomeServerConnectionConfig as
internal class DefaultLegacySessionImporter @Inject constructor( internal class DefaultLegacySessionImporter @Inject constructor(
private val context: Context, private val context: Context,
private val sessionParamsStore: SessionParamsStore, private val sessionParamsStore: SessionParamsStore,
private val realmCryptoStoreMigration: RealmCryptoStoreMigration,
private val realmKeysUtils: RealmKeysUtils private val realmKeysUtils: RealmKeysUtils
) : LegacySessionImporter { ) : LegacySessionImporter {
@ -172,7 +171,7 @@ internal class DefaultLegacySessionImporter @Inject constructor(
.name("crypto_store.realm") .name("crypto_store.realm")
.modules(RealmCryptoStoreModule()) .modules(RealmCryptoStoreModule())
.schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION) .schemaVersion(RealmCryptoStoreMigration.CRYPTO_STORE_SCHEMA_VERSION)
.migration(realmCryptoStoreMigration) .migration(RealmCryptoStoreMigration)
.build() .build()
Timber.d("Migration: copy DB to encrypted DB") Timber.d("Migration: copy DB to encrypted DB")

View File

@ -60,7 +60,6 @@ internal abstract class IdentityModule {
@SessionScope @SessionScope
fun providesIdentityRealmConfiguration(realmKeysUtils: RealmKeysUtils, fun providesIdentityRealmConfiguration(realmKeysUtils: RealmKeysUtils,
@SessionFilesDirectory directory: File, @SessionFilesDirectory directory: File,
migration: RealmIdentityStoreMigration,
@UserMd5 userMd5: String): RealmConfiguration { @UserMd5 userMd5: String): RealmConfiguration {
return RealmConfiguration.Builder() return RealmConfiguration.Builder()
.directory(directory) .directory(directory)
@ -69,7 +68,7 @@ internal abstract class IdentityModule {
realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5)) realmKeysUtils.configureEncryption(this, SessionModule.getKeyAlias(userMd5))
} }
.schemaVersion(RealmIdentityStoreMigration.IDENTITY_STORE_SCHEMA_VERSION) .schemaVersion(RealmIdentityStoreMigration.IDENTITY_STORE_SCHEMA_VERSION)
.migration(migration) .migration(RealmIdentityStoreMigration)
.allowWritesOnUiThread(true) .allowWritesOnUiThread(true)
.modules(IdentityRealmModule()) .modules(IdentityRealmModule())
.build() .build()

View File

@ -19,13 +19,10 @@ package org.matrix.android.sdk.internal.session.identity.db
import io.realm.DynamicRealm import io.realm.DynamicRealm
import io.realm.RealmMigration import io.realm.RealmMigration
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
internal class RealmIdentityStoreMigration @Inject constructor() : RealmMigration { internal object RealmIdentityStoreMigration : RealmMigration {
companion object { const val IDENTITY_STORE_SCHEMA_VERSION = 1L
const val IDENTITY_STORE_SCHEMA_VERSION = 1L
}
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Timber.v("Migrating Realm Identity from $oldVersion to $newVersion") Timber.v("Migrating Realm Identity from $oldVersion to $newVersion")