Fix incorrect ACI/PNI storage for revoked invites in group updates.
This commit is contained in:
parent
10ae26c924
commit
86d78d2e5d
4 changed files with 103 additions and 4 deletions
|
@ -85,7 +85,6 @@ import org.whispersystems.signalservice.api.util.UuidUtil
|
|||
import org.whispersystems.signalservice.api.util.toByteArray
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
import java.util.HashMap
|
||||
import java.util.LinkedList
|
||||
import java.util.Queue
|
||||
import java.util.concurrent.Callable
|
||||
|
|
|
@ -114,6 +114,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V254_AddChatFolderC
|
|||
import org.thoughtcrime.securesms.database.helpers.migration.V255_AddCallTableLogIndex
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V256_FixIncrementalDigestColumns
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V257_CreateBackupMediaSyncTable
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V258_FixGroupRevokedInviteeUpdate
|
||||
|
||||
/**
|
||||
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
||||
|
@ -230,10 +231,11 @@ object SignalDatabaseMigrations {
|
|||
254 to V254_AddChatFolderConstraint,
|
||||
255 to V255_AddCallTableLogIndex,
|
||||
256 to V256_FixIncrementalDigestColumns,
|
||||
257 to V257_CreateBackupMediaSyncTable
|
||||
257 to V257_CreateBackupMediaSyncTable,
|
||||
258 to V258_FixGroupRevokedInviteeUpdate
|
||||
)
|
||||
|
||||
const val DATABASE_VERSION = 257
|
||||
const val DATABASE_VERSION = 258
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import androidx.core.content.contentValuesOf
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
import okio.IOException
|
||||
import org.signal.core.util.forEach
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.requireBlob
|
||||
import org.signal.core.util.requireLong
|
||||
import org.thoughtcrime.securesms.backup.v2.proto.GroupInvitationRevokedUpdate
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
|
||||
/**
|
||||
* Ensure we store ACIs only in the ACI fields and non-byte prefixed PNIs only in the PNI fields of
|
||||
* [GroupInvitationRevokedUpdate.Invitee] in [GroupInvitationRevokedUpdate].
|
||||
*/
|
||||
@Suppress("ClassName")
|
||||
object V258_FixGroupRevokedInviteeUpdate : SignalDatabaseMigration {
|
||||
|
||||
private val TAG = Log.tag(V258_FixGroupRevokedInviteeUpdate::class)
|
||||
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
val messageExtrasFixes = mutableListOf<Pair<Long, ByteArray>>()
|
||||
|
||||
db.query("message", arrayOf("_id", "message_extras"), "message_extras IS NOT NULL AND type & 0x10000 != 0", null, null, null, null)
|
||||
.forEach { cursor ->
|
||||
val blob = cursor.requireBlob("message_extras")!!
|
||||
|
||||
val messageExtras: MessageExtras? = try {
|
||||
MessageExtras.ADAPTER.decode(blob)
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Unable to decode message extras", e)
|
||||
null
|
||||
}
|
||||
|
||||
if (messageExtras?.gv2UpdateDescription?.groupChangeUpdate?.updates?.any { it.groupInvitationRevokedUpdate != null } != true) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val groupUpdateDescription = messageExtras.gv2UpdateDescription
|
||||
val groupUpdate = groupUpdateDescription.groupChangeUpdate!!
|
||||
val updates = groupUpdate.updates.toMutableList()
|
||||
|
||||
updates
|
||||
.replaceAll { change ->
|
||||
if (change.groupInvitationRevokedUpdate != null) {
|
||||
val invitees = change.groupInvitationRevokedUpdate.invitees.toMutableList()
|
||||
|
||||
invitees.replaceAll { invitee ->
|
||||
val inviteeAciFieldServiceId = ServiceId.parseOrNull(invitee.inviteeAci)
|
||||
val inviteePniFieldServiceId = ServiceId.parseOrNull(invitee.inviteePni)
|
||||
|
||||
if (inviteeAciFieldServiceId is ServiceId.PNI) {
|
||||
// We have an obvious PNI in the ACI field, move to PNI field without byte prefix
|
||||
invitee.copy(inviteeAci = null, inviteePni = inviteeAciFieldServiceId.toByteStringWithoutPrefix())
|
||||
} else if (inviteePniFieldServiceId is ServiceId.PNI) {
|
||||
// We have a byte-prefixed encoded PNI in the PNI field, update to remove byte prefix
|
||||
invitee.copy(inviteePni = inviteePniFieldServiceId.toByteStringWithoutPrefix())
|
||||
} else {
|
||||
// ACI field doesn't have an obvious PNI and PNI doesn't have a byte-prefixed PNI, no fix needed
|
||||
invitee
|
||||
}
|
||||
}
|
||||
|
||||
change.copy(groupInvitationRevokedUpdate = change.groupInvitationRevokedUpdate.copy(invitees = invitees))
|
||||
} else {
|
||||
change
|
||||
}
|
||||
}
|
||||
|
||||
val updatedMessageExtras = messageExtras.copy(
|
||||
gv2UpdateDescription = groupUpdateDescription.copy(
|
||||
groupChangeUpdate = groupUpdate.copy(
|
||||
updates = updates
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
messageExtrasFixes += cursor.requireLong("_id") to updatedMessageExtras.encode()
|
||||
}
|
||||
|
||||
messageExtrasFixes.forEach { (id, extras) ->
|
||||
db.update("message", contentValuesOf("message_extras" to extras), "_id = $id", null)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -161,9 +161,10 @@ public class ApplicationMigrations {
|
|||
static final int SVR2_ENCLAVE_UPDATE_2 = 117;
|
||||
static final int WALLPAPER_MIGRATION_CLEANUP = 118;
|
||||
static final int AEP_INTRODUCTION = 119;
|
||||
static final int GROUP_EXTRAS_DB_FIX = 120;
|
||||
}
|
||||
|
||||
public static final int CURRENT_VERSION = 119;
|
||||
public static final int CURRENT_VERSION = 120;
|
||||
|
||||
/**
|
||||
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
|
||||
|
@ -738,6 +739,10 @@ public class ApplicationMigrations {
|
|||
jobs.put(Version.AEP_INTRODUCTION, new AepMigrationJob());
|
||||
}
|
||||
|
||||
if (lastSeenVersion < Version.GROUP_EXTRAS_DB_FIX) {
|
||||
jobs.put(Version.GROUP_EXTRAS_DB_FIX, new DatabaseMigrationJob());
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue