1
0
mirror of https://github.com/vector-im/riotX-android synced 2025-10-06 00:02:48 +02:00

Realm : migrate Auth database to realm-kotlin

This commit is contained in:
ganfra
2022-07-22 19:49:40 +02:00
parent 4a68412777
commit 1380c60d10
18 changed files with 282 additions and 217 deletions

View File

@@ -20,18 +20,23 @@ import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import io.realm.RealmConfiguration
import io.realm.kotlin.RealmConfiguration
import kotlinx.coroutines.CoroutineScope
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.internal.auth.db.AUTH_REALM_SCHEMA
import org.matrix.android.sdk.internal.auth.db.AuthRealmMigration
import org.matrix.android.sdk.internal.auth.db.AuthRealmModule
import org.matrix.android.sdk.internal.auth.db.RealmPendingSessionStore
import org.matrix.android.sdk.internal.auth.db.RealmSessionParamsStore
import org.matrix.android.sdk.internal.auth.login.DefaultDirectLoginTask
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
import org.matrix.android.sdk.internal.database.RealmInstance
import org.matrix.android.sdk.internal.database.RealmKeysUtils
import org.matrix.android.sdk.internal.di.AuthDatabase
import org.matrix.android.sdk.internal.di.MatrixCoroutineScope
import org.matrix.android.sdk.internal.di.MatrixScope
import org.matrix.android.sdk.internal.legacy.DefaultLegacySessionImporter
import org.matrix.android.sdk.internal.wellknown.WellknownModule
import java.io.File
@@ -56,16 +61,31 @@ internal abstract class AuthModule {
old.renameTo(File(context.filesDir, "matrix-sdk-auth.realm"))
}
return RealmConfiguration.Builder()
return RealmConfiguration.Builder(AUTH_REALM_SCHEMA)
.apply {
realmKeysUtils.configureEncryption(this, DB_ALIAS)
}
.name("matrix-sdk-auth.realm")
.modules(AuthRealmModule())
.schemaVersion(authRealmMigration.schemaVersion)
.migration(authRealmMigration)
.build()
}
@JvmStatic
@Provides
@AuthDatabase
@MatrixScope
fun providesRealmInstance(
@AuthDatabase realmConfiguration: RealmConfiguration,
@MatrixCoroutineScope matrixCoroutineScope: CoroutineScope,
matrixCoroutineDispatchers: MatrixCoroutineDispatchers
): RealmInstance {
return RealmInstance(
coroutineScope = matrixCoroutineScope,
realmConfiguration = realmConfiguration,
coroutineDispatcher = matrixCoroutineDispatchers.io
)
}
}
@Binds

View File

@@ -16,17 +16,18 @@
package org.matrix.android.sdk.internal.auth.db
import io.realm.DynamicRealm
import io.realm.RealmMigration
import io.realm.kotlin.migration.AutomaticSchemaMigration
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo001
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo002
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo003
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo004
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo005
import org.matrix.android.sdk.internal.database.newVersion
import org.matrix.android.sdk.internal.database.oldVersion
import timber.log.Timber
import javax.inject.Inject
internal class AuthRealmMigration @Inject constructor() : RealmMigration {
internal class AuthRealmMigration @Inject constructor() : AutomaticSchemaMigration {
/**
* Forces all AuthRealmMigration instances to be equal.
* Avoids Realm throwing when multiple instances of the migration are set.
@@ -34,15 +35,17 @@ internal class AuthRealmMigration @Inject constructor() : RealmMigration {
override fun equals(other: Any?) = other is AuthRealmMigration
override fun hashCode() = 4000
val schemaVersion = 5L
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
override fun migrate(migrationContext: AutomaticSchemaMigration.MigrationContext) {
val oldVersion = migrationContext.oldVersion
val newVersion = migrationContext.newVersion
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
if (oldVersion < 1) MigrateAuthTo001(realm).perform()
if (oldVersion < 2) MigrateAuthTo002(realm).perform()
if (oldVersion < 3) MigrateAuthTo003(realm).perform()
if (oldVersion < 4) MigrateAuthTo004(realm).perform()
if (oldVersion < 5) MigrateAuthTo005(realm).perform()
if (oldVersion < 1) MigrateAuthTo001(migrationContext).perform()
if (oldVersion < 2) MigrateAuthTo002(migrationContext).perform()
if (oldVersion < 3) MigrateAuthTo003(migrationContext).perform()
if (oldVersion < 4) MigrateAuthTo004(migrationContext).perform()
if (oldVersion < 5) MigrateAuthTo005(migrationContext).perform()
}
val schemaVersion = 5L
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* 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.auth.db
/**
* Realm module for authentication classes.
*/
internal val AUTH_REALM_SCHEMA = setOf(
SessionParamsEntity::class,
PendingSessionEntity::class
)

View File

@@ -16,16 +16,14 @@
package org.matrix.android.sdk.internal.auth.db
import io.realm.RealmModel
import io.realm.annotations.RealmClass
import io.realm.kotlin.types.RealmObject
@RealmClass
internal open class PendingSessionEntity(
var homeServerConnectionConfigJson: String = "",
var clientSecret: String = "",
var sendAttempt: Int = 0,
var resetPasswordDataJson: String? = null,
var currentSession: String? = null,
var isRegistrationStarted: Boolean = false,
var currentThreePidDataJson: String? = null
) : RealmModel
internal class PendingSessionEntity : RealmObject {
var homeServerConnectionConfigJson: String = ""
var clientSecret: String = ""
var sendAttempt: Int = 0
var resetPasswordDataJson: String? = null
var currentSession: String? = null
var isRegistrationStarted: Boolean = false
var currentThreePidDataJson: String? = null
}

View File

@@ -57,14 +57,14 @@ internal class PendingSessionMapper @Inject constructor(moshi: Moshi) {
val resetPasswordDataJson = resetPasswordDataAdapter.toJson(sessionData.resetPasswordData)
val currentThreePidDataJson = threePidDataAdapter.toJson(sessionData.currentThreePidData)
return PendingSessionEntity(
homeServerConnectionConfigJson = homeServerConnectionConfigJson,
clientSecret = sessionData.clientSecret,
sendAttempt = sessionData.sendAttempt,
resetPasswordDataJson = resetPasswordDataJson,
currentSession = sessionData.currentSession,
isRegistrationStarted = sessionData.isRegistrationStarted,
currentThreePidDataJson = currentThreePidDataJson
)
return PendingSessionEntity().apply {
this.homeServerConnectionConfigJson = homeServerConnectionConfigJson
this.clientSecret = sessionData.clientSecret
this.sendAttempt = sessionData.sendAttempt
this.resetPasswordDataJson = resetPasswordDataJson
this.currentSession = sessionData.currentSession
this.isRegistrationStarted = sessionData.isRegistrationStarted
this.currentThreePidDataJson = currentThreePidDataJson
}
}
}

View File

@@ -16,47 +16,44 @@
package org.matrix.android.sdk.internal.auth.db
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.kotlin.MutableRealm
import org.matrix.android.sdk.internal.auth.PendingSessionStore
import org.matrix.android.sdk.internal.database.awaitTransaction
import org.matrix.android.sdk.internal.database.RealmInstance
import org.matrix.android.sdk.internal.di.AuthDatabase
import javax.inject.Inject
internal class RealmPendingSessionStore @Inject constructor(
private val mapper: PendingSessionMapper,
@AuthDatabase
private val realmConfiguration: RealmConfiguration
private val realmInstance: RealmInstance,
) : PendingSessionStore {
override suspend fun savePendingSessionData(pendingSessionData: PendingSessionData) {
awaitTransaction(realmConfiguration) { realm ->
realmInstance.write {
val entity = mapper.map(pendingSessionData)
if (entity != null) {
realm.where(PendingSessionEntity::class.java)
.findAll()
.deleteAllFromRealm()
realm.insert(entity)
deleteAllPendingSessions()
copyToRealm(entity)
}
}
}
override fun getPendingSessionData(): PendingSessionData? {
return Realm.getInstance(realmConfiguration).use { realm ->
realm
.where(PendingSessionEntity::class.java)
.findAll()
.map { mapper.map(it) }
.firstOrNull()
}
return realmInstance.blockingRealm()
.query(PendingSessionEntity::class)
.find()
.map { mapper.map(it) }
.firstOrNull()
}
override suspend fun delete() {
awaitTransaction(realmConfiguration) {
it.where(PendingSessionEntity::class.java)
.findAll()
.deleteAllFromRealm()
realmInstance.write {
deleteAllPendingSessions()
}
}
private fun MutableRealm.deleteAllPendingSessions() {
val pendingSessionEntities = query(PendingSessionEntity::class).find()
delete(pendingSessionEntities)
}
}

View File

@@ -16,14 +16,12 @@
package org.matrix.android.sdk.internal.auth.db
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.exceptions.RealmPrimaryKeyConstraintException
import io.realm.kotlin.UpdatePolicy
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.auth.data.sessionId
import org.matrix.android.sdk.internal.auth.SessionParamsStore
import org.matrix.android.sdk.internal.database.awaitTransaction
import org.matrix.android.sdk.internal.database.RealmInstance
import org.matrix.android.sdk.internal.di.AuthDatabase
import timber.log.Timber
import javax.inject.Inject
@@ -31,60 +29,49 @@ import javax.inject.Inject
internal class RealmSessionParamsStore @Inject constructor(
private val mapper: SessionParamsMapper,
@AuthDatabase
private val realmConfiguration: RealmConfiguration
private val realmInstance: RealmInstance
) : SessionParamsStore {
override fun getLast(): SessionParams? {
return Realm.getInstance(realmConfiguration).use { realm ->
realm
.where(SessionParamsEntity::class.java)
.findAll()
.map { mapper.map(it) }
.lastOrNull()
}
return realmInstance.blockingRealm()
.query(SessionParamsEntity::class)
.find()
.map { mapper.map(it) }
.lastOrNull()
}
override fun get(sessionId: String): SessionParams? {
return Realm.getInstance(realmConfiguration).use { realm ->
realm
.where(SessionParamsEntity::class.java)
.equalTo(SessionParamsEntityFields.SESSION_ID, sessionId)
.findAll()
.map { mapper.map(it) }
.firstOrNull()
}
return realmInstance.blockingRealm()
.query(SessionParamsEntity::class)
.query("sessionId == $0", sessionId)
.first()
.find()
?.let { mapper.map(it) }
}
override fun getAll(): List<SessionParams> {
return Realm.getInstance(realmConfiguration).use { realm ->
realm
.where(SessionParamsEntity::class.java)
.findAll()
.mapNotNull { mapper.map(it) }
}
return realmInstance.blockingRealm()
.query(SessionParamsEntity::class)
.find()
.mapNotNull { mapper.map(it) }
}
override suspend fun save(sessionParams: SessionParams) {
awaitTransaction(realmConfiguration) {
realmInstance.write {
val entity = mapper.map(sessionParams)
if (entity != null) {
try {
it.insert(entity)
} catch (e: RealmPrimaryKeyConstraintException) {
Timber.e(e, "Something wrong happened during previous session creation. Override with new credentials")
it.insertOrUpdate(entity)
}
copyToRealm(entity, updatePolicy = UpdatePolicy.ALL)
}
}
}
override suspend fun setTokenInvalid(sessionId: String) {
awaitTransaction(realmConfiguration) { realm ->
val currentSessionParams = realm
.where(SessionParamsEntity::class.java)
.equalTo(SessionParamsEntityFields.SESSION_ID, sessionId)
.findAll()
.firstOrNull()
realmInstance.write {
val currentSessionParams =
query(SessionParamsEntity::class)
.query("sessionId == $0", sessionId)
.first()
.find()
if (currentSessionParams == null) {
// Should not happen
@@ -98,13 +85,12 @@ internal class RealmSessionParamsStore @Inject constructor(
}
override suspend fun updateCredentials(newCredentials: Credentials) {
awaitTransaction(realmConfiguration) { realm ->
val currentSessionParams = realm
.where(SessionParamsEntity::class.java)
.equalTo(SessionParamsEntityFields.SESSION_ID, newCredentials.sessionId())
.findAll()
.map { mapper.map(it) }
.firstOrNull()
realmInstance.write {
val currentSessionParams = query(SessionParamsEntity::class)
.query("sessionId == $0", newCredentials.sessionId())
.first()
.find()
?.let { mapper.map(it) }
if (currentSessionParams == null) {
// Should not happen
@@ -119,26 +105,25 @@ internal class RealmSessionParamsStore @Inject constructor(
val entity = mapper.map(newSessionParams)
if (entity != null) {
realm.insertOrUpdate(entity)
copyToRealm(entity, updatePolicy = UpdatePolicy.ALL)
}
}
}
}
override suspend fun delete(sessionId: String) {
awaitTransaction(realmConfiguration) {
it.where(SessionParamsEntity::class.java)
.equalTo(SessionParamsEntityFields.SESSION_ID, sessionId)
.findAll()
.deleteAllFromRealm()
realmInstance.write {
val sessionParam = query(SessionParamsEntity::class)
.query("sessionId == $0", sessionId)
.find()
delete(sessionParam)
}
}
override suspend fun deleteAll() {
awaitTransaction(realmConfiguration) {
it.where(SessionParamsEntity::class.java)
.findAll()
.deleteAllFromRealm()
realmInstance.write {
val sessionParam = query(SessionParamsEntity::class).find()
delete(sessionParam)
}
}
}

View File

@@ -16,18 +16,17 @@
package org.matrix.android.sdk.internal.auth.db
import io.realm.RealmModel
import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
@RealmClass
internal open class SessionParamsEntity(
@PrimaryKey var sessionId: String = "",
var userId: String = "",
var credentialsJson: String = "",
var homeServerConnectionConfigJson: String = "",
// Set to false when the token is invalid and the user has been soft logged out
// In case of hard logout, this object is deleted from DB
var isTokenValid: Boolean = true,
var loginType: String = "",
) : RealmModel
internal class SessionParamsEntity : RealmObject {
@PrimaryKey var sessionId: String = ""
var userId: String = ""
var credentialsJson: String = ""
var homeServerConnectionConfigJson: String = ""
// Set to false when the token is invalid and the user has been soft logged out
// In case of hard logout, this object is deleted from DB
var isTokenValid: Boolean = true
var loginType: String = ""
}

View File

@@ -50,13 +50,13 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
if (credentialsJson == null || homeServerConnectionConfigJson == null) {
return null
}
return SessionParamsEntity(
sessionParams.credentials.sessionId(),
sessionParams.userId,
credentialsJson,
homeServerConnectionConfigJson,
sessionParams.isTokenValid,
sessionParams.loginType.name,
)
return SessionParamsEntity().apply {
this.sessionId = sessionParams.credentials.sessionId()
this.userId = sessionParams.userId
this.credentialsJson = credentialsJson
this.homeServerConnectionConfigJson = homeServerConnectionConfigJson
this.isTokenValid = sessionParams.isTokenValid
this.loginType = sessionParams.loginType.name
}
}
}

View File

@@ -16,26 +16,13 @@
package org.matrix.android.sdk.internal.auth.db.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.auth.db.PendingSessionEntityFields
import org.matrix.android.sdk.internal.util.database.RealmMigrator
import io.realm.kotlin.migration.AutomaticSchemaMigration
import org.matrix.android.sdk.internal.database.KotlinRealmMigrator
import timber.log.Timber
internal class MigrateAuthTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
internal class MigrateAuthTo001(migrationContext: AutomaticSchemaMigration.MigrationContext) : KotlinRealmMigrator(migrationContext, targetSchemaVersion = 1) {
override fun doMigrate(realm: DynamicRealm) {
override fun doMigrate(migrationContext: AutomaticSchemaMigration.MigrationContext) {
Timber.d("Create PendingSessionEntity")
realm.schema.create("PendingSessionEntity")
.addField(PendingSessionEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON, String::class.java)
.setRequired(PendingSessionEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON, true)
.addField(PendingSessionEntityFields.CLIENT_SECRET, String::class.java)
.setRequired(PendingSessionEntityFields.CLIENT_SECRET, true)
.addField(PendingSessionEntityFields.SEND_ATTEMPT, Integer::class.java)
.setRequired(PendingSessionEntityFields.SEND_ATTEMPT, true)
.addField(PendingSessionEntityFields.RESET_PASSWORD_DATA_JSON, String::class.java)
.addField(PendingSessionEntityFields.CURRENT_SESSION, String::class.java)
.addField(PendingSessionEntityFields.IS_REGISTRATION_STARTED, Boolean::class.java)
.addField(PendingSessionEntityFields.CURRENT_THREE_PID_DATA_JSON, String::class.java)
}
}

View File

@@ -16,18 +16,13 @@
package org.matrix.android.sdk.internal.auth.db.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
import org.matrix.android.sdk.internal.util.database.RealmMigrator
import io.realm.kotlin.migration.AutomaticSchemaMigration
import org.matrix.android.sdk.internal.database.KotlinRealmMigrator
import timber.log.Timber
internal class MigrateAuthTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) {
internal class MigrateAuthTo002(migrationContext: AutomaticSchemaMigration.MigrationContext) : KotlinRealmMigrator(migrationContext, targetSchemaVersion = 2) {
override fun doMigrate(realm: DynamicRealm) {
override fun doMigrate(migrationContext: AutomaticSchemaMigration.MigrationContext) {
Timber.d("Add boolean isTokenValid in SessionParamsEntity, with value true")
realm.schema.get("SessionParamsEntity")
?.addField(SessionParamsEntityFields.IS_TOKEN_VALID, Boolean::class.java)
?.transform { it.set(SessionParamsEntityFields.IS_TOKEN_VALID, true) }
}
}

View File

@@ -16,32 +16,24 @@
package org.matrix.android.sdk.internal.auth.db.migration
import io.realm.DynamicRealm
import io.realm.kotlin.migration.AutomaticSchemaMigration
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.sessionId
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
import org.matrix.android.sdk.internal.database.KotlinRealmMigrator
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.util.database.RealmMigrator
import timber.log.Timber
internal class MigrateAuthTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) {
internal class MigrateAuthTo003(migrationContext: AutomaticSchemaMigration.MigrationContext) : KotlinRealmMigrator(migrationContext, targetSchemaVersion = 3) {
override fun doMigrate(realm: DynamicRealm) {
override fun doMigrate(migrationContext: AutomaticSchemaMigration.MigrationContext) {
Timber.d("Update SessionParamsEntity primary key, to allow several sessions with the same userId")
realm.schema.get("SessionParamsEntity")
?.removePrimaryKey()
?.addField(SessionParamsEntityFields.SESSION_ID, String::class.java)
?.setRequired(SessionParamsEntityFields.SESSION_ID, true)
?.transform {
val credentialsJson = it.getString(SessionParamsEntityFields.CREDENTIALS_JSON)
val credentials = MoshiProvider.providesMoshi()
.adapter(Credentials::class.java)
.fromJson(credentialsJson)
it.set(SessionParamsEntityFields.SESSION_ID, credentials!!.sessionId())
}
?.addPrimaryKey(SessionParamsEntityFields.SESSION_ID)
val credentialsAdapter = MoshiProvider.providesMoshi()
.adapter(Credentials::class.java)
migrationContext.enumerate("SessionParamsEntity") { oldObject, newObject ->
val credentialsJson = oldObject.getValue("credentialsJson", String::class)
val credentials = credentialsAdapter.fromJson(credentialsJson)
newObject?.set("sessionId", credentials!!.sessionId())
}
}
}

View File

@@ -17,41 +17,39 @@
package org.matrix.android.sdk.internal.auth.db.migration
import android.net.Uri
import io.realm.DynamicRealm
import io.realm.kotlin.migration.AutomaticSchemaMigration
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
import org.matrix.android.sdk.internal.database.KotlinRealmMigrator
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.util.database.RealmMigrator
import timber.log.Timber
internal class MigrateAuthTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) {
internal class MigrateAuthTo004(migrationContext: AutomaticSchemaMigration.MigrationContext) : KotlinRealmMigrator(migrationContext, targetSchemaVersion = 4) {
override fun doMigrate(realm: DynamicRealm) {
override fun doMigrate(migrationContext: AutomaticSchemaMigration.MigrationContext) {
Timber.d("Update SessionParamsEntity to add HomeServerConnectionConfig.homeServerUriBase value")
val adapter = MoshiProvider.providesMoshi()
.adapter(HomeServerConnectionConfig::class.java)
realm.schema.get("SessionParamsEntity")
?.transform {
val homeserverConnectionConfigJson = it.getString(SessionParamsEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON)
migrationContext.enumerate("SessionParamsEntity") { oldObj, newObj ->
val homeserverConnectionConfigJson = oldObj.getValue("homeServerConnectionConfigJson", String::class)
val homeserverConnectionConfig = adapter
.fromJson(homeserverConnectionConfigJson)
val homeserverUrl = homeserverConnectionConfig?.homeServerUri?.toString()
val homeserverConnectionConfig = adapter
.fromJson(homeserverConnectionConfigJson)
// Special case for matrix.org. Old session may use "https://matrix.org", newer one may use
// "https://matrix-client.matrix.org". So fix that here
val alteredHomeserverConnectionConfig =
if (homeserverUrl == "https://matrix.org" || homeserverUrl == "https://matrix-client.matrix.org") {
homeserverConnectionConfig.copy(
homeServerUri = Uri.parse("https://matrix.org"),
homeServerUriBase = Uri.parse("https://matrix-client.matrix.org")
)
} else {
homeserverConnectionConfig
}
newObj?.set("homeServerConnectionConfigJson", adapter.toJson(alteredHomeserverConnectionConfig))
val homeserverUrl = homeserverConnectionConfig?.homeServerUri?.toString()
// Special case for matrix.org. Old session may use "https://matrix.org", newer one may use
// "https://matrix-client.matrix.org". So fix that here
val alteredHomeserverConnectionConfig =
if (homeserverUrl == "https://matrix.org" || homeserverUrl == "https://matrix-client.matrix.org") {
homeserverConnectionConfig.copy(
homeServerUri = Uri.parse("https://matrix.org"),
homeServerUriBase = Uri.parse("https://matrix-client.matrix.org")
)
} else {
homeserverConnectionConfig
}
it.set(SessionParamsEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON, adapter.toJson(alteredHomeserverConnectionConfig))
}
}
}
}

View File

@@ -16,20 +16,18 @@
package org.matrix.android.sdk.internal.auth.db.migration
import io.realm.DynamicRealm
import io.realm.kotlin.migration.AutomaticSchemaMigration
import org.matrix.android.sdk.api.auth.LoginType
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
import org.matrix.android.sdk.internal.util.database.RealmMigrator
import org.matrix.android.sdk.internal.database.KotlinRealmMigrator
import timber.log.Timber
internal class MigrateAuthTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) {
internal class MigrateAuthTo005(migrationContext: AutomaticSchemaMigration.MigrationContext) : KotlinRealmMigrator(migrationContext, targetSchemaVersion = 5) {
override fun doMigrate(realm: DynamicRealm) {
override fun doMigrate(migrationContext: AutomaticSchemaMigration.MigrationContext) {
Timber.d("Update SessionParamsEntity to add LoginType")
realm.schema.get("SessionParamsEntity")
?.addField(SessionParamsEntityFields.LOGIN_TYPE, String::class.java)
?.setRequired(SessionParamsEntityFields.LOGIN_TYPE, true)
?.transform { it.set(SessionParamsEntityFields.LOGIN_TYPE, LoginType.UNKNOWN.name) }
migrationContext.enumerate("SessionParamsEntity") { _, newObj ->
newObj?.set("loginType", LoginType.UNKNOWN.name)
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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.database
import io.realm.kotlin.migration.AutomaticSchemaMigration
import timber.log.Timber
internal abstract class KotlinRealmMigrator(
private val migrationContext: AutomaticSchemaMigration.MigrationContext,
private val targetSchemaVersion: Int
) {
fun perform() {
Timber.d("Migrate ${migrationContext.oldRealm.configuration.name} to $targetSchemaVersion")
doMigrate(migrationContext)
}
abstract fun doMigrate(migrationContext: AutomaticSchemaMigration.MigrationContext)
}
val AutomaticSchemaMigration.MigrationContext.oldVersion: Long
get() {
return oldRealm.schemaVersion()
}
val AutomaticSchemaMigration.MigrationContext.newVersion: Long
get() {
return newRealm.schemaVersion()
}

View File

@@ -19,6 +19,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
@@ -26,6 +27,8 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.toOptional
import org.matrix.android.sdk.internal.database.pagedlist.RealmTiledDataSource
internal typealias RealmQueryBuilder<T> = (Realm) -> RealmQuery<T>
@@ -74,6 +77,16 @@ internal class RealmInstance(
}
}
fun <T : RealmObject> queryFirst(
realmQueryBuilder: RealmQueryBuilder<T>
): Flow<Optional<T>> {
return getRealm().flatMapConcat {
realmQueryBuilder(it).first().asFlow()
}.map {
Optional.from(it.obj)
}
}
fun <T : RealmObject> queryPagedList(
config: PagedList.Config,
queryBuilder: RealmQueryBuilder<T>
@@ -110,6 +123,12 @@ internal class RealmInstance(
}
}
fun blockingRealm(): Realm {
return runBlocking {
getRealm().first()
}
}
fun getRealm(): Flow<Realm> = flow {
emit(realm.await())
}

View File

@@ -95,6 +95,12 @@ internal class RealmKeysUtils @Inject constructor(
realmConfigurationBuilder.encryptionKey(key)
}
fun configureEncryption(realmConfigurationBuilder: io.realm.kotlin.RealmConfiguration.Builder, alias: String) {
val key = getRealmEncryptionKey(alias)
realmConfigurationBuilder.encryptionKey(key)
}
// Expose to handle Realm migration to riotX
fun getRealmEncryptionKey(alias: String): ByteArray {
val key = if (hasKeyForDatabase(alias)) {

View File

@@ -25,19 +25,19 @@ import org.matrix.android.sdk.internal.di.GlobalDatabase
import javax.inject.Inject
internal class DefaultDebugService @Inject constructor(
@AuthDatabase private val realmConfigurationAuth: RealmConfiguration,
//@AuthDatabase private val realmConfigurationAuth: RealmConfiguration,
@GlobalDatabase private val realmConfigurationGlobal: RealmConfiguration,
private val sessionManager: SessionManager,
) : DebugService {
override fun getAllRealmConfigurations(): List<RealmConfiguration> {
return sessionManager.getLastSession()?.getRealmConfigurations().orEmpty() +
realmConfigurationAuth +
//realmConfigurationAuth +
realmConfigurationGlobal
}
override fun logDbUsageInfo() {
RealmDebugTools(realmConfigurationAuth).logInfo("Auth")
//RealmDebugTools(realmConfigurationAuth).logInfo("Auth")
RealmDebugTools(realmConfigurationGlobal).logInfo("Global")
sessionManager.getLastSession()?.logDbUsageInfo()
}