mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Split the classes RealmMigration into smaller classes
This commit is contained in:
parent
4ce1ab2665
commit
8a4ecf616a
50 changed files with 2190 additions and 1093 deletions
|
@ -16,13 +16,12 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.auth.db
|
||||
|
||||
import android.net.Uri
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.RealmMigration
|
||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||
import org.matrix.android.sdk.api.auth.data.sessionId
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
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 timber.log.Timber
|
||||
|
||||
internal object AuthRealmMigration : RealmMigration {
|
||||
|
@ -33,85 +32,9 @@ internal object AuthRealmMigration : RealmMigration {
|
|||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
|
||||
|
||||
if (oldVersion <= 0) migrateTo1(realm)
|
||||
if (oldVersion <= 1) migrateTo2(realm)
|
||||
if (oldVersion <= 2) migrateTo3(realm)
|
||||
if (oldVersion <= 3) migrateTo4(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
Timber.d("Step 0 -> 1")
|
||||
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)
|
||||
}
|
||||
|
||||
private fun migrateTo2(realm: DynamicRealm) {
|
||||
Timber.d("Step 1 -> 2")
|
||||
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) }
|
||||
}
|
||||
|
||||
private fun migrateTo3(realm: DynamicRealm) {
|
||||
Timber.d("Step 2 -> 3")
|
||||
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)
|
||||
}
|
||||
|
||||
private fun migrateTo4(realm: DynamicRealm) {
|
||||
Timber.d("Step 3 -> 4")
|
||||
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)
|
||||
|
||||
val homeserverConnectionConfig = adapter
|
||||
.fromJson(homeserverConnectionConfigJson)
|
||||
|
||||
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))
|
||||
}
|
||||
if (oldVersion < 1) MigrateAuthTo001(realm).perform()
|
||||
if (oldVersion < 2) MigrateAuthTo002(realm).perform()
|
||||
if (oldVersion < 3) MigrateAuthTo003(realm).perform()
|
||||
if (oldVersion < 4) MigrateAuthTo004(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.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 timber.log.Timber
|
||||
|
||||
class MigrateAuthTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.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 timber.log.Timber
|
||||
|
||||
class MigrateAuthTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
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) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.auth.db.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
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.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateAuthTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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.auth.db.migration
|
||||
|
||||
import android.net.Uri
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateAuthTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
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)
|
||||
|
||||
val homeserverConnectionConfig = adapter
|
||||
.fromJson(homeserverConnectionConfigJson)
|
||||
|
||||
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,39 +16,23 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto.store.db
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
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.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.GossipingEventEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRequestEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.KeyInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntityFields
|
||||
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.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.SharedSessionEntityFields
|
||||
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.WithHeldSessionEntityFields
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.di.SerializeNulls
|
||||
import org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo001Legacy
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo002Legacy
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo003RiotX
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo004
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo005
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo006
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo007
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo008
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo009
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo010
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo011
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo012
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo013
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.migration.MigrateCryptoTo014
|
||||
import timber.log.Timber
|
||||
import org.matrix.androidsdk.crypto.data.MXDeviceInfo as LegacyMXDeviceInfo
|
||||
|
||||
internal object RealmCryptoStoreMigration : RealmMigration {
|
||||
|
||||
|
@ -57,519 +41,22 @@ internal object RealmCryptoStoreMigration : RealmMigration {
|
|||
// 4, 5, 6, 7, 8, 9: migrations from RiotX (which was previously 1, 2, 3, 4, 5, 6)
|
||||
const val CRYPTO_STORE_SCHEMA_VERSION = 14L
|
||||
|
||||
private fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema {
|
||||
if (!hasField(fieldName)) {
|
||||
addField(fieldName, fieldType)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun RealmObjectSchema.removeFieldIfExists(fieldName: String): RealmObjectSchema {
|
||||
if (hasField(fieldName)) {
|
||||
removeField(fieldName)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun RealmObjectSchema.setRequiredIfNotAlready(fieldName: String, isRequired: Boolean): RealmObjectSchema {
|
||||
if (isRequired != isRequired(fieldName)) {
|
||||
setRequired(fieldName, isRequired)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.v("Migrating Realm Crypto from $oldVersion to $newVersion")
|
||||
|
||||
if (oldVersion <= 0) migrateTo1Legacy(realm)
|
||||
if (oldVersion <= 1) migrateTo2Legacy(realm)
|
||||
if (oldVersion <= 2) migrateTo3RiotX(realm)
|
||||
if (oldVersion <= 3) migrateTo4(realm)
|
||||
if (oldVersion <= 4) migrateTo5(realm)
|
||||
if (oldVersion <= 5) migrateTo6(realm)
|
||||
if (oldVersion <= 6) migrateTo7(realm)
|
||||
if (oldVersion <= 7) migrateTo8(realm)
|
||||
if (oldVersion <= 8) migrateTo9(realm)
|
||||
if (oldVersion <= 9) migrateTo10(realm)
|
||||
if (oldVersion <= 10) migrateTo11(realm)
|
||||
if (oldVersion <= 11) migrateTo12(realm)
|
||||
if (oldVersion <= 12) migrateTo13(realm)
|
||||
if (oldVersion <= 13) migrateTo14(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1Legacy(realm: DynamicRealm) {
|
||||
Timber.d("Step 0 -> 1")
|
||||
Timber.d("Add field lastReceivedMessageTs (Long) and set the value to 0")
|
||||
|
||||
realm.schema.get("OlmSessionEntity")
|
||||
?.addField(OlmSessionEntityFields.LAST_RECEIVED_MESSAGE_TS, Long::class.java)
|
||||
?.transform {
|
||||
it.setLong(OlmSessionEntityFields.LAST_RECEIVED_MESSAGE_TS, 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo2Legacy(realm: DynamicRealm) {
|
||||
Timber.d("Step 1 -> 2")
|
||||
Timber.d("Update IncomingRoomKeyRequestEntity format: requestBodyString field is exploded into several fields")
|
||||
|
||||
realm.schema.get("IncomingRoomKeyRequestEntity")
|
||||
?.addFieldIfNotExists("requestBodyAlgorithm", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodyRoomId", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySenderKey", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySessionId", String::class.java)
|
||||
?.transform { dynamicObject ->
|
||||
try {
|
||||
val requestBodyString = dynamicObject.getString("requestBodyString")
|
||||
// It was a map before
|
||||
val map: Map<String, String>? = deserializeFromRealm(requestBodyString)
|
||||
|
||||
map?.let {
|
||||
dynamicObject.setString("requestBodyAlgorithm", it["algorithm"])
|
||||
dynamicObject.setString("requestBodyRoomId", it["room_id"])
|
||||
dynamicObject.setString("requestBodySenderKey", it["sender_key"])
|
||||
dynamicObject.setString("requestBodySessionId", it["session_id"])
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
?.removeFieldIfExists("requestBodyString")
|
||||
|
||||
Timber.d("Update IncomingRoomKeyRequestEntity format: requestBodyString field is exploded into several fields")
|
||||
|
||||
realm.schema.get("OutgoingRoomKeyRequestEntity")
|
||||
?.addFieldIfNotExists("requestBodyAlgorithm", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodyRoomId", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySenderKey", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySessionId", String::class.java)
|
||||
?.transform { dynamicObject ->
|
||||
try {
|
||||
val requestBodyString = dynamicObject.getString("requestBodyString")
|
||||
// It was a map before
|
||||
val map: Map<String, String>? = deserializeFromRealm(requestBodyString)
|
||||
|
||||
map?.let {
|
||||
dynamicObject.setString("requestBodyAlgorithm", it["algorithm"])
|
||||
dynamicObject.setString("requestBodyRoomId", it["room_id"])
|
||||
dynamicObject.setString("requestBodySenderKey", it["sender_key"])
|
||||
dynamicObject.setString("requestBodySessionId", it["session_id"])
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
?.removeFieldIfExists("requestBodyString")
|
||||
|
||||
Timber.d("Create KeysBackupDataEntity")
|
||||
|
||||
if (!realm.schema.contains("KeysBackupDataEntity")) {
|
||||
realm.schema.create("KeysBackupDataEntity")
|
||||
.addField(KeysBackupDataEntityFields.PRIMARY_KEY, Integer::class.java)
|
||||
.addPrimaryKey(KeysBackupDataEntityFields.PRIMARY_KEY)
|
||||
.setRequired(KeysBackupDataEntityFields.PRIMARY_KEY, true)
|
||||
.addField(KeysBackupDataEntityFields.BACKUP_LAST_SERVER_HASH, String::class.java)
|
||||
.addField(KeysBackupDataEntityFields.BACKUP_LAST_SERVER_NUMBER_OF_KEYS, Integer::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo3RiotX(realm: DynamicRealm) {
|
||||
Timber.d("Step 2 -> 3")
|
||||
Timber.d("Migrate to RiotX model")
|
||||
|
||||
realm.schema.get("CryptoRoomEntity")
|
||||
?.addFieldIfNotExists(CryptoRoomEntityFields.SHOULD_ENCRYPT_FOR_INVITED_MEMBERS, Boolean::class.java)
|
||||
?.setRequiredIfNotAlready(CryptoRoomEntityFields.SHOULD_ENCRYPT_FOR_INVITED_MEMBERS, false)
|
||||
|
||||
// Convert format of MXDeviceInfo, package has to be the same.
|
||||
realm.schema.get("DeviceInfoEntity")
|
||||
?.transform { obj ->
|
||||
try {
|
||||
val oldSerializedData = obj.getString("deviceInfoData")
|
||||
deserializeFromRealm<LegacyMXDeviceInfo>(oldSerializedData)?.let { legacyMxDeviceInfo ->
|
||||
val newMxDeviceInfo = MXDeviceInfo(
|
||||
deviceId = legacyMxDeviceInfo.deviceId,
|
||||
userId = legacyMxDeviceInfo.userId,
|
||||
algorithms = legacyMxDeviceInfo.algorithms,
|
||||
keys = legacyMxDeviceInfo.keys,
|
||||
signatures = legacyMxDeviceInfo.signatures,
|
||||
unsigned = legacyMxDeviceInfo.unsigned,
|
||||
verified = legacyMxDeviceInfo.mVerified
|
||||
)
|
||||
|
||||
obj.setString("deviceInfoData", serializeForRealm(newMxDeviceInfo))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
|
||||
// Convert MXOlmInboundGroupSession2 to OlmInboundGroupSessionWrapper
|
||||
realm.schema.get("OlmInboundGroupSessionEntity")
|
||||
?.transform { obj ->
|
||||
try {
|
||||
val oldSerializedData = obj.getString("olmInboundGroupSessionData")
|
||||
deserializeFromRealm<MXOlmInboundGroupSession2>(oldSerializedData)?.let { mxOlmInboundGroupSession2 ->
|
||||
val sessionKey = mxOlmInboundGroupSession2.mSession.sessionIdentifier()
|
||||
val newOlmInboundGroupSessionWrapper = OlmInboundGroupSessionWrapper(sessionKey, false)
|
||||
.apply {
|
||||
olmInboundGroupSession = mxOlmInboundGroupSession2.mSession
|
||||
roomId = mxOlmInboundGroupSession2.mRoomId
|
||||
senderKey = mxOlmInboundGroupSession2.mSenderKey
|
||||
keysClaimed = mxOlmInboundGroupSession2.mKeysClaimed
|
||||
forwardingCurve25519KeyChain = mxOlmInboundGroupSession2.mForwardingCurve25519KeyChain
|
||||
}
|
||||
|
||||
obj.setString("olmInboundGroupSessionData", serializeForRealm(newOlmInboundGroupSessionWrapper))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Version 4L added Cross Signing info persistence
|
||||
private fun migrateTo4(realm: DynamicRealm) {
|
||||
Timber.d("Step 3 -> 4")
|
||||
|
||||
if (realm.schema.contains("TrustLevelEntity")) {
|
||||
Timber.d("Skipping Step 3 -> 4 because entities already exist")
|
||||
return
|
||||
}
|
||||
|
||||
Timber.d("Create KeyInfoEntity")
|
||||
val trustLevelEntityEntitySchema = realm.schema.create("TrustLevelEntity")
|
||||
.addField(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, Boolean::class.java)
|
||||
.setNullable(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, true)
|
||||
.addField(TrustLevelEntityFields.LOCALLY_VERIFIED, Boolean::class.java)
|
||||
.setNullable(TrustLevelEntityFields.LOCALLY_VERIFIED, true)
|
||||
|
||||
val keyInfoEntitySchema = realm.schema.create("KeyInfoEntity")
|
||||
.addField(KeyInfoEntityFields.PUBLIC_KEY_BASE64, String::class.java)
|
||||
.addField(KeyInfoEntityFields.SIGNATURES, String::class.java)
|
||||
.addRealmListField(KeyInfoEntityFields.USAGES.`$`, String::class.java)
|
||||
.addRealmObjectField(KeyInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevelEntityEntitySchema)
|
||||
|
||||
Timber.d("Create CrossSigningInfoEntity")
|
||||
|
||||
val crossSigningInfoSchema = realm.schema.create("CrossSigningInfoEntity")
|
||||
.addField(CrossSigningInfoEntityFields.USER_ID, String::class.java)
|
||||
.addPrimaryKey(CrossSigningInfoEntityFields.USER_ID)
|
||||
.addRealmListField(CrossSigningInfoEntityFields.CROSS_SIGNING_KEYS.`$`, keyInfoEntitySchema)
|
||||
|
||||
Timber.d("Updating UserEntity table")
|
||||
realm.schema.get("UserEntity")
|
||||
?.addRealmObjectField(UserEntityFields.CROSS_SIGNING_INFO_ENTITY.`$`, crossSigningInfoSchema)
|
||||
|
||||
Timber.d("Updating CryptoMetadataEntity table")
|
||||
realm.schema.get("CryptoMetadataEntity")
|
||||
?.addField(CryptoMetadataEntityFields.X_SIGN_MASTER_PRIVATE_KEY, String::class.java)
|
||||
?.addField(CryptoMetadataEntityFields.X_SIGN_USER_PRIVATE_KEY, String::class.java)
|
||||
?.addField(CryptoMetadataEntityFields.X_SIGN_SELF_SIGNED_PRIVATE_KEY, String::class.java)
|
||||
|
||||
val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build()
|
||||
val listMigrationAdapter = moshi.adapter<List<String>>(Types.newParameterizedType(
|
||||
List::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
val mapMigrationAdapter = moshi.adapter<JsonDict>(Types.newParameterizedType(
|
||||
Map::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
|
||||
realm.schema.get("DeviceInfoEntity")
|
||||
?.addField(DeviceInfoEntityFields.USER_ID, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.ALGORITHM_LIST_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.KEYS_MAP_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.SIGNATURE_MAP_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.UNSIGNED_MAP_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.IS_BLOCKED, Boolean::class.java)
|
||||
?.setNullable(DeviceInfoEntityFields.IS_BLOCKED, true)
|
||||
?.addRealmObjectField(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevelEntityEntitySchema)
|
||||
?.transform { obj ->
|
||||
|
||||
try {
|
||||
val oldSerializedData = obj.getString("deviceInfoData")
|
||||
deserializeFromRealm<MXDeviceInfo>(oldSerializedData)?.let { oldDevice ->
|
||||
|
||||
val trustLevel = realm.createObject("TrustLevelEntity")
|
||||
when (oldDevice.verified) {
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_UNKNOWN -> {
|
||||
obj.setNull(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`)
|
||||
}
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_BLOCKED -> {
|
||||
trustLevel.setNull(TrustLevelEntityFields.LOCALLY_VERIFIED)
|
||||
trustLevel.setNull(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED)
|
||||
obj.setBoolean(DeviceInfoEntityFields.IS_BLOCKED, oldDevice.isBlocked)
|
||||
obj.setObject(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevel)
|
||||
}
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED -> {
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.LOCALLY_VERIFIED, false)
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, false)
|
||||
obj.setObject(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevel)
|
||||
}
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED -> {
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.LOCALLY_VERIFIED, true)
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, false)
|
||||
obj.setObject(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevel)
|
||||
}
|
||||
}
|
||||
|
||||
obj.setString(DeviceInfoEntityFields.USER_ID, oldDevice.userId)
|
||||
obj.setString(DeviceInfoEntityFields.IDENTITY_KEY, oldDevice.identityKey())
|
||||
obj.setString(DeviceInfoEntityFields.ALGORITHM_LIST_JSON, listMigrationAdapter.toJson(oldDevice.algorithms))
|
||||
obj.setString(DeviceInfoEntityFields.KEYS_MAP_JSON, mapMigrationAdapter.toJson(oldDevice.keys))
|
||||
obj.setString(DeviceInfoEntityFields.SIGNATURE_MAP_JSON, mapMigrationAdapter.toJson(oldDevice.signatures))
|
||||
obj.setString(DeviceInfoEntityFields.UNSIGNED_MAP_JSON, mapMigrationAdapter.toJson(oldDevice.unsigned))
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.w(failure, "Crypto Data base migration error")
|
||||
// an unfortunate refactor did modify that class, making deserialization failing
|
||||
// so we just skip and ignore..
|
||||
}
|
||||
}
|
||||
?.removeField("deviceInfoData")
|
||||
}
|
||||
|
||||
private fun migrateTo5(realm: DynamicRealm) {
|
||||
Timber.d("Step 4 -> 5")
|
||||
realm.schema.remove("OutgoingRoomKeyRequestEntity")
|
||||
realm.schema.remove("IncomingRoomKeyRequestEntity")
|
||||
|
||||
// Not need to migrate existing request, just start fresh?
|
||||
|
||||
realm.schema.create("GossipingEventEntity")
|
||||
.addField(GossipingEventEntityFields.TYPE, String::class.java)
|
||||
.addIndex(GossipingEventEntityFields.TYPE)
|
||||
.addField(GossipingEventEntityFields.CONTENT, String::class.java)
|
||||
.addField(GossipingEventEntityFields.SENDER, String::class.java)
|
||||
.addIndex(GossipingEventEntityFields.SENDER)
|
||||
.addField(GossipingEventEntityFields.DECRYPTION_RESULT_JSON, String::class.java)
|
||||
.addField(GossipingEventEntityFields.DECRYPTION_ERROR_CODE, String::class.java)
|
||||
.addField(GossipingEventEntityFields.AGE_LOCAL_TS, Long::class.java)
|
||||
.setNullable(GossipingEventEntityFields.AGE_LOCAL_TS, true)
|
||||
.addField(GossipingEventEntityFields.SEND_STATE_STR, String::class.java)
|
||||
|
||||
realm.schema.create("IncomingGossipingRequestEntity")
|
||||
.addField(IncomingGossipingRequestEntityFields.REQUEST_ID, String::class.java)
|
||||
.addIndex(IncomingGossipingRequestEntityFields.REQUEST_ID)
|
||||
.addField(IncomingGossipingRequestEntityFields.TYPE_STR, String::class.java)
|
||||
.addIndex(IncomingGossipingRequestEntityFields.TYPE_STR)
|
||||
.addField(IncomingGossipingRequestEntityFields.OTHER_USER_ID, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.REQUESTED_INFO_STR, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.OTHER_DEVICE_ID, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.REQUEST_STATE_STR, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, Long::class.java)
|
||||
.setNullable(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, true)
|
||||
|
||||
realm.schema.create("OutgoingGossipingRequestEntity")
|
||||
.addField(OutgoingGossipingRequestEntityFields.REQUEST_ID, String::class.java)
|
||||
.addIndex(OutgoingGossipingRequestEntityFields.REQUEST_ID)
|
||||
.addField(OutgoingGossipingRequestEntityFields.RECIPIENTS_DATA, String::class.java)
|
||||
.addField(OutgoingGossipingRequestEntityFields.REQUESTED_INFO_STR, String::class.java)
|
||||
.addField(OutgoingGossipingRequestEntityFields.TYPE_STR, String::class.java)
|
||||
.addIndex(OutgoingGossipingRequestEntityFields.TYPE_STR)
|
||||
.addField(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, String::class.java)
|
||||
}
|
||||
|
||||
private fun migrateTo6(realm: DynamicRealm) {
|
||||
Timber.d("Step 5 -> 6")
|
||||
Timber.d("Updating CryptoMetadataEntity table")
|
||||
realm.schema.get("CryptoMetadataEntity")
|
||||
?.addField(CryptoMetadataEntityFields.KEY_BACKUP_RECOVERY_KEY, String::class.java)
|
||||
?.addField(CryptoMetadataEntityFields.KEY_BACKUP_RECOVERY_KEY_VERSION, String::class.java)
|
||||
}
|
||||
|
||||
private fun migrateTo7(realm: DynamicRealm) {
|
||||
Timber.d("Step 6 -> 7")
|
||||
Timber.d("Updating KeyInfoEntity table")
|
||||
val crossSigningKeysMapper = CrossSigningKeysMapper(MoshiProvider.providesMoshi())
|
||||
|
||||
val keyInfoEntities = realm.where("KeyInfoEntity").findAll()
|
||||
try {
|
||||
keyInfoEntities.forEach {
|
||||
val stringSignatures = it.getString(KeyInfoEntityFields.SIGNATURES)
|
||||
val objectSignatures: Map<String, Map<String, String>>? = deserializeFromRealm(stringSignatures)
|
||||
val jsonSignatures = crossSigningKeysMapper.serializeSignatures(objectSignatures)
|
||||
it.setString(KeyInfoEntityFields.SIGNATURES, jsonSignatures)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
|
||||
// Migrate frozen classes
|
||||
val inboundGroupSessions = realm.where("OlmInboundGroupSessionEntity").findAll()
|
||||
inboundGroupSessions.forEach { dynamicObject ->
|
||||
dynamicObject.getString(OlmInboundGroupSessionEntityFields.OLM_INBOUND_GROUP_SESSION_DATA)?.let { serializedObject ->
|
||||
try {
|
||||
deserializeFromRealm<OlmInboundGroupSessionWrapper?>(serializedObject)?.let { oldFormat ->
|
||||
val newFormat = oldFormat.exportKeys()?.let {
|
||||
OlmInboundGroupSessionWrapper2(it)
|
||||
}
|
||||
dynamicObject.setString(OlmInboundGroupSessionEntityFields.OLM_INBOUND_GROUP_SESSION_DATA, serializeForRealm(newFormat))
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## OlmInboundGroupSessionEntity migration failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo8(realm: DynamicRealm) {
|
||||
Timber.d("Step 7 -> 8")
|
||||
realm.schema.create("MyDeviceLastSeenInfoEntity")
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.DEVICE_ID, String::class.java)
|
||||
.addPrimaryKey(MyDeviceLastSeenInfoEntityFields.DEVICE_ID)
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.DISPLAY_NAME, String::class.java)
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_IP, String::class.java)
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_TS, Long::class.java)
|
||||
.setNullable(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_TS, true)
|
||||
|
||||
val now = System.currentTimeMillis()
|
||||
realm.schema.get("DeviceInfoEntity")
|
||||
?.addField(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, Long::class.java)
|
||||
?.setNullable(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, true)
|
||||
?.transform { deviceInfoEntity ->
|
||||
tryOrNull {
|
||||
deviceInfoEntity.setLong(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, now)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes duplicate devices in UserEntity#devices
|
||||
private fun migrateTo9(realm: DynamicRealm) {
|
||||
Timber.d("Step 8 -> 9")
|
||||
val userEntities = realm.where("UserEntity").findAll()
|
||||
userEntities.forEach {
|
||||
try {
|
||||
val deviceList = it.getList(UserEntityFields.DEVICES.`$`)
|
||||
?: return@forEach
|
||||
val distinct = deviceList.distinctBy { it.getString(DeviceInfoEntityFields.DEVICE_ID) }
|
||||
if (distinct.size != deviceList.size) {
|
||||
deviceList.clear()
|
||||
deviceList.addAll(distinct)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.w(failure, "Crypto Data base migration error for migrateTo9")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Version 10L added WithHeld Keys Info (MSC2399)
|
||||
private fun migrateTo10(realm: DynamicRealm) {
|
||||
Timber.d("Step 9 -> 10")
|
||||
realm.schema.create("WithHeldSessionEntity")
|
||||
.addField(WithHeldSessionEntityFields.ROOM_ID, String::class.java)
|
||||
.addField(WithHeldSessionEntityFields.ALGORITHM, String::class.java)
|
||||
.addField(WithHeldSessionEntityFields.SESSION_ID, String::class.java)
|
||||
.addIndex(WithHeldSessionEntityFields.SESSION_ID)
|
||||
.addField(WithHeldSessionEntityFields.SENDER_KEY, String::class.java)
|
||||
.addIndex(WithHeldSessionEntityFields.SENDER_KEY)
|
||||
.addField(WithHeldSessionEntityFields.CODE_STRING, String::class.java)
|
||||
.addField(WithHeldSessionEntityFields.REASON, String::class.java)
|
||||
|
||||
realm.schema.create("SharedSessionEntity")
|
||||
.addField(SharedSessionEntityFields.ROOM_ID, String::class.java)
|
||||
.addField(SharedSessionEntityFields.ALGORITHM, String::class.java)
|
||||
.addField(SharedSessionEntityFields.SESSION_ID, String::class.java)
|
||||
.addIndex(SharedSessionEntityFields.SESSION_ID)
|
||||
.addField(SharedSessionEntityFields.USER_ID, String::class.java)
|
||||
.addIndex(SharedSessionEntityFields.USER_ID)
|
||||
.addField(SharedSessionEntityFields.DEVICE_ID, String::class.java)
|
||||
.addIndex(SharedSessionEntityFields.DEVICE_ID)
|
||||
.addField(SharedSessionEntityFields.CHAIN_INDEX, Long::class.java)
|
||||
.setNullable(SharedSessionEntityFields.CHAIN_INDEX, true)
|
||||
}
|
||||
|
||||
// Version 11L added deviceKeysSentToServer boolean to CryptoMetadataEntity
|
||||
private fun migrateTo11(realm: DynamicRealm) {
|
||||
Timber.d("Step 10 -> 11")
|
||||
realm.schema.get("CryptoMetadataEntity")
|
||||
?.addField(CryptoMetadataEntityFields.DEVICE_KEYS_SENT_TO_SERVER, Boolean::class.java)
|
||||
}
|
||||
|
||||
// Version 12L added outbound group session persistence
|
||||
private fun migrateTo12(realm: DynamicRealm) {
|
||||
Timber.d("Step 11 -> 12")
|
||||
val outboundEntitySchema = realm.schema.create("OutboundGroupSessionInfoEntity")
|
||||
.addField(OutboundGroupSessionInfoEntityFields.SERIALIZED_OUTBOUND_SESSION_DATA, String::class.java)
|
||||
.addField(OutboundGroupSessionInfoEntityFields.CREATION_TIME, Long::class.java)
|
||||
.setNullable(OutboundGroupSessionInfoEntityFields.CREATION_TIME, true)
|
||||
|
||||
realm.schema.get("CryptoRoomEntity")
|
||||
?.addRealmObjectField(CryptoRoomEntityFields.OUTBOUND_SESSION_INFO.`$`, outboundEntitySchema)
|
||||
}
|
||||
|
||||
// Version 13L delete unreferenced TrustLevelEntity
|
||||
private fun migrateTo13(realm: DynamicRealm) {
|
||||
Timber.d("Step 12 -> 13")
|
||||
|
||||
// Use a trick to do that... Ref: https://stackoverflow.com/questions/55221366
|
||||
val trustLevelEntitySchema = realm.schema.get("TrustLevelEntity")
|
||||
|
||||
/*
|
||||
Creating a new temp field called isLinked which is set to true for those which are
|
||||
references by other objects. Rest of them are set to false. Then removing all
|
||||
those which are false and hence duplicate and unnecessary. Then removing the temp field
|
||||
isLinked
|
||||
*/
|
||||
var mainCounter = 0
|
||||
var deviceInfoCounter = 0
|
||||
var keyInfoCounter = 0
|
||||
val deleteCounter: Int
|
||||
|
||||
trustLevelEntitySchema
|
||||
?.addField("isLinked", Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
// Setting to false for all by default
|
||||
obj.set("isLinked", false)
|
||||
mainCounter++
|
||||
}
|
||||
|
||||
realm.schema.get("DeviceInfoEntity")?.transform { obj ->
|
||||
// Setting to true for those which are referenced in DeviceInfoEntity
|
||||
deviceInfoCounter++
|
||||
obj.getObject("trustLevelEntity")?.set("isLinked", true)
|
||||
}
|
||||
|
||||
realm.schema.get("KeyInfoEntity")?.transform { obj ->
|
||||
// Setting to true for those which are referenced in KeyInfoEntity
|
||||
keyInfoCounter++
|
||||
obj.getObject("trustLevelEntity")?.set("isLinked", true)
|
||||
}
|
||||
|
||||
// Removing all those which are set as false
|
||||
realm.where("TrustLevelEntity")
|
||||
.equalTo("isLinked", false)
|
||||
.findAll()
|
||||
.also { deleteCounter = it.size }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
trustLevelEntitySchema?.removeField("isLinked")
|
||||
|
||||
Timber.w("TrustLevelEntity cleanup: $mainCounter entities")
|
||||
Timber.w("TrustLevelEntity cleanup: $deviceInfoCounter entities referenced in DeviceInfoEntities")
|
||||
Timber.w("TrustLevelEntity cleanup: $keyInfoCounter entities referenced in KeyInfoEntity")
|
||||
Timber.w("TrustLevelEntity cleanup: $deleteCounter entities deleted!")
|
||||
if (mainCounter != deviceInfoCounter + keyInfoCounter + deleteCounter) {
|
||||
Timber.e("TrustLevelEntity cleanup: Something is not correct...")
|
||||
}
|
||||
}
|
||||
|
||||
// Version 14L Update the way we remember key sharing
|
||||
private fun migrateTo14(realm: DynamicRealm) {
|
||||
Timber.d("Step 13 -> 14")
|
||||
realm.schema.get("SharedSessionEntity")
|
||||
?.addField(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, String::class.java)
|
||||
?.addIndex(SharedSessionEntityFields.DEVICE_IDENTITY_KEY)
|
||||
?.transform {
|
||||
val sharedUserId = it.getString(SharedSessionEntityFields.USER_ID)
|
||||
val sharedDeviceId = it.getString(SharedSessionEntityFields.DEVICE_ID)
|
||||
val knownDevice = realm.where("DeviceInfoEntity")
|
||||
.equalTo(DeviceInfoEntityFields.USER_ID, sharedUserId)
|
||||
.equalTo(DeviceInfoEntityFields.DEVICE_ID, sharedDeviceId)
|
||||
.findFirst()
|
||||
it.setString(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, knownDevice?.getString(DeviceInfoEntityFields.IDENTITY_KEY))
|
||||
}
|
||||
if (oldVersion < 1) MigrateCryptoTo001Legacy(realm).perform()
|
||||
if (oldVersion < 2) MigrateCryptoTo002Legacy(realm).perform()
|
||||
if (oldVersion < 3) MigrateCryptoTo003RiotX(realm).perform()
|
||||
if (oldVersion < 4) MigrateCryptoTo004(realm).perform()
|
||||
if (oldVersion < 5) MigrateCryptoTo005(realm).perform()
|
||||
if (oldVersion < 6) MigrateCryptoTo006(realm).perform()
|
||||
if (oldVersion < 7) MigrateCryptoTo007(realm).perform()
|
||||
if (oldVersion < 8) MigrateCryptoTo008(realm).perform()
|
||||
if (oldVersion < 9) MigrateCryptoTo009(realm).perform()
|
||||
if (oldVersion < 10) MigrateCryptoTo010(realm).perform()
|
||||
if (oldVersion < 11) MigrateCryptoTo011(realm).perform()
|
||||
if (oldVersion < 12) MigrateCryptoTo012(realm).perform()
|
||||
if (oldVersion < 13) MigrateCryptoTo013(realm).perform()
|
||||
if (oldVersion < 14) MigrateCryptoTo014(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateCryptoTo001Legacy(realm: DynamicRealm) : RealmMigrator(realm, 1) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
Timber.d("Add field lastReceivedMessageTs (Long) and set the value to 0")
|
||||
|
||||
realm.schema.get("OlmSessionEntity")
|
||||
?.addField(OlmSessionEntityFields.LAST_RECEIVED_MESSAGE_TS, Long::class.java)
|
||||
?.transform {
|
||||
it.setLong(OlmSessionEntityFields.LAST_RECEIVED_MESSAGE_TS, 0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateCryptoTo002Legacy(realm: DynamicRealm) : RealmMigrator(realm, 2) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
Timber.d("Update IncomingRoomKeyRequestEntity format: requestBodyString field is exploded into several fields")
|
||||
realm.schema.get("IncomingRoomKeyRequestEntity")
|
||||
?.addFieldIfNotExists("requestBodyAlgorithm", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodyRoomId", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySenderKey", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySessionId", String::class.java)
|
||||
?.transform { dynamicObject ->
|
||||
try {
|
||||
val requestBodyString = dynamicObject.getString("requestBodyString")
|
||||
// It was a map before
|
||||
val map: Map<String, String>? = deserializeFromRealm(requestBodyString)
|
||||
|
||||
map?.let {
|
||||
dynamicObject.setString("requestBodyAlgorithm", it["algorithm"])
|
||||
dynamicObject.setString("requestBodyRoomId", it["room_id"])
|
||||
dynamicObject.setString("requestBodySenderKey", it["sender_key"])
|
||||
dynamicObject.setString("requestBodySessionId", it["session_id"])
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
?.removeFieldIfExists("requestBodyString")
|
||||
|
||||
Timber.d("Update IncomingRoomKeyRequestEntity format: requestBodyString field is exploded into several fields")
|
||||
realm.schema.get("OutgoingRoomKeyRequestEntity")
|
||||
?.addFieldIfNotExists("requestBodyAlgorithm", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodyRoomId", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySenderKey", String::class.java)
|
||||
?.addFieldIfNotExists("requestBodySessionId", String::class.java)
|
||||
?.transform { dynamicObject ->
|
||||
try {
|
||||
val requestBodyString = dynamicObject.getString("requestBodyString")
|
||||
// It was a map before
|
||||
val map: Map<String, String>? = deserializeFromRealm(requestBodyString)
|
||||
|
||||
map?.let {
|
||||
dynamicObject.setString("requestBodyAlgorithm", it["algorithm"])
|
||||
dynamicObject.setString("requestBodyRoomId", it["room_id"])
|
||||
dynamicObject.setString("requestBodySenderKey", it["sender_key"])
|
||||
dynamicObject.setString("requestBodySessionId", it["session_id"])
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
?.removeFieldIfExists("requestBodyString")
|
||||
|
||||
Timber.d("Create KeysBackupDataEntity")
|
||||
if (!realm.schema.contains("KeysBackupDataEntity")) {
|
||||
realm.schema.create("KeysBackupDataEntity")
|
||||
.addField(KeysBackupDataEntityFields.PRIMARY_KEY, Integer::class.java)
|
||||
.addPrimaryKey(KeysBackupDataEntityFields.PRIMARY_KEY)
|
||||
.setRequired(KeysBackupDataEntityFields.PRIMARY_KEY, true)
|
||||
.addField(KeysBackupDataEntityFields.BACKUP_LAST_SERVER_HASH, String::class.java)
|
||||
.addField(KeysBackupDataEntityFields.BACKUP_LAST_SERVER_NUMBER_OF_KEYS, Integer::class.java)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import org.matrix.androidsdk.crypto.data.MXDeviceInfo
|
||||
import org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateCryptoTo003RiotX(realm: DynamicRealm) : RealmMigrator(realm, 3) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
Timber.d("Migrate to RiotX model")
|
||||
realm.schema.get("CryptoRoomEntity")
|
||||
?.addFieldIfNotExists(CryptoRoomEntityFields.SHOULD_ENCRYPT_FOR_INVITED_MEMBERS, Boolean::class.java)
|
||||
?.setRequiredIfNotAlready(CryptoRoomEntityFields.SHOULD_ENCRYPT_FOR_INVITED_MEMBERS, false)
|
||||
|
||||
// Convert format of MXDeviceInfo, package has to be the same.
|
||||
realm.schema.get("DeviceInfoEntity")
|
||||
?.transform { obj ->
|
||||
try {
|
||||
val oldSerializedData = obj.getString("deviceInfoData")
|
||||
deserializeFromRealm<MXDeviceInfo>(oldSerializedData)?.let { legacyMxDeviceInfo ->
|
||||
val newMxDeviceInfo = org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo(
|
||||
deviceId = legacyMxDeviceInfo.deviceId,
|
||||
userId = legacyMxDeviceInfo.userId,
|
||||
algorithms = legacyMxDeviceInfo.algorithms,
|
||||
keys = legacyMxDeviceInfo.keys,
|
||||
signatures = legacyMxDeviceInfo.signatures,
|
||||
unsigned = legacyMxDeviceInfo.unsigned,
|
||||
verified = legacyMxDeviceInfo.mVerified
|
||||
)
|
||||
|
||||
obj.setString("deviceInfoData", serializeForRealm(newMxDeviceInfo))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
|
||||
// Convert MXOlmInboundGroupSession2 to OlmInboundGroupSessionWrapper
|
||||
realm.schema.get("OlmInboundGroupSessionEntity")
|
||||
?.transform { obj ->
|
||||
try {
|
||||
val oldSerializedData = obj.getString("olmInboundGroupSessionData")
|
||||
deserializeFromRealm<MXOlmInboundGroupSession2>(oldSerializedData)?.let { mxOlmInboundGroupSession2 ->
|
||||
val sessionKey = mxOlmInboundGroupSession2.mSession.sessionIdentifier()
|
||||
val newOlmInboundGroupSessionWrapper = OlmInboundGroupSessionWrapper(sessionKey, false)
|
||||
.apply {
|
||||
olmInboundGroupSession = mxOlmInboundGroupSession2.mSession
|
||||
roomId = mxOlmInboundGroupSession2.mRoomId
|
||||
senderKey = mxOlmInboundGroupSession2.mSenderKey
|
||||
keysClaimed = mxOlmInboundGroupSession2.mKeysClaimed
|
||||
forwardingCurve25519KeyChain = mxOlmInboundGroupSession2.mForwardingCurve25519KeyChain
|
||||
}
|
||||
|
||||
obj.setString("olmInboundGroupSessionData", serializeForRealm(newOlmInboundGroupSessionWrapper))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.KeyInfoEntityFields
|
||||
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.di.SerializeNulls
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
// Version 4L added Cross Signing info persistence
|
||||
class MigrateCryptoTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
if (realm.schema.contains("TrustLevelEntity")) {
|
||||
Timber.d("Skipping Step 3 -> 4 because entities already exist")
|
||||
return
|
||||
}
|
||||
|
||||
Timber.d("Create KeyInfoEntity")
|
||||
val trustLevelEntityEntitySchema = realm.schema.create("TrustLevelEntity")
|
||||
.addField(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, Boolean::class.java)
|
||||
.setNullable(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, true)
|
||||
.addField(TrustLevelEntityFields.LOCALLY_VERIFIED, Boolean::class.java)
|
||||
.setNullable(TrustLevelEntityFields.LOCALLY_VERIFIED, true)
|
||||
|
||||
val keyInfoEntitySchema = realm.schema.create("KeyInfoEntity")
|
||||
.addField(KeyInfoEntityFields.PUBLIC_KEY_BASE64, String::class.java)
|
||||
.addField(KeyInfoEntityFields.SIGNATURES, String::class.java)
|
||||
.addRealmListField(KeyInfoEntityFields.USAGES.`$`, String::class.java)
|
||||
.addRealmObjectField(KeyInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevelEntityEntitySchema)
|
||||
|
||||
Timber.d("Create CrossSigningInfoEntity")
|
||||
|
||||
val crossSigningInfoSchema = realm.schema.create("CrossSigningInfoEntity")
|
||||
.addField(CrossSigningInfoEntityFields.USER_ID, String::class.java)
|
||||
.addPrimaryKey(CrossSigningInfoEntityFields.USER_ID)
|
||||
.addRealmListField(CrossSigningInfoEntityFields.CROSS_SIGNING_KEYS.`$`, keyInfoEntitySchema)
|
||||
|
||||
Timber.d("Updating UserEntity table")
|
||||
realm.schema.get("UserEntity")
|
||||
?.addRealmObjectField(UserEntityFields.CROSS_SIGNING_INFO_ENTITY.`$`, crossSigningInfoSchema)
|
||||
|
||||
Timber.d("Updating CryptoMetadataEntity table")
|
||||
realm.schema.get("CryptoMetadataEntity")
|
||||
?.addField(CryptoMetadataEntityFields.X_SIGN_MASTER_PRIVATE_KEY, String::class.java)
|
||||
?.addField(CryptoMetadataEntityFields.X_SIGN_USER_PRIVATE_KEY, String::class.java)
|
||||
?.addField(CryptoMetadataEntityFields.X_SIGN_SELF_SIGNED_PRIVATE_KEY, String::class.java)
|
||||
|
||||
val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build()
|
||||
val listMigrationAdapter = moshi.adapter<List<String>>(Types.newParameterizedType(
|
||||
List::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
val mapMigrationAdapter = moshi.adapter<JsonDict>(Types.newParameterizedType(
|
||||
Map::class.java,
|
||||
String::class.java,
|
||||
Any::class.java
|
||||
))
|
||||
|
||||
realm.schema.get("DeviceInfoEntity")
|
||||
?.addField(DeviceInfoEntityFields.USER_ID, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.ALGORITHM_LIST_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.KEYS_MAP_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.SIGNATURE_MAP_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.UNSIGNED_MAP_JSON, String::class.java)
|
||||
?.addField(DeviceInfoEntityFields.IS_BLOCKED, Boolean::class.java)
|
||||
?.setNullable(DeviceInfoEntityFields.IS_BLOCKED, true)
|
||||
?.addRealmObjectField(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevelEntityEntitySchema)
|
||||
?.transform { obj ->
|
||||
|
||||
try {
|
||||
val oldSerializedData = obj.getString("deviceInfoData")
|
||||
deserializeFromRealm<MXDeviceInfo>(oldSerializedData)?.let { oldDevice ->
|
||||
|
||||
val trustLevel = realm.createObject("TrustLevelEntity")
|
||||
when (oldDevice.verified) {
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_UNKNOWN -> {
|
||||
obj.setNull(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`)
|
||||
}
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_BLOCKED -> {
|
||||
trustLevel.setNull(TrustLevelEntityFields.LOCALLY_VERIFIED)
|
||||
trustLevel.setNull(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED)
|
||||
obj.setBoolean(DeviceInfoEntityFields.IS_BLOCKED, oldDevice.isBlocked)
|
||||
obj.setObject(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevel)
|
||||
}
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED -> {
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.LOCALLY_VERIFIED, false)
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, false)
|
||||
obj.setObject(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevel)
|
||||
}
|
||||
MXDeviceInfo.DEVICE_VERIFICATION_VERIFIED -> {
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.LOCALLY_VERIFIED, true)
|
||||
trustLevel.setBoolean(TrustLevelEntityFields.CROSS_SIGNED_VERIFIED, false)
|
||||
obj.setObject(DeviceInfoEntityFields.TRUST_LEVEL_ENTITY.`$`, trustLevel)
|
||||
}
|
||||
}
|
||||
|
||||
obj.setString(DeviceInfoEntityFields.USER_ID, oldDevice.userId)
|
||||
obj.setString(DeviceInfoEntityFields.IDENTITY_KEY, oldDevice.identityKey())
|
||||
obj.setString(DeviceInfoEntityFields.ALGORITHM_LIST_JSON, listMigrationAdapter.toJson(oldDevice.algorithms))
|
||||
obj.setString(DeviceInfoEntityFields.KEYS_MAP_JSON, mapMigrationAdapter.toJson(oldDevice.keys))
|
||||
obj.setString(DeviceInfoEntityFields.SIGNATURE_MAP_JSON, mapMigrationAdapter.toJson(oldDevice.signatures))
|
||||
obj.setString(DeviceInfoEntityFields.UNSIGNED_MAP_JSON, mapMigrationAdapter.toJson(oldDevice.unsigned))
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.w(failure, "Crypto Data base migration error")
|
||||
// an unfortunate refactor did modify that class, making deserialization failing
|
||||
// so we just skip and ignore..
|
||||
}
|
||||
}
|
||||
?.removeField("deviceInfoData")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.GossipingEventEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRequestEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateCryptoTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.remove("OutgoingRoomKeyRequestEntity")
|
||||
realm.schema.remove("IncomingRoomKeyRequestEntity")
|
||||
|
||||
// Not need to migrate existing request, just start fresh?
|
||||
|
||||
realm.schema.create("GossipingEventEntity")
|
||||
.addField(GossipingEventEntityFields.TYPE, String::class.java)
|
||||
.addIndex(GossipingEventEntityFields.TYPE)
|
||||
.addField(GossipingEventEntityFields.CONTENT, String::class.java)
|
||||
.addField(GossipingEventEntityFields.SENDER, String::class.java)
|
||||
.addIndex(GossipingEventEntityFields.SENDER)
|
||||
.addField(GossipingEventEntityFields.DECRYPTION_RESULT_JSON, String::class.java)
|
||||
.addField(GossipingEventEntityFields.DECRYPTION_ERROR_CODE, String::class.java)
|
||||
.addField(GossipingEventEntityFields.AGE_LOCAL_TS, Long::class.java)
|
||||
.setNullable(GossipingEventEntityFields.AGE_LOCAL_TS, true)
|
||||
.addField(GossipingEventEntityFields.SEND_STATE_STR, String::class.java)
|
||||
|
||||
realm.schema.create("IncomingGossipingRequestEntity")
|
||||
.addField(IncomingGossipingRequestEntityFields.REQUEST_ID, String::class.java)
|
||||
.addIndex(IncomingGossipingRequestEntityFields.REQUEST_ID)
|
||||
.addField(IncomingGossipingRequestEntityFields.TYPE_STR, String::class.java)
|
||||
.addIndex(IncomingGossipingRequestEntityFields.TYPE_STR)
|
||||
.addField(IncomingGossipingRequestEntityFields.OTHER_USER_ID, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.REQUESTED_INFO_STR, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.OTHER_DEVICE_ID, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.REQUEST_STATE_STR, String::class.java)
|
||||
.addField(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, Long::class.java)
|
||||
.setNullable(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, true)
|
||||
|
||||
realm.schema.create("OutgoingGossipingRequestEntity")
|
||||
.addField(OutgoingGossipingRequestEntityFields.REQUEST_ID, String::class.java)
|
||||
.addIndex(OutgoingGossipingRequestEntityFields.REQUEST_ID)
|
||||
.addField(OutgoingGossipingRequestEntityFields.RECIPIENTS_DATA, String::class.java)
|
||||
.addField(OutgoingGossipingRequestEntityFields.REQUESTED_INFO_STR, String::class.java)
|
||||
.addField(OutgoingGossipingRequestEntityFields.TYPE_STR, String::class.java)
|
||||
.addIndex(OutgoingGossipingRequestEntityFields.TYPE_STR)
|
||||
.addField(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, String::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateCryptoTo006(realm: DynamicRealm) : RealmMigrator(realm, 6) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
Timber.d("Updating CryptoMetadataEntity table")
|
||||
realm.schema.get("CryptoMetadataEntity")
|
||||
?.addField(CryptoMetadataEntityFields.KEY_BACKUP_RECOVERY_KEY, String::class.java)
|
||||
?.addField(CryptoMetadataEntityFields.KEY_BACKUP_RECOVERY_KEY_VERSION, String::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper
|
||||
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.KeyInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.OlmInboundGroupSessionEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateCryptoTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
Timber.d("Updating KeyInfoEntity table")
|
||||
val crossSigningKeysMapper = CrossSigningKeysMapper(MoshiProvider.providesMoshi())
|
||||
|
||||
val keyInfoEntities = realm.where("KeyInfoEntity").findAll()
|
||||
try {
|
||||
keyInfoEntities.forEach {
|
||||
val stringSignatures = it.getString(KeyInfoEntityFields.SIGNATURES)
|
||||
val objectSignatures: Map<String, Map<String, String>>? = deserializeFromRealm(stringSignatures)
|
||||
val jsonSignatures = crossSigningKeysMapper.serializeSignatures(objectSignatures)
|
||||
it.setString(KeyInfoEntityFields.SIGNATURES, jsonSignatures)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
|
||||
// Migrate frozen classes
|
||||
val inboundGroupSessions = realm.where("OlmInboundGroupSessionEntity").findAll()
|
||||
inboundGroupSessions.forEach { dynamicObject ->
|
||||
dynamicObject.getString(OlmInboundGroupSessionEntityFields.OLM_INBOUND_GROUP_SESSION_DATA)?.let { serializedObject ->
|
||||
try {
|
||||
deserializeFromRealm<OlmInboundGroupSessionWrapper?>(serializedObject)?.let { oldFormat ->
|
||||
val newFormat = oldFormat.exportKeys()?.let {
|
||||
OlmInboundGroupSessionWrapper2(it)
|
||||
}
|
||||
dynamicObject.setString(OlmInboundGroupSessionEntityFields.OLM_INBOUND_GROUP_SESSION_DATA, serializeForRealm(newFormat))
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## OlmInboundGroupSessionEntity migration failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateCryptoTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("MyDeviceLastSeenInfoEntity")
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.DEVICE_ID, String::class.java)
|
||||
.addPrimaryKey(MyDeviceLastSeenInfoEntityFields.DEVICE_ID)
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.DISPLAY_NAME, String::class.java)
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_IP, String::class.java)
|
||||
.addField(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_TS, Long::class.java)
|
||||
.setNullable(MyDeviceLastSeenInfoEntityFields.LAST_SEEN_TS, true)
|
||||
|
||||
val now = System.currentTimeMillis()
|
||||
realm.schema.get("DeviceInfoEntity")
|
||||
?.addField(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, Long::class.java)
|
||||
?.setNullable(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, true)
|
||||
?.transform { deviceInfoEntity ->
|
||||
tryOrNull {
|
||||
deviceInfoEntity.setLong(DeviceInfoEntityFields.FIRST_TIME_SEEN_LOCAL_TS, now)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
// Fixes duplicate devices in UserEntity#devices
|
||||
class MigrateCryptoTo009(realm: DynamicRealm) : RealmMigrator(realm, 9) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val userEntities = realm.where("UserEntity").findAll()
|
||||
userEntities.forEach {
|
||||
try {
|
||||
val deviceList = it.getList(UserEntityFields.DEVICES.`$`)
|
||||
?: return@forEach
|
||||
val distinct = deviceList.distinctBy { it.getString(DeviceInfoEntityFields.DEVICE_ID) }
|
||||
if (distinct.size != deviceList.size) {
|
||||
deviceList.clear()
|
||||
deviceList.addAll(distinct)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.w(failure, "Crypto Data base migration error for migrateTo9")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
// Version 10L added WithHeld Keys Info (MSC2399)
|
||||
class MigrateCryptoTo010(realm: DynamicRealm) : RealmMigrator(realm, 10) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("WithHeldSessionEntity")
|
||||
.addField(WithHeldSessionEntityFields.ROOM_ID, String::class.java)
|
||||
.addField(WithHeldSessionEntityFields.ALGORITHM, String::class.java)
|
||||
.addField(WithHeldSessionEntityFields.SESSION_ID, String::class.java)
|
||||
.addIndex(WithHeldSessionEntityFields.SESSION_ID)
|
||||
.addField(WithHeldSessionEntityFields.SENDER_KEY, String::class.java)
|
||||
.addIndex(WithHeldSessionEntityFields.SENDER_KEY)
|
||||
.addField(WithHeldSessionEntityFields.CODE_STRING, String::class.java)
|
||||
.addField(WithHeldSessionEntityFields.REASON, String::class.java)
|
||||
|
||||
realm.schema.create("SharedSessionEntity")
|
||||
.addField(SharedSessionEntityFields.ROOM_ID, String::class.java)
|
||||
.addField(SharedSessionEntityFields.ALGORITHM, String::class.java)
|
||||
.addField(SharedSessionEntityFields.SESSION_ID, String::class.java)
|
||||
.addIndex(SharedSessionEntityFields.SESSION_ID)
|
||||
.addField(SharedSessionEntityFields.USER_ID, String::class.java)
|
||||
.addIndex(SharedSessionEntityFields.USER_ID)
|
||||
.addField(SharedSessionEntityFields.DEVICE_ID, String::class.java)
|
||||
.addIndex(SharedSessionEntityFields.DEVICE_ID)
|
||||
.addField(SharedSessionEntityFields.CHAIN_INDEX, Long::class.java)
|
||||
.setNullable(SharedSessionEntityFields.CHAIN_INDEX, true)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
// Version 11L added deviceKeysSentToServer boolean to CryptoMetadataEntity
|
||||
class MigrateCryptoTo011(realm: DynamicRealm) : RealmMigrator(realm, 11) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("CryptoMetadataEntity")
|
||||
?.addField(CryptoMetadataEntityFields.DEVICE_KEYS_SENT_TO_SERVER, Boolean::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessionInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
// Version 12L added outbound group session persistence
|
||||
class MigrateCryptoTo012(realm: DynamicRealm) : RealmMigrator(realm, 12) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val outboundEntitySchema = realm.schema.create("OutboundGroupSessionInfoEntity")
|
||||
.addField(OutboundGroupSessionInfoEntityFields.SERIALIZED_OUTBOUND_SESSION_DATA, String::class.java)
|
||||
.addField(OutboundGroupSessionInfoEntityFields.CREATION_TIME, Long::class.java)
|
||||
.setNullable(OutboundGroupSessionInfoEntityFields.CREATION_TIME, true)
|
||||
|
||||
realm.schema.get("CryptoRoomEntity")
|
||||
?.addRealmObjectField(CryptoRoomEntityFields.OUTBOUND_SESSION_INFO.`$`, outboundEntitySchema)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
// Version 13L delete unreferenced TrustLevelEntity
|
||||
class MigrateCryptoTo013(realm: DynamicRealm) : RealmMigrator(realm, 13) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
// Use a trick to do that... Ref: https://stackoverflow.com/questions/55221366
|
||||
val trustLevelEntitySchema = realm.schema.get("TrustLevelEntity")
|
||||
|
||||
/*
|
||||
Creating a new temp field called isLinked which is set to true for those which are
|
||||
references by other objects. Rest of them are set to false. Then removing all
|
||||
those which are false and hence duplicate and unnecessary. Then removing the temp field
|
||||
isLinked
|
||||
*/
|
||||
var mainCounter = 0
|
||||
var deviceInfoCounter = 0
|
||||
var keyInfoCounter = 0
|
||||
val deleteCounter: Int
|
||||
|
||||
trustLevelEntitySchema
|
||||
?.addField("isLinked", Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
// Setting to false for all by default
|
||||
obj.set("isLinked", false)
|
||||
mainCounter++
|
||||
}
|
||||
|
||||
realm.schema.get("DeviceInfoEntity")?.transform { obj ->
|
||||
// Setting to true for those which are referenced in DeviceInfoEntity
|
||||
deviceInfoCounter++
|
||||
obj.getObject("trustLevelEntity")?.set("isLinked", true)
|
||||
}
|
||||
|
||||
realm.schema.get("KeyInfoEntity")?.transform { obj ->
|
||||
// Setting to true for those which are referenced in KeyInfoEntity
|
||||
keyInfoCounter++
|
||||
obj.getObject("trustLevelEntity")?.set("isLinked", true)
|
||||
}
|
||||
|
||||
// Removing all those which are set as false
|
||||
realm.where("TrustLevelEntity")
|
||||
.equalTo("isLinked", false)
|
||||
.findAll()
|
||||
.also { deleteCounter = it.size }
|
||||
.deleteAllFromRealm()
|
||||
|
||||
trustLevelEntitySchema?.removeField("isLinked")
|
||||
|
||||
Timber.w("TrustLevelEntity cleanup: $mainCounter entities")
|
||||
Timber.w("TrustLevelEntity cleanup: $deviceInfoCounter entities referenced in DeviceInfoEntities")
|
||||
Timber.w("TrustLevelEntity cleanup: $keyInfoCounter entities referenced in KeyInfoEntity")
|
||||
Timber.w("TrustLevelEntity cleanup: $deleteCounter entities deleted!")
|
||||
if (mainCounter != deviceInfoCounter + keyInfoCounter + deleteCounter) {
|
||||
Timber.e("TrustLevelEntity cleanup: Something is not correct...")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFields
|
||||
import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
// Version 14L Update the way we remember key sharing
|
||||
class MigrateCryptoTo014(realm: DynamicRealm) : RealmMigrator(realm, 14) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("SharedSessionEntity")
|
||||
?.addField(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, String::class.java)
|
||||
?.addIndex(SharedSessionEntityFields.DEVICE_IDENTITY_KEY)
|
||||
?.transform {
|
||||
val sharedUserId = it.getString(SharedSessionEntityFields.USER_ID)
|
||||
val sharedDeviceId = it.getString(SharedSessionEntityFields.DEVICE_ID)
|
||||
val knownDevice = realm.where("DeviceInfoEntity")
|
||||
.equalTo(DeviceInfoEntityFields.USER_ID, sharedUserId)
|
||||
.equalTo(DeviceInfoEntityFields.DEVICE_ID, sharedDeviceId)
|
||||
.findFirst()
|
||||
it.setString(SharedSessionEntityFields.DEVICE_IDENTITY_KEY, knownDevice?.getString(DeviceInfoEntityFields.IDENTITY_KEY))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,37 +17,31 @@
|
|||
package org.matrix.android.sdk.internal.database
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.FieldAttribute
|
||||
import io.realm.RealmMigration
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||
import org.matrix.android.sdk.api.session.room.model.VersioningState
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
|
||||
import org.matrix.android.sdk.api.session.threads.ThreadNotificationState
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
|
||||
import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EditAggregatedSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EditionOfEventFields
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomTagEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceParentSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.query.process
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo001
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo002
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo003
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo004
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo005
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo006
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo007
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo008
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo009
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo010
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo011
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo012
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo013
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo014
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo015
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo016
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo017
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo018
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo019
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo020
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo021
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo022
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo023
|
||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo024
|
||||
import org.matrix.android.sdk.internal.util.Normalizer
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
@ -70,423 +64,29 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
|
||||
|
||||
if (oldVersion <= 0) migrateTo1(realm)
|
||||
if (oldVersion <= 1) migrateTo2(realm)
|
||||
if (oldVersion <= 2) migrateTo3(realm)
|
||||
if (oldVersion <= 3) migrateTo4(realm)
|
||||
if (oldVersion <= 4) migrateTo5(realm)
|
||||
if (oldVersion <= 5) migrateTo6(realm)
|
||||
if (oldVersion <= 6) migrateTo7(realm)
|
||||
if (oldVersion <= 7) migrateTo8(realm)
|
||||
if (oldVersion <= 8) migrateTo9(realm)
|
||||
if (oldVersion <= 9) migrateTo10(realm)
|
||||
if (oldVersion <= 10) migrateTo11(realm)
|
||||
if (oldVersion <= 11) migrateTo12(realm)
|
||||
if (oldVersion <= 12) migrateTo13(realm)
|
||||
if (oldVersion <= 13) migrateTo14(realm)
|
||||
if (oldVersion <= 14) migrateTo15(realm)
|
||||
if (oldVersion <= 15) migrateTo16(realm)
|
||||
if (oldVersion <= 16) migrateTo17(realm)
|
||||
if (oldVersion <= 17) migrateTo18(realm)
|
||||
if (oldVersion <= 18) migrateTo19(realm)
|
||||
if (oldVersion <= 19) migrateTo20(realm)
|
||||
if (oldVersion <= 20) migrateTo21(realm)
|
||||
if (oldVersion <= 21) migrateTo22(realm)
|
||||
if (oldVersion <= 22) migrateTo23(realm)
|
||||
if (oldVersion <= 23) migrateTo24(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
Timber.d("Step 0 -> 1")
|
||||
// Add hasFailedSending in RoomSummary and a small warning icon on room list
|
||||
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.HAS_FAILED_SENDING, Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
obj.setBoolean(RoomSummaryEntityFields.HAS_FAILED_SENDING, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo2(realm: DynamicRealm) {
|
||||
Timber.d("Step 1 -> 2")
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField("adminE2EByDefault", Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
obj.setBoolean("adminE2EByDefault", true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo3(realm: DynamicRealm) {
|
||||
Timber.d("Step 2 -> 3")
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField("preferredJitsiDomain", String::class.java)
|
||||
?.transform { obj ->
|
||||
// Schedule a refresh of the capabilities
|
||||
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo4(realm: DynamicRealm) {
|
||||
Timber.d("Step 3 -> 4")
|
||||
realm.schema.create("PendingThreePidEntity")
|
||||
.addField(PendingThreePidEntityFields.CLIENT_SECRET, String::class.java)
|
||||
.setRequired(PendingThreePidEntityFields.CLIENT_SECRET, true)
|
||||
.addField(PendingThreePidEntityFields.EMAIL, String::class.java)
|
||||
.addField(PendingThreePidEntityFields.MSISDN, String::class.java)
|
||||
.addField(PendingThreePidEntityFields.SEND_ATTEMPT, Int::class.java)
|
||||
.addField(PendingThreePidEntityFields.SID, String::class.java)
|
||||
.setRequired(PendingThreePidEntityFields.SID, true)
|
||||
.addField(PendingThreePidEntityFields.SUBMIT_URL, String::class.java)
|
||||
}
|
||||
|
||||
private fun migrateTo5(realm: DynamicRealm) {
|
||||
Timber.d("Step 4 -> 5")
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.removeField("adminE2EByDefault")
|
||||
?.removeField("preferredJitsiDomain")
|
||||
}
|
||||
|
||||
private fun migrateTo6(realm: DynamicRealm) {
|
||||
Timber.d("Step 5 -> 6")
|
||||
realm.schema.create("PreviewUrlCacheEntity")
|
||||
.addField(PreviewUrlCacheEntityFields.URL, String::class.java)
|
||||
.setRequired(PreviewUrlCacheEntityFields.URL, true)
|
||||
.addPrimaryKey(PreviewUrlCacheEntityFields.URL)
|
||||
.addField(PreviewUrlCacheEntityFields.URL_FROM_SERVER, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.SITE_NAME, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.TITLE, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.DESCRIPTION, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.MXC_URL, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.LAST_UPDATED_TIMESTAMP, Long::class.java)
|
||||
}
|
||||
|
||||
private fun migrateTo7(realm: DynamicRealm) {
|
||||
Timber.d("Step 6 -> 7")
|
||||
realm.schema.get("RoomEntity")
|
||||
?.addField(RoomEntityFields.MEMBERS_LOAD_STATUS_STR, String::class.java)
|
||||
?.transform { obj ->
|
||||
if (obj.getBoolean("areAllMembersLoaded")) {
|
||||
obj.setString("membersLoadStatusStr", RoomMembersLoadStatusType.LOADED.name)
|
||||
} else {
|
||||
obj.setString("membersLoadStatusStr", RoomMembersLoadStatusType.NONE.name)
|
||||
}
|
||||
}
|
||||
?.removeField("areAllMembersLoaded")
|
||||
}
|
||||
|
||||
private fun migrateTo8(realm: DynamicRealm) {
|
||||
Timber.d("Step 7 -> 8")
|
||||
|
||||
val editionOfEventSchema = realm.schema.create("EditionOfEvent")
|
||||
.addField(EditionOfEventFields.CONTENT, String::class.java)
|
||||
.addField(EditionOfEventFields.EVENT_ID, String::class.java)
|
||||
.setRequired(EditionOfEventFields.EVENT_ID, true)
|
||||
.addField(EditionOfEventFields.SENDER_ID, String::class.java)
|
||||
.setRequired(EditionOfEventFields.SENDER_ID, true)
|
||||
.addField(EditionOfEventFields.TIMESTAMP, Long::class.java)
|
||||
.addField(EditionOfEventFields.IS_LOCAL_ECHO, Boolean::class.java)
|
||||
|
||||
realm.schema.get("EditAggregatedSummaryEntity")
|
||||
?.removeField("aggregatedContent")
|
||||
?.removeField("sourceEvents")
|
||||
?.removeField("lastEditTs")
|
||||
?.removeField("sourceLocalEchoEvents")
|
||||
?.addRealmListField(EditAggregatedSummaryEntityFields.EDITIONS.`$`, editionOfEventSchema)
|
||||
|
||||
// This has to be done once a parent use the model as a child
|
||||
// See https://github.com/realm/realm-java/issues/7402
|
||||
editionOfEventSchema.isEmbedded = true
|
||||
}
|
||||
|
||||
private fun migrateTo9(realm: DynamicRealm) {
|
||||
Timber.d("Step 8 -> 9")
|
||||
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Long::class.java, FieldAttribute.INDEXED)
|
||||
?.setNullable(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, true)
|
||||
?.addIndex(RoomSummaryEntityFields.MEMBERSHIP_STR)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_DIRECT)
|
||||
?.addIndex(RoomSummaryEntityFields.VERSIONING_STATE_STR)
|
||||
|
||||
?.addField(RoomSummaryEntityFields.IS_FAVOURITE, Boolean::class.java)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_FAVOURITE)
|
||||
?.addField(RoomSummaryEntityFields.IS_LOW_PRIORITY, Boolean::class.java)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_LOW_PRIORITY)
|
||||
?.addField(RoomSummaryEntityFields.IS_SERVER_NOTICE, Boolean::class.java)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_SERVER_NOTICE)
|
||||
|
||||
?.transform { obj ->
|
||||
val isFavorite = obj.getList(RoomSummaryEntityFields.TAGS.`$`).any {
|
||||
it.getString(RoomTagEntityFields.TAG_NAME) == RoomTag.ROOM_TAG_FAVOURITE
|
||||
}
|
||||
obj.setBoolean(RoomSummaryEntityFields.IS_FAVOURITE, isFavorite)
|
||||
|
||||
val isLowPriority = obj.getList(RoomSummaryEntityFields.TAGS.`$`).any {
|
||||
it.getString(RoomTagEntityFields.TAG_NAME) == RoomTag.ROOM_TAG_LOW_PRIORITY
|
||||
}
|
||||
|
||||
obj.setBoolean(RoomSummaryEntityFields.IS_LOW_PRIORITY, isLowPriority)
|
||||
|
||||
// XXX migrate last message origin server ts
|
||||
obj.getObject(RoomSummaryEntityFields.LATEST_PREVIEWABLE_EVENT.`$`)
|
||||
?.getObject(TimelineEventEntityFields.ROOT.`$`)
|
||||
?.getLong(EventEntityFields.ORIGIN_SERVER_TS)?.let {
|
||||
obj.setLong(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo10(realm: DynamicRealm) {
|
||||
Timber.d("Step 9 -> 10")
|
||||
realm.schema.create("SpaceChildSummaryEntity")
|
||||
?.addField(SpaceChildSummaryEntityFields.ORDER, String::class.java)
|
||||
?.addField(SpaceChildSummaryEntityFields.CHILD_ROOM_ID, String::class.java)
|
||||
?.addField(SpaceChildSummaryEntityFields.AUTO_JOIN, Boolean::class.java)
|
||||
?.setNullable(SpaceChildSummaryEntityFields.AUTO_JOIN, true)
|
||||
?.addRealmObjectField(SpaceChildSummaryEntityFields.CHILD_SUMMARY_ENTITY.`$`, realm.schema.get("RoomSummaryEntity")!!)
|
||||
?.addRealmListField(SpaceChildSummaryEntityFields.VIA_SERVERS.`$`, String::class.java)
|
||||
|
||||
realm.schema.create("SpaceParentSummaryEntity")
|
||||
?.addField(SpaceParentSummaryEntityFields.PARENT_ROOM_ID, String::class.java)
|
||||
?.addField(SpaceParentSummaryEntityFields.CANONICAL, Boolean::class.java)
|
||||
?.setNullable(SpaceParentSummaryEntityFields.CANONICAL, true)
|
||||
?.addRealmObjectField(SpaceParentSummaryEntityFields.PARENT_SUMMARY_ENTITY.`$`, realm.schema.get("RoomSummaryEntity")!!)
|
||||
?.addRealmListField(SpaceParentSummaryEntityFields.VIA_SERVERS.`$`, String::class.java)
|
||||
|
||||
val creationContentAdapter = MoshiProvider.providesMoshi().adapter(RoomCreateContent::class.java)
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.ROOM_TYPE, String::class.java)
|
||||
?.addField(RoomSummaryEntityFields.FLATTEN_PARENT_IDS, String::class.java)
|
||||
?.addField(RoomSummaryEntityFields.GROUP_IDS, String::class.java)
|
||||
?.transform { obj ->
|
||||
|
||||
val creationEvent = realm.where("CurrentStateEventEntity")
|
||||
.equalTo(CurrentStateEventEntityFields.ROOM_ID, obj.getString(RoomSummaryEntityFields.ROOM_ID))
|
||||
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_CREATE)
|
||||
.findFirst()
|
||||
|
||||
val roomType = creationEvent?.getObject(CurrentStateEventEntityFields.ROOT.`$`)
|
||||
?.getString(EventEntityFields.CONTENT)?.let {
|
||||
creationContentAdapter.fromJson(it)?.type
|
||||
}
|
||||
|
||||
obj.setString(RoomSummaryEntityFields.ROOM_TYPE, roomType)
|
||||
}
|
||||
?.addRealmListField(RoomSummaryEntityFields.PARENTS.`$`, realm.schema.get("SpaceParentSummaryEntity")!!)
|
||||
?.addRealmListField(RoomSummaryEntityFields.CHILDREN.`$`, realm.schema.get("SpaceChildSummaryEntity")!!)
|
||||
}
|
||||
|
||||
private fun migrateTo11(realm: DynamicRealm) {
|
||||
Timber.d("Step 10 -> 11")
|
||||
realm.schema.get("EventEntity")
|
||||
?.addField(EventEntityFields.SEND_STATE_DETAILS, String::class.java)
|
||||
}
|
||||
|
||||
private fun migrateTo12(realm: DynamicRealm) {
|
||||
Timber.d("Step 11 -> 12")
|
||||
|
||||
val joinRulesContentAdapter = MoshiProvider.providesMoshi().adapter(RoomJoinRulesContent::class.java)
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.JOIN_RULES_STR, String::class.java)
|
||||
?.transform { obj ->
|
||||
val joinRulesEvent = realm.where("CurrentStateEventEntity")
|
||||
.equalTo(CurrentStateEventEntityFields.ROOM_ID, obj.getString(RoomSummaryEntityFields.ROOM_ID))
|
||||
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_JOIN_RULES)
|
||||
.findFirst()
|
||||
|
||||
val roomJoinRules = joinRulesEvent?.getObject(CurrentStateEventEntityFields.ROOT.`$`)
|
||||
?.getString(EventEntityFields.CONTENT)?.let {
|
||||
joinRulesContentAdapter.fromJson(it)?.joinRules
|
||||
}
|
||||
|
||||
obj.setString(RoomSummaryEntityFields.JOIN_RULES_STR, roomJoinRules?.name)
|
||||
}
|
||||
|
||||
realm.schema.get("SpaceChildSummaryEntity")
|
||||
?.addField(SpaceChildSummaryEntityFields.SUGGESTED, Boolean::class.java)
|
||||
?.setNullable(SpaceChildSummaryEntityFields.SUGGESTED, true)
|
||||
}
|
||||
|
||||
private fun migrateTo13(realm: DynamicRealm) {
|
||||
Timber.d("Step 12 -> 13")
|
||||
// Fix issue with the nightly build. Eventually play again the migration which has been included in migrateTo12()
|
||||
realm.schema.get("SpaceChildSummaryEntity")
|
||||
?.takeIf { !it.hasField(SpaceChildSummaryEntityFields.SUGGESTED) }
|
||||
?.addField(SpaceChildSummaryEntityFields.SUGGESTED, Boolean::class.java)
|
||||
?.setNullable(SpaceChildSummaryEntityFields.SUGGESTED, true)
|
||||
}
|
||||
|
||||
private fun migrateTo14(realm: DynamicRealm) {
|
||||
Timber.d("Step 13 -> 14")
|
||||
val roomAccountDataSchema = realm.schema.create("RoomAccountDataEntity")
|
||||
.addField(RoomAccountDataEntityFields.CONTENT_STR, String::class.java)
|
||||
.addField(RoomAccountDataEntityFields.TYPE, String::class.java, FieldAttribute.INDEXED)
|
||||
|
||||
realm.schema.get("RoomEntity")
|
||||
?.addRealmListField(RoomEntityFields.ACCOUNT_DATA.`$`, roomAccountDataSchema)
|
||||
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, Boolean::class.java, FieldAttribute.INDEXED)
|
||||
?.transform {
|
||||
val isHiddenFromUser = it.getString(RoomSummaryEntityFields.VERSIONING_STATE_STR) == VersioningState.UPGRADED_ROOM_JOINED.name
|
||||
it.setBoolean(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, isHiddenFromUser)
|
||||
}
|
||||
|
||||
roomAccountDataSchema.isEmbedded = true
|
||||
}
|
||||
|
||||
private fun migrateTo15(realm: DynamicRealm) {
|
||||
Timber.d("Step 14 -> 15")
|
||||
// fix issue with flattenParentIds on DM that kept growing with duplicate
|
||||
// so we reset it, will be updated next sync
|
||||
realm.where("RoomSummaryEntity")
|
||||
.process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships())
|
||||
.equalTo(RoomSummaryEntityFields.IS_DIRECT, true)
|
||||
.findAll()
|
||||
.onEach {
|
||||
it.setString(RoomSummaryEntityFields.FLATTEN_PARENT_IDS, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo16(realm: DynamicRealm) {
|
||||
Timber.d("Step 15 -> 16")
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField(HomeServerCapabilitiesEntityFields.ROOM_VERSIONS_JSON, String::class.java)
|
||||
?.transform { obj ->
|
||||
// Schedule a refresh of the capabilities
|
||||
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo17(realm: DynamicRealm) {
|
||||
Timber.d("Step 16 -> 17")
|
||||
realm.schema.get("EventInsertEntity")
|
||||
?.addField(EventInsertEntityFields.CAN_BE_PROCESSED, Boolean::class.java)
|
||||
}
|
||||
|
||||
private fun migrateTo18(realm: DynamicRealm) {
|
||||
Timber.d("Step 17 -> 18")
|
||||
realm.schema.create("UserPresenceEntity")
|
||||
?.addField(UserPresenceEntityFields.USER_ID, String::class.java)
|
||||
?.addPrimaryKey(UserPresenceEntityFields.USER_ID)
|
||||
?.setRequired(UserPresenceEntityFields.USER_ID, true)
|
||||
?.addField(UserPresenceEntityFields.PRESENCE_STR, String::class.java)
|
||||
?.addField(UserPresenceEntityFields.LAST_ACTIVE_AGO, Long::class.java)
|
||||
?.setNullable(UserPresenceEntityFields.LAST_ACTIVE_AGO, true)
|
||||
?.addField(UserPresenceEntityFields.STATUS_MESSAGE, String::class.java)
|
||||
?.addField(UserPresenceEntityFields.IS_CURRENTLY_ACTIVE, Boolean::class.java)
|
||||
?.setNullable(UserPresenceEntityFields.IS_CURRENTLY_ACTIVE, true)
|
||||
?.addField(UserPresenceEntityFields.AVATAR_URL, String::class.java)
|
||||
?.addField(UserPresenceEntityFields.DISPLAY_NAME, String::class.java)
|
||||
|
||||
val userPresenceEntity = realm.schema.get("UserPresenceEntity") ?: return
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addRealmObjectField(RoomSummaryEntityFields.DIRECT_USER_PRESENCE.`$`, userPresenceEntity)
|
||||
|
||||
realm.schema.get("RoomMemberSummaryEntity")
|
||||
?.addRealmObjectField(RoomMemberSummaryEntityFields.USER_PRESENCE_ENTITY.`$`, userPresenceEntity)
|
||||
}
|
||||
|
||||
private fun migrateTo19(realm: DynamicRealm) {
|
||||
Timber.d("Step 18 -> 19")
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, String::class.java)
|
||||
?.transform {
|
||||
it.getString(RoomSummaryEntityFields.DISPLAY_NAME)?.let { displayName ->
|
||||
val normalised = normalizer.normalize(displayName)
|
||||
it.set(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, normalised)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo20(realm: DynamicRealm) {
|
||||
Timber.d("Step 19 -> 20")
|
||||
|
||||
realm.schema.get("ChunkEntity")?.apply {
|
||||
if (hasField("numberOfTimelineEvents")) {
|
||||
removeField("numberOfTimelineEvents")
|
||||
}
|
||||
var cleanOldChunks = false
|
||||
if (!hasField(ChunkEntityFields.NEXT_CHUNK.`$`)) {
|
||||
cleanOldChunks = true
|
||||
addRealmObjectField(ChunkEntityFields.NEXT_CHUNK.`$`, this)
|
||||
}
|
||||
if (!hasField(ChunkEntityFields.PREV_CHUNK.`$`)) {
|
||||
cleanOldChunks = true
|
||||
addRealmObjectField(ChunkEntityFields.PREV_CHUNK.`$`, this)
|
||||
}
|
||||
if (cleanOldChunks) {
|
||||
val chunkEntities = realm.where("ChunkEntity").equalTo(ChunkEntityFields.IS_LAST_FORWARD, false).findAll()
|
||||
chunkEntities.deleteAllFromRealm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo21(realm: DynamicRealm) {
|
||||
Timber.d("Step 20 -> 21")
|
||||
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.E2E_ALGORITHM, String::class.java)
|
||||
?.transform { obj ->
|
||||
|
||||
val encryptionContentAdapter = MoshiProvider.providesMoshi().adapter(EncryptionEventContent::class.java)
|
||||
|
||||
val encryptionEvent = realm.where("CurrentStateEventEntity")
|
||||
.equalTo(CurrentStateEventEntityFields.ROOM_ID, obj.getString(RoomSummaryEntityFields.ROOM_ID))
|
||||
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
||||
.findFirst()
|
||||
|
||||
val encryptionEventRoot = encryptionEvent?.getObject(CurrentStateEventEntityFields.ROOT.`$`)
|
||||
val algorithm = encryptionEventRoot
|
||||
?.getString(EventEntityFields.CONTENT)?.let {
|
||||
encryptionContentAdapter.fromJson(it)?.algorithm
|
||||
}
|
||||
|
||||
obj.setString(RoomSummaryEntityFields.E2E_ALGORITHM, algorithm)
|
||||
obj.setBoolean(RoomSummaryEntityFields.IS_ENCRYPTED, encryptionEvent != null)
|
||||
encryptionEventRoot?.getLong(EventEntityFields.ORIGIN_SERVER_TS)?.let {
|
||||
obj.setLong(RoomSummaryEntityFields.ENCRYPTION_EVENT_TS, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo22(realm: DynamicRealm) {
|
||||
Timber.d("Step 21 -> 22")
|
||||
val listJoinedRoomIds = realm.where("RoomEntity")
|
||||
.equalTo(RoomEntityFields.MEMBERSHIP_STR, Membership.JOIN.name).findAll()
|
||||
.map { it.getString(RoomEntityFields.ROOM_ID) }
|
||||
|
||||
val hasMissingStateEvent = realm.where("CurrentStateEventEntity")
|
||||
.`in`(CurrentStateEventEntityFields.ROOM_ID, listJoinedRoomIds.toTypedArray())
|
||||
.isNull(CurrentStateEventEntityFields.ROOT.`$`).findFirst() != null
|
||||
|
||||
if (hasMissingStateEvent) {
|
||||
Timber.v("Has some missing state event, clear session cache")
|
||||
realm.deleteAll()
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateTo23(realm: DynamicRealm) {
|
||||
Timber.d("Step 22 -> 23")
|
||||
val eventEntity = realm.schema.get("TimelineEventEntity") ?: return
|
||||
|
||||
realm.schema.get("EventEntity")
|
||||
?.addField(EventEntityFields.IS_ROOT_THREAD, Boolean::class.java, FieldAttribute.INDEXED)
|
||||
?.addField(EventEntityFields.ROOT_THREAD_EVENT_ID, String::class.java, FieldAttribute.INDEXED)
|
||||
?.addField(EventEntityFields.NUMBER_OF_THREADS, Int::class.java)
|
||||
?.addField(EventEntityFields.THREAD_NOTIFICATION_STATE_STR, String::class.java)
|
||||
?.transform {
|
||||
it.setString(EventEntityFields.THREAD_NOTIFICATION_STATE_STR, ThreadNotificationState.NO_NEW_MESSAGE.name)
|
||||
}
|
||||
?.addRealmObjectField(EventEntityFields.THREAD_SUMMARY_LATEST_MESSAGE.`$`, eventEntity)
|
||||
}
|
||||
|
||||
private fun migrateTo24(realm: DynamicRealm) {
|
||||
Timber.d("Step 23 -> 24")
|
||||
realm.schema.get("PreviewUrlCacheEntity")
|
||||
?.addField(PreviewUrlCacheEntityFields.IMAGE_WIDTH, Int::class.java)
|
||||
?.setNullable(PreviewUrlCacheEntityFields.IMAGE_WIDTH, true)
|
||||
?.addField(PreviewUrlCacheEntityFields.IMAGE_HEIGHT, Int::class.java)
|
||||
?.setNullable(PreviewUrlCacheEntityFields.IMAGE_HEIGHT, true)
|
||||
if (oldVersion < 1) MigrateSessionTo001(realm).perform()
|
||||
if (oldVersion < 2) MigrateSessionTo002(realm).perform()
|
||||
if (oldVersion < 3) MigrateSessionTo003(realm).perform()
|
||||
if (oldVersion < 4) MigrateSessionTo004(realm).perform()
|
||||
if (oldVersion < 5) MigrateSessionTo005(realm).perform()
|
||||
if (oldVersion < 6) MigrateSessionTo006(realm).perform()
|
||||
if (oldVersion < 7) MigrateSessionTo007(realm).perform()
|
||||
if (oldVersion < 8) MigrateSessionTo008(realm).perform()
|
||||
if (oldVersion < 9) MigrateSessionTo009(realm).perform()
|
||||
if (oldVersion < 10) MigrateSessionTo010(realm).perform()
|
||||
if (oldVersion < 11) MigrateSessionTo011(realm).perform()
|
||||
if (oldVersion < 12) MigrateSessionTo012(realm).perform()
|
||||
if (oldVersion < 13) MigrateSessionTo013(realm).perform()
|
||||
if (oldVersion < 14) MigrateSessionTo014(realm).perform()
|
||||
if (oldVersion < 15) MigrateSessionTo015(realm).perform()
|
||||
if (oldVersion < 16) MigrateSessionTo016(realm).perform()
|
||||
if (oldVersion < 17) MigrateSessionTo017(realm).perform()
|
||||
if (oldVersion < 18) MigrateSessionTo018(realm).perform()
|
||||
if (oldVersion < 19) MigrateSessionTo019(realm, normalizer).perform()
|
||||
if (oldVersion < 20) MigrateSessionTo020(realm).perform()
|
||||
if (oldVersion < 21) MigrateSessionTo021(realm).perform()
|
||||
if (oldVersion < 22) MigrateSessionTo022(realm).perform()
|
||||
if (oldVersion < 23) MigrateSessionTo023(realm).perform()
|
||||
if (oldVersion < 24) MigrateSessionTo024(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
// Add hasFailedSending in RoomSummary and a small warning icon on room list
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.HAS_FAILED_SENDING, Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
obj.setBoolean(RoomSummaryEntityFields.HAS_FAILED_SENDING, false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField("adminE2EByDefault", Boolean::class.java)
|
||||
?.transform { obj ->
|
||||
obj.setBoolean("adminE2EByDefault", true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField("preferredJitsiDomain", String::class.java)
|
||||
?.transform { obj ->
|
||||
// Schedule a refresh of the capabilities
|
||||
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("PendingThreePidEntity")
|
||||
.addField(PendingThreePidEntityFields.CLIENT_SECRET, String::class.java)
|
||||
.setRequired(PendingThreePidEntityFields.CLIENT_SECRET, true)
|
||||
.addField(PendingThreePidEntityFields.EMAIL, String::class.java)
|
||||
.addField(PendingThreePidEntityFields.MSISDN, String::class.java)
|
||||
.addField(PendingThreePidEntityFields.SEND_ATTEMPT, Int::class.java)
|
||||
.addField(PendingThreePidEntityFields.SID, String::class.java)
|
||||
.setRequired(PendingThreePidEntityFields.SID, true)
|
||||
.addField(PendingThreePidEntityFields.SUBMIT_URL, String::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.removeField("adminE2EByDefault")
|
||||
?.removeField("preferredJitsiDomain")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo006(realm: DynamicRealm) : RealmMigrator(realm, 6) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("PreviewUrlCacheEntity")
|
||||
.addField(PreviewUrlCacheEntityFields.URL, String::class.java)
|
||||
.setRequired(PreviewUrlCacheEntityFields.URL, true)
|
||||
.addPrimaryKey(PreviewUrlCacheEntityFields.URL)
|
||||
.addField(PreviewUrlCacheEntityFields.URL_FROM_SERVER, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.SITE_NAME, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.TITLE, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.DESCRIPTION, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.MXC_URL, String::class.java)
|
||||
.addField(PreviewUrlCacheEntityFields.LAST_UPDATED_TIMESTAMP, Long::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("RoomEntity")
|
||||
?.addField(RoomEntityFields.MEMBERS_LOAD_STATUS_STR, String::class.java)
|
||||
?.transform { obj ->
|
||||
if (obj.getBoolean("areAllMembersLoaded")) {
|
||||
obj.setString("membersLoadStatusStr", RoomMembersLoadStatusType.LOADED.name)
|
||||
} else {
|
||||
obj.setString("membersLoadStatusStr", RoomMembersLoadStatusType.NONE.name)
|
||||
}
|
||||
}
|
||||
?.removeField("areAllMembersLoaded")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.EditAggregatedSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EditionOfEventFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val editionOfEventSchema = realm.schema.create("EditionOfEvent")
|
||||
.addField(EditionOfEventFields.CONTENT, String::class.java)
|
||||
.addField(EditionOfEventFields.EVENT_ID, String::class.java)
|
||||
.setRequired(EditionOfEventFields.EVENT_ID, true)
|
||||
.addField(EditionOfEventFields.SENDER_ID, String::class.java)
|
||||
.setRequired(EditionOfEventFields.SENDER_ID, true)
|
||||
.addField(EditionOfEventFields.TIMESTAMP, Long::class.java)
|
||||
.addField(EditionOfEventFields.IS_LOCAL_ECHO, Boolean::class.java)
|
||||
|
||||
realm.schema.get("EditAggregatedSummaryEntity")
|
||||
?.removeField("aggregatedContent")
|
||||
?.removeField("sourceEvents")
|
||||
?.removeField("lastEditTs")
|
||||
?.removeField("sourceLocalEchoEvents")
|
||||
?.addRealmListField(EditAggregatedSummaryEntityFields.EDITIONS.`$`, editionOfEventSchema)
|
||||
|
||||
// This has to be done once a parent use the model as a child
|
||||
// See https://github.com/realm/realm-java/issues/7402
|
||||
editionOfEventSchema.isEmbedded = true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.FieldAttribute
|
||||
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomTagEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo009(realm: DynamicRealm) : RealmMigrator(realm, 9) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Long::class.java, FieldAttribute.INDEXED)
|
||||
?.setNullable(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, true)
|
||||
?.addIndex(RoomSummaryEntityFields.MEMBERSHIP_STR)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_DIRECT)
|
||||
?.addIndex(RoomSummaryEntityFields.VERSIONING_STATE_STR)
|
||||
|
||||
?.addField(RoomSummaryEntityFields.IS_FAVOURITE, Boolean::class.java)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_FAVOURITE)
|
||||
?.addField(RoomSummaryEntityFields.IS_LOW_PRIORITY, Boolean::class.java)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_LOW_PRIORITY)
|
||||
?.addField(RoomSummaryEntityFields.IS_SERVER_NOTICE, Boolean::class.java)
|
||||
?.addIndex(RoomSummaryEntityFields.IS_SERVER_NOTICE)
|
||||
|
||||
?.transform { obj ->
|
||||
val isFavorite = obj.getList(RoomSummaryEntityFields.TAGS.`$`).any {
|
||||
it.getString(RoomTagEntityFields.TAG_NAME) == RoomTag.ROOM_TAG_FAVOURITE
|
||||
}
|
||||
obj.setBoolean(RoomSummaryEntityFields.IS_FAVOURITE, isFavorite)
|
||||
|
||||
val isLowPriority = obj.getList(RoomSummaryEntityFields.TAGS.`$`).any {
|
||||
it.getString(RoomTagEntityFields.TAG_NAME) == RoomTag.ROOM_TAG_LOW_PRIORITY
|
||||
}
|
||||
|
||||
obj.setBoolean(RoomSummaryEntityFields.IS_LOW_PRIORITY, isLowPriority)
|
||||
|
||||
// XXX migrate last message origin server ts
|
||||
obj.getObject(RoomSummaryEntityFields.LATEST_PREVIEWABLE_EVENT.`$`)
|
||||
?.getObject(TimelineEventEntityFields.ROOT.`$`)
|
||||
?.getLong(EventEntityFields.ORIGIN_SERVER_TS)?.let {
|
||||
obj.setLong(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceParentSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo010(realm: DynamicRealm) : RealmMigrator(realm, 10) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("SpaceChildSummaryEntity")
|
||||
?.addField(SpaceChildSummaryEntityFields.ORDER, String::class.java)
|
||||
?.addField(SpaceChildSummaryEntityFields.CHILD_ROOM_ID, String::class.java)
|
||||
?.addField(SpaceChildSummaryEntityFields.AUTO_JOIN, Boolean::class.java)
|
||||
?.setNullable(SpaceChildSummaryEntityFields.AUTO_JOIN, true)
|
||||
?.addRealmObjectField(SpaceChildSummaryEntityFields.CHILD_SUMMARY_ENTITY.`$`, realm.schema.get("RoomSummaryEntity")!!)
|
||||
?.addRealmListField(SpaceChildSummaryEntityFields.VIA_SERVERS.`$`, String::class.java)
|
||||
|
||||
realm.schema.create("SpaceParentSummaryEntity")
|
||||
?.addField(SpaceParentSummaryEntityFields.PARENT_ROOM_ID, String::class.java)
|
||||
?.addField(SpaceParentSummaryEntityFields.CANONICAL, Boolean::class.java)
|
||||
?.setNullable(SpaceParentSummaryEntityFields.CANONICAL, true)
|
||||
?.addRealmObjectField(SpaceParentSummaryEntityFields.PARENT_SUMMARY_ENTITY.`$`, realm.schema.get("RoomSummaryEntity")!!)
|
||||
?.addRealmListField(SpaceParentSummaryEntityFields.VIA_SERVERS.`$`, String::class.java)
|
||||
|
||||
val creationContentAdapter = MoshiProvider.providesMoshi().adapter(RoomCreateContent::class.java)
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.ROOM_TYPE, String::class.java)
|
||||
?.addField(RoomSummaryEntityFields.FLATTEN_PARENT_IDS, String::class.java)
|
||||
?.addField(RoomSummaryEntityFields.GROUP_IDS, String::class.java)
|
||||
?.transform { obj ->
|
||||
|
||||
val creationEvent = realm.where("CurrentStateEventEntity")
|
||||
.equalTo(CurrentStateEventEntityFields.ROOM_ID, obj.getString(RoomSummaryEntityFields.ROOM_ID))
|
||||
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_CREATE)
|
||||
.findFirst()
|
||||
|
||||
val roomType = creationEvent?.getObject(CurrentStateEventEntityFields.ROOT.`$`)
|
||||
?.getString(EventEntityFields.CONTENT)?.let {
|
||||
creationContentAdapter.fromJson(it)?.type
|
||||
}
|
||||
|
||||
obj.setString(RoomSummaryEntityFields.ROOM_TYPE, roomType)
|
||||
}
|
||||
?.addRealmListField(RoomSummaryEntityFields.PARENTS.`$`, realm.schema.get("SpaceParentSummaryEntity")!!)
|
||||
?.addRealmListField(RoomSummaryEntityFields.CHILDREN.`$`, realm.schema.get("SpaceChildSummaryEntity")!!)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo011(realm: DynamicRealm) : RealmMigrator(realm, 11) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("EventEntity")
|
||||
?.addField(EventEntityFields.SEND_STATE_DETAILS, String::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo012(realm: DynamicRealm) : RealmMigrator(realm, 12) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val joinRulesContentAdapter = MoshiProvider.providesMoshi().adapter(RoomJoinRulesContent::class.java)
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.JOIN_RULES_STR, String::class.java)
|
||||
?.transform { obj ->
|
||||
val joinRulesEvent = realm.where("CurrentStateEventEntity")
|
||||
.equalTo(CurrentStateEventEntityFields.ROOM_ID, obj.getString(RoomSummaryEntityFields.ROOM_ID))
|
||||
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_JOIN_RULES)
|
||||
.findFirst()
|
||||
|
||||
val roomJoinRules = joinRulesEvent?.getObject(CurrentStateEventEntityFields.ROOT.`$`)
|
||||
?.getString(EventEntityFields.CONTENT)?.let {
|
||||
joinRulesContentAdapter.fromJson(it)?.joinRules
|
||||
}
|
||||
|
||||
obj.setString(RoomSummaryEntityFields.JOIN_RULES_STR, roomJoinRules?.name)
|
||||
}
|
||||
|
||||
realm.schema.get("SpaceChildSummaryEntity")
|
||||
?.addField(SpaceChildSummaryEntityFields.SUGGESTED, Boolean::class.java)
|
||||
?.setNullable(SpaceChildSummaryEntityFields.SUGGESTED, true)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo013(realm: DynamicRealm) : RealmMigrator(realm, 13) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
// Fix issue with the nightly build. Eventually play again the migration which has been included in migrateTo12()
|
||||
realm.schema.get("SpaceChildSummaryEntity")
|
||||
?.takeIf { !it.hasField(SpaceChildSummaryEntityFields.SUGGESTED) }
|
||||
?.addField(SpaceChildSummaryEntityFields.SUGGESTED, Boolean::class.java)
|
||||
?.setNullable(SpaceChildSummaryEntityFields.SUGGESTED, true)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.FieldAttribute
|
||||
import org.matrix.android.sdk.api.session.room.model.VersioningState
|
||||
import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo014(realm: DynamicRealm) : RealmMigrator(realm, 14) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val roomAccountDataSchema = realm.schema.create("RoomAccountDataEntity")
|
||||
.addField(RoomAccountDataEntityFields.CONTENT_STR, String::class.java)
|
||||
.addField(RoomAccountDataEntityFields.TYPE, String::class.java, FieldAttribute.INDEXED)
|
||||
|
||||
realm.schema.get("RoomEntity")
|
||||
?.addRealmListField(RoomEntityFields.ACCOUNT_DATA.`$`, roomAccountDataSchema)
|
||||
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, Boolean::class.java, FieldAttribute.INDEXED)
|
||||
?.transform {
|
||||
val isHiddenFromUser = it.getString(RoomSummaryEntityFields.VERSIONING_STATE_STR) == VersioningState.UPGRADED_ROOM_JOINED.name
|
||||
it.setBoolean(RoomSummaryEntityFields.IS_HIDDEN_FROM_USER, isHiddenFromUser)
|
||||
}
|
||||
|
||||
roomAccountDataSchema.isEmbedded = true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.query.process
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo015(realm: DynamicRealm) : RealmMigrator(realm, 15) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
// fix issue with flattenParentIds on DM that kept growing with duplicate
|
||||
// so we reset it, will be updated next sync
|
||||
realm.where("RoomSummaryEntity")
|
||||
.process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships())
|
||||
.equalTo(RoomSummaryEntityFields.IS_DIRECT, true)
|
||||
.findAll()
|
||||
.onEach {
|
||||
it.setString(RoomSummaryEntityFields.FLATTEN_PARENT_IDS, null)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo016(realm: DynamicRealm) : RealmMigrator(realm, 16) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("HomeServerCapabilitiesEntity")
|
||||
?.addField(HomeServerCapabilitiesEntityFields.ROOM_VERSIONS_JSON, String::class.java)
|
||||
?.transform { obj ->
|
||||
// Schedule a refresh of the capabilities
|
||||
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo017(realm: DynamicRealm) : RealmMigrator(realm, 17) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("EventInsertEntity")
|
||||
?.addField(EventInsertEntityFields.CAN_BE_PROCESSED, Boolean::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo018(realm: DynamicRealm) : RealmMigrator(realm, 18) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("UserPresenceEntity")
|
||||
?.addField(UserPresenceEntityFields.USER_ID, String::class.java)
|
||||
?.addPrimaryKey(UserPresenceEntityFields.USER_ID)
|
||||
?.setRequired(UserPresenceEntityFields.USER_ID, true)
|
||||
?.addField(UserPresenceEntityFields.PRESENCE_STR, String::class.java)
|
||||
?.addField(UserPresenceEntityFields.LAST_ACTIVE_AGO, Long::class.java)
|
||||
?.setNullable(UserPresenceEntityFields.LAST_ACTIVE_AGO, true)
|
||||
?.addField(UserPresenceEntityFields.STATUS_MESSAGE, String::class.java)
|
||||
?.addField(UserPresenceEntityFields.IS_CURRENTLY_ACTIVE, Boolean::class.java)
|
||||
?.setNullable(UserPresenceEntityFields.IS_CURRENTLY_ACTIVE, true)
|
||||
?.addField(UserPresenceEntityFields.AVATAR_URL, String::class.java)
|
||||
?.addField(UserPresenceEntityFields.DISPLAY_NAME, String::class.java)
|
||||
|
||||
val userPresenceEntity = realm.schema.get("UserPresenceEntity") ?: return
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addRealmObjectField(RoomSummaryEntityFields.DIRECT_USER_PRESENCE.`$`, userPresenceEntity)
|
||||
|
||||
realm.schema.get("RoomMemberSummaryEntity")
|
||||
?.addRealmObjectField(RoomMemberSummaryEntityFields.USER_PRESENCE_ENTITY.`$`, userPresenceEntity)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.util.Normalizer
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo019(realm: DynamicRealm,
|
||||
private val normalizer: Normalizer) : RealmMigrator(realm, 19) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, String::class.java)
|
||||
?.transform {
|
||||
it.getString(RoomSummaryEntityFields.DISPLAY_NAME)?.let { displayName ->
|
||||
val normalised = normalizer.normalize(displayName)
|
||||
it.set(RoomSummaryEntityFields.NORMALIZED_DISPLAY_NAME, normalised)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo020(realm: DynamicRealm) : RealmMigrator(realm, 20) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("ChunkEntity")?.apply {
|
||||
if (hasField("numberOfTimelineEvents")) {
|
||||
removeField("numberOfTimelineEvents")
|
||||
}
|
||||
var cleanOldChunks = false
|
||||
if (!hasField(ChunkEntityFields.NEXT_CHUNK.`$`)) {
|
||||
cleanOldChunks = true
|
||||
addRealmObjectField(ChunkEntityFields.NEXT_CHUNK.`$`, this)
|
||||
}
|
||||
if (!hasField(ChunkEntityFields.PREV_CHUNK.`$`)) {
|
||||
cleanOldChunks = true
|
||||
addRealmObjectField(ChunkEntityFields.PREV_CHUNK.`$`, this)
|
||||
}
|
||||
if (cleanOldChunks) {
|
||||
val chunkEntities = realm.where("ChunkEntity").equalTo(ChunkEntityFields.IS_LAST_FORWARD, false).findAll()
|
||||
chunkEntities.deleteAllFromRealm()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo021(realm: DynamicRealm) : RealmMigrator(realm, 21) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("RoomSummaryEntity")
|
||||
?.addField(RoomSummaryEntityFields.E2E_ALGORITHM, String::class.java)
|
||||
?.transform { obj ->
|
||||
|
||||
val encryptionContentAdapter = MoshiProvider.providesMoshi().adapter(EncryptionEventContent::class.java)
|
||||
|
||||
val encryptionEvent = realm.where("CurrentStateEventEntity")
|
||||
.equalTo(CurrentStateEventEntityFields.ROOM_ID, obj.getString(RoomSummaryEntityFields.ROOM_ID))
|
||||
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
||||
.findFirst()
|
||||
|
||||
val encryptionEventRoot = encryptionEvent?.getObject(CurrentStateEventEntityFields.ROOT.`$`)
|
||||
val algorithm = encryptionEventRoot
|
||||
?.getString(EventEntityFields.CONTENT)?.let {
|
||||
encryptionContentAdapter.fromJson(it)?.algorithm
|
||||
}
|
||||
|
||||
obj.setString(RoomSummaryEntityFields.E2E_ALGORITHM, algorithm)
|
||||
obj.setBoolean(RoomSummaryEntityFields.IS_ENCRYPTED, encryptionEvent != null)
|
||||
encryptionEventRoot?.getLong(EventEntityFields.ORIGIN_SERVER_TS)?.let {
|
||||
obj.setLong(RoomSummaryEntityFields.ENCRYPTION_EVENT_TS, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateSessionTo022(realm: DynamicRealm) : RealmMigrator(realm, 22) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val listJoinedRoomIds = realm.where("RoomEntity")
|
||||
.equalTo(RoomEntityFields.MEMBERSHIP_STR, Membership.JOIN.name).findAll()
|
||||
.map { it.getString(RoomEntityFields.ROOM_ID) }
|
||||
|
||||
val hasMissingStateEvent = realm.where("CurrentStateEventEntity")
|
||||
.`in`(CurrentStateEventEntityFields.ROOM_ID, listJoinedRoomIds.toTypedArray())
|
||||
.isNull(CurrentStateEventEntityFields.ROOT.`$`).findFirst() != null
|
||||
|
||||
if (hasMissingStateEvent) {
|
||||
Timber.v("Has some missing state event, clear session cache")
|
||||
realm.deleteAll()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.FieldAttribute
|
||||
import org.matrix.android.sdk.api.session.threads.ThreadNotificationState
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo023(realm: DynamicRealm) : RealmMigrator(realm, 23) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
val eventEntity = realm.schema.get("TimelineEventEntity") ?: return
|
||||
|
||||
realm.schema.get("EventEntity")
|
||||
?.addField(EventEntityFields.IS_ROOT_THREAD, Boolean::class.java, FieldAttribute.INDEXED)
|
||||
?.addField(EventEntityFields.ROOT_THREAD_EVENT_ID, String::class.java, FieldAttribute.INDEXED)
|
||||
?.addField(EventEntityFields.NUMBER_OF_THREADS, Int::class.java)
|
||||
?.addField(EventEntityFields.THREAD_NOTIFICATION_STATE_STR, String::class.java)
|
||||
?.transform {
|
||||
it.setString(EventEntityFields.THREAD_NOTIFICATION_STATE_STR, ThreadNotificationState.NO_NEW_MESSAGE.name)
|
||||
}
|
||||
?.addRealmObjectField(EventEntityFields.THREAD_SUMMARY_LATEST_MESSAGE.`$`, eventEntity)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateSessionTo024(realm: DynamicRealm) : RealmMigrator(realm, 24) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.get("PreviewUrlCacheEntity")
|
||||
?.addField(PreviewUrlCacheEntityFields.IMAGE_WIDTH, Int::class.java)
|
||||
?.setNullable(PreviewUrlCacheEntityFields.IMAGE_WIDTH, true)
|
||||
?.addField(PreviewUrlCacheEntityFields.IMAGE_HEIGHT, Int::class.java)
|
||||
?.setNullable(PreviewUrlCacheEntityFields.IMAGE_HEIGHT, true)
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.raw
|
|||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.RealmMigration
|
||||
import org.matrix.android.sdk.internal.database.model.KnownServerUrlEntityFields
|
||||
import org.matrix.android.sdk.internal.raw.migration.MigrateGlobalTo001
|
||||
import timber.log.Timber
|
||||
|
||||
internal object GlobalRealmMigration : RealmMigration {
|
||||
|
@ -27,15 +27,8 @@ internal object GlobalRealmMigration : RealmMigration {
|
|||
const val SCHEMA_VERSION = 1L
|
||||
|
||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
|
||||
Timber.d("Migrating Global Realm from $oldVersion to $newVersion")
|
||||
|
||||
if (oldVersion <= 0) migrateTo1(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
realm.schema.create("KnownServerUrlEntity")
|
||||
.addField(KnownServerUrlEntityFields.URL, String::class.java)
|
||||
.addPrimaryKey(KnownServerUrlEntityFields.URL)
|
||||
.setRequired(KnownServerUrlEntityFields.URL, true)
|
||||
if (oldVersion < 1) MigrateGlobalTo001(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.raw.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.database.model.KnownServerUrlEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
|
||||
class MigrateGlobalTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
realm.schema.create("KnownServerUrlEntity")
|
||||
.addField(KnownServerUrlEntityFields.URL, String::class.java)
|
||||
.addPrimaryKey(KnownServerUrlEntityFields.URL)
|
||||
.setRequired(KnownServerUrlEntityFields.URL, true)
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.identity.db
|
|||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.RealmMigration
|
||||
import org.matrix.android.sdk.internal.session.identity.db.migration.MigrateIdentityTo001
|
||||
import timber.log.Timber
|
||||
|
||||
internal object RealmIdentityStoreMigration : RealmMigration {
|
||||
|
@ -27,14 +28,6 @@ internal object RealmIdentityStoreMigration : RealmMigration {
|
|||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
Timber.v("Migrating Realm Identity from $oldVersion to $newVersion")
|
||||
|
||||
if (oldVersion <= 0) migrateTo1(realm)
|
||||
}
|
||||
|
||||
private fun migrateTo1(realm: DynamicRealm) {
|
||||
Timber.d("Step 0 -> 1")
|
||||
Timber.d("Add field userConsent (Boolean) and set the value to false")
|
||||
|
||||
realm.schema.get("IdentityDataEntity")
|
||||
?.addField(IdentityDataEntityFields.USER_CONSENT, Boolean::class.java)
|
||||
if (oldVersion < 1) MigrateIdentityTo001(realm).perform()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.session.identity.db.migration
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import org.matrix.android.sdk.internal.session.identity.db.IdentityDataEntityFields
|
||||
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||
import timber.log.Timber
|
||||
|
||||
class MigrateIdentityTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
|
||||
|
||||
override fun doMigrate(realm: DynamicRealm) {
|
||||
Timber.d("Add field userConsent (Boolean) and set the value to false")
|
||||
realm.schema.get("IdentityDataEntity")
|
||||
?.addField(IdentityDataEntityFields.USER_CONSENT, Boolean::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.util.database
|
||||
|
||||
import io.realm.DynamicRealm
|
||||
import io.realm.RealmObjectSchema
|
||||
import timber.log.Timber
|
||||
|
||||
abstract class RealmMigrator(private val realm: DynamicRealm,
|
||||
private val targetSchemaVersion: Int) {
|
||||
fun perform() {
|
||||
Timber.d("Migrate ${realm.configuration.realmFileName} to $targetSchemaVersion")
|
||||
doMigrate(realm)
|
||||
}
|
||||
|
||||
abstract fun doMigrate(realm: DynamicRealm)
|
||||
|
||||
protected fun RealmObjectSchema.addFieldIfNotExists(fieldName: String, fieldType: Class<*>): RealmObjectSchema {
|
||||
if (!hasField(fieldName)) {
|
||||
addField(fieldName, fieldType)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
protected fun RealmObjectSchema.removeFieldIfExists(fieldName: String): RealmObjectSchema {
|
||||
if (hasField(fieldName)) {
|
||||
removeField(fieldName)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
protected fun RealmObjectSchema.setRequiredIfNotAlready(fieldName: String, isRequired: Boolean): RealmObjectSchema {
|
||||
if (isRequired != isRequired(fieldName)) {
|
||||
setRequired(fieldName, isRequired)
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue