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:
@@ -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
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
)
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 = ""
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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()
|
||||
}
|
||||
|
@@ -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())
|
||||
}
|
||||
|
@@ -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)) {
|
||||
|
@@ -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()
|
||||
}
|
||||
|
Reference in New Issue
Block a user