From 7a555d127fd0380ca57aac0187e2a50818bb3d27 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Thu, 18 May 2023 17:39:36 -0300 Subject: [PATCH] Tighten migration and remove null peer events. --- .../securesms/database/CallTable.kt | 16 +-- .../helpers/SignalDatabaseMigrations.kt | 7 +- .../V193_BackCallLinksWithRecipient.kt | 81 +-------------- .../V196_BackCallLinksWithRecipientV2.kt | 98 +++++++++++++++++++ 4 files changed, 114 insertions(+), 88 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V196_BackCallLinksWithRecipientV2.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt index 2959c625ab..52c87c2dc5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -65,7 +65,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl $ID INTEGER PRIMARY KEY, $CALL_ID INTEGER NOT NULL, $MESSAGE_ID INTEGER DEFAULT NULL REFERENCES ${MessageTable.TABLE_NAME} (${MessageTable.ID}) ON DELETE SET NULL, - $PEER INTEGER DEFAULT NULL REFERENCES ${RecipientTable.TABLE_NAME} (${RecipientTable.ID}) ON DELETE CASCADE, + $PEER INTEGER NOT NULL REFERENCES ${RecipientTable.TABLE_NAME} (${RecipientTable.ID}) ON DELETE CASCADE, $TYPE INTEGER NOT NULL, $DIRECTION INTEGER NOT NULL, $EVENT INTEGER NOT NULL, @@ -270,18 +270,18 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl fun insertDeletedGroupCallFromSyncEvent( callId: Long, - recipientId: RecipientId?, + recipientId: RecipientId, direction: Direction, timestamp: Long ) { - val type = if (recipientId != null) Type.GROUP_CALL else Type.AD_HOC_CALL + val type = Type.GROUP_CALL writableDatabase .insertInto(TABLE_NAME) .values( CALL_ID to callId, MESSAGE_ID to null, - PEER to recipientId?.toLong(), + PEER to recipientId.toLong(), EVENT to Event.serialize(Event.DELETE), TYPE to Type.serialize(type), DIRECTION to Direction.serialize(direction), @@ -318,16 +318,16 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl fun insertAcceptedGroupCall( callId: Long, - recipientId: RecipientId?, + recipientId: RecipientId, direction: Direction, timestamp: Long ) { - val type = if (recipientId != null) Type.GROUP_CALL else Type.AD_HOC_CALL + val type = Type.GROUP_CALL val event = if (direction == Direction.OUTGOING) Event.OUTGOING_RING else Event.JOINED val ringer = if (direction == Direction.OUTGOING) Recipient.self().id.toLong() else null writableDatabase.withinTransaction { db -> - val messageId: MessageId? = if (recipientId != null) { + val messageId: MessageId? = if (type == Type.GROUP_CALL) { SignalDatabase.messages.insertGroupCall( groupRecipientId = recipientId, sender = Recipient.self().id, @@ -345,7 +345,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl .values( CALL_ID to callId, MESSAGE_ID to messageId?.id, - PEER to recipientId?.toLong(), + PEER to recipientId.toLong(), EVENT to Event.serialize(event), TYPE to Type.serialize(type), DIRECTION to Direction.serialize(direction), diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt index 9d9a86443e..90587b5938 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt @@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V192_CallLinkTableN import org.thoughtcrime.securesms.database.helpers.migration.V193_BackCallLinksWithRecipient import org.thoughtcrime.securesms.database.helpers.migration.V194_KyberPreKeyMigration import org.thoughtcrime.securesms.database.helpers.migration.V195_GroupMemberForeignKeyMigration +import org.thoughtcrime.securesms.database.helpers.migration.V196_BackCallLinksWithRecipientV2 /** * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. @@ -59,7 +60,7 @@ object SignalDatabaseMigrations { val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass) - const val DATABASE_VERSION = 195 + const val DATABASE_VERSION = 196 @JvmStatic fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { @@ -250,6 +251,10 @@ object SignalDatabaseMigrations { if (oldVersion < 195) { V195_GroupMemberForeignKeyMigration.migrate(context, db, oldVersion, newVersion) } + + if (oldVersion < 196) { + V196_BackCallLinksWithRecipientV2.migrate(context, db, oldVersion, newVersion) + } } @JvmStatic diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V193_BackCallLinksWithRecipient.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V193_BackCallLinksWithRecipient.kt index f4ff3dc240..bec7522f88 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V193_BackCallLinksWithRecipient.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V193_BackCallLinksWithRecipient.kt @@ -7,88 +7,11 @@ package org.thoughtcrime.securesms.database.helpers.migration import android.app.Application import net.zetetic.database.sqlcipher.SQLiteDatabase -import org.signal.core.util.SqlUtil -import org.signal.core.util.logging.Log /** - * Back CallLinks with a Recipient to ease integration and ensure we can support - * different features which would require that relation in the future. + * Due to a bug, this has been replaced by [V196_BackCallLinksWithRecipientV2] */ object V193_BackCallLinksWithRecipient : SignalDatabaseMigration { - private val TAG = Log.tag(V193_BackCallLinksWithRecipient::class.java) - - override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { - // add new column to recipient table to store the room id - db.execSQL("ALTER TABLE recipient ADD COLUMN call_link_room_id TEXT DEFAULT NULL") - - // recreate the call link table with the new recipient id reference. - db.execSQL("DROP TABLE call_link") - db.execSQL( - """ - CREATE TABLE call_link ( - _id INTEGER PRIMARY KEY, - root_key BLOB, - room_id TEXT NOT NULL UNIQUE, - admin_key BLOB, - name TEXT NOT NULL, - restrictions INTEGER NOT NULL, - revoked INTEGER NOT NULL, - expiration INTEGER NOT NULL, - avatar_color TEXT NOT NULL, - recipient_id INTEGER UNIQUE REFERENCES recipient (_id) ON DELETE CASCADE - ) - """.trimIndent() - ) - - // recreate the call table dropping the call_link column - db.execSQL( - """ - CREATE TABLE call_tmp ( - _id INTEGER PRIMARY KEY, - call_id INTEGER NOT NULL, - message_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE SET NULL, - peer INTEGER DEFAULT NULL REFERENCES recipient (_id) ON DELETE CASCADE, - type INTEGER NOT NULL, - direction INTEGER NOT NULL, - event INTEGER NOT NULL, - timestamp INTEGER NOT NULL, - ringer INTEGER DEFAULT NULL, - deletion_timestamp INTEGER DEFAULT 0, - UNIQUE (call_id, peer) ON CONFLICT FAIL - ) - """.trimIndent() - ) - - db.execSQL( - """ - INSERT INTO call_tmp - SELECT - _id, - call_id, - message_id, - peer, - type, - direction, - event, - timestamp, - ringer, - deletion_timestamp - FROM call - """.trimIndent() - ) - - db.execSQL("DROP TABLE call") - db.execSQL("ALTER TABLE call_tmp RENAME TO call") - - db.execSQL("CREATE INDEX IF NOT EXISTS call_call_id_index ON call (call_id)") - db.execSQL("CREATE INDEX IF NOT EXISTS call_message_id_index ON call (message_id)") - db.execSQL("CREATE INDEX IF NOT EXISTS call_peer_index ON call (peer)") - - val foreignKeyViolations: List = SqlUtil.getForeignKeyViolations(db, "call") - if (foreignKeyViolations.isNotEmpty()) { - Log.w(TAG, "Foreign key violations!\n${foreignKeyViolations.joinToString(separator = "\n")}") - throw IllegalStateException("Foreign key violations!") - } - } + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) = Unit } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V196_BackCallLinksWithRecipientV2.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V196_BackCallLinksWithRecipientV2.kt new file mode 100644 index 0000000000..4fd697e516 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V196_BackCallLinksWithRecipientV2.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.database.helpers.migration + +import android.app.Application +import net.zetetic.database.sqlcipher.SQLiteDatabase +import org.signal.core.util.SqlUtil +import org.signal.core.util.logging.Log + +/** + * Cleans up the call events table and restricts peer to non-null. + */ +object V196_BackCallLinksWithRecipientV2 : SignalDatabaseMigration { + + private val TAG = Log.tag(V196_BackCallLinksWithRecipientV2::class.java) + + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + if (!SqlUtil.columnExists(db, "recipient", "call_link_room_id")) { + // add new column to recipient table to store the room id + db.execSQL("ALTER TABLE recipient ADD COLUMN call_link_room_id TEXT DEFAULT NULL") + + // recreate the call link table with the new recipient id reference. + db.execSQL("DROP TABLE call_link") + db.execSQL( + """ + CREATE TABLE call_link ( + _id INTEGER PRIMARY KEY, + root_key BLOB, + room_id TEXT NOT NULL UNIQUE, + admin_key BLOB, + name TEXT NOT NULL, + restrictions INTEGER NOT NULL, + revoked INTEGER NOT NULL, + expiration INTEGER NOT NULL, + avatar_color TEXT NOT NULL, + recipient_id INTEGER UNIQUE REFERENCES recipient (_id) ON DELETE CASCADE + ) + """.trimIndent() + ) + } + + // drop all call events with a null peer. + db.execSQL("DELETE FROM call WHERE peer IS NULL") + + // recreate the call table dropping the call_link column + db.execSQL( + """ + CREATE TABLE call_tmp ( + _id INTEGER PRIMARY KEY, + call_id INTEGER NOT NULL, + message_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE SET NULL, + peer INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE, + type INTEGER NOT NULL, + direction INTEGER NOT NULL, + event INTEGER NOT NULL, + timestamp INTEGER NOT NULL, + ringer INTEGER DEFAULT NULL, + deletion_timestamp INTEGER DEFAULT 0, + UNIQUE (call_id, peer) ON CONFLICT FAIL + ) + """.trimIndent() + ) + + db.execSQL( + """ + INSERT INTO call_tmp + SELECT + _id, + call_id, + message_id, + peer, + type, + direction, + event, + timestamp, + ringer, + deletion_timestamp + FROM call + """.trimIndent() + ) + + db.execSQL("DROP TABLE call") + db.execSQL("ALTER TABLE call_tmp RENAME TO call") + + db.execSQL("CREATE INDEX IF NOT EXISTS call_call_id_index ON call (call_id)") + db.execSQL("CREATE INDEX IF NOT EXISTS call_message_id_index ON call (message_id)") + db.execSQL("CREATE INDEX IF NOT EXISTS call_peer_index ON call (peer)") + + val foreignKeyViolations: List = SqlUtil.getForeignKeyViolations(db, "call") + if (foreignKeyViolations.isNotEmpty()) { + Log.w(TAG, "Foreign key violations!\n${foreignKeyViolations.joinToString(separator = "\n")}") + throw IllegalStateException("Foreign key violations!") + } + } +}