Fix pni in aci only field of decline invite for backupv2.

This commit is contained in:
Cody Henthorne
2025-02-26 09:54:24 -05:00
committed by Greyson Parrelli
parent 0b3a949264
commit 8b6b0a30e5
5 changed files with 87 additions and 5 deletions

View File

@@ -122,6 +122,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V263_InAppPaymentsS
import org.thoughtcrime.securesms.database.helpers.migration.V264_FixGroupAddMemberUpdate
import org.thoughtcrime.securesms.database.helpers.migration.V265_FixFtsTriggers
import org.thoughtcrime.securesms.database.helpers.migration.V266_UniqueThreadPinOrder
import org.thoughtcrime.securesms.database.helpers.migration.V267_FixGroupInvitationDeclinedUpdate
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@@ -247,10 +248,11 @@ object SignalDatabaseMigrations {
263 to V263_InAppPaymentsSubscriberTableRebuild,
264 to V264_FixGroupAddMemberUpdate,
265 to V265_FixFtsTriggers,
266 to V266_UniqueThreadPinOrder
266 to V266_UniqueThreadPinOrder,
267 to V267_FixGroupInvitationDeclinedUpdate
)
const val DATABASE_VERSION = 266
const val DATABASE_VERSION = 267
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {

View File

@@ -0,0 +1,74 @@
/*
* 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.GroupInvitationDeclinedUpdate
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
import org.whispersystems.signalservice.api.push.ServiceId
/**
* Ensure we store ACIs only in the ACI only-field and null for PNIs for field [GroupInvitationDeclinedUpdate.inviteeAci] in [GroupInvitationDeclinedUpdate].
*/
@Suppress("ClassName")
object V267_FixGroupInvitationDeclinedUpdate : SignalDatabaseMigration {
private val TAG = Log.tag(V267_FixGroupInvitationDeclinedUpdate::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.groupInvitationDeclinedUpdate != null } != true) {
return@forEach
}
val groupUpdateDescription = messageExtras.gv2UpdateDescription
val groupUpdate = groupUpdateDescription.groupChangeUpdate!!
val updates = groupUpdate.updates.toMutableList()
updates
.replaceAll { change ->
if (change.groupInvitationDeclinedUpdate != null && ServiceId.parseOrNull(change.groupInvitationDeclinedUpdate.inviteeAci) is ServiceId.PNI) {
change.copy(groupInvitationDeclinedUpdate = change.groupInvitationDeclinedUpdate.copy(inviteeAci = null))
} 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)
}
}
}

View File

@@ -241,9 +241,10 @@ object GroupsV2UpdateMessageConverter {
for (invitee in change.deletePendingMembers) {
val decline = invitee.serviceIdBytes == editorAci
if (decline) {
val inviteeServiceId = ServiceId.parseOrNull(invitee.serviceIdBytes)
updates.add(
GroupChangeChatUpdate.Update(
groupInvitationDeclinedUpdate = GroupInvitationDeclinedUpdate(inviteeAci = invitee.serviceIdBytes)
groupInvitationDeclinedUpdate = GroupInvitationDeclinedUpdate(inviteeAci = if (inviteeServiceId is ServiceId.ACI) invitee.serviceIdBytes else null)
)
)
} else if (selfIds.matches(invitee.serviceIdBytes)) {

View File

@@ -450,7 +450,7 @@ final class GroupsV2UpdateMessageProducer {
}
private void describeGroupInvitationDeclinedUpdate(@NonNull GroupInvitationDeclinedUpdate update, @NonNull List<UpdateDescription> updates) {
if (selfIds.matches(update.inviteeAci)) {
if (update.inviteeAci != null && selfIds.matches(update.inviteeAci)) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
} else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group), R.drawable.ic_update_group_decline_16));

View File

@@ -172,9 +172,10 @@ public class ApplicationMigrations {
static final int DUPLICATE_E164_FIX = 128;
static final int FTS_TRIGGER_FIX = 129;
static final int THREAD_TABLE_PINNED_MIGRATION = 130;
static final int GROUP_DECLINE_INVITE_FIX = 131;
}
public static final int CURRENT_VERSION = 130;
public static final int CURRENT_VERSION = 131;
/**
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
@@ -793,6 +794,10 @@ public class ApplicationMigrations {
jobs.put(Version.THREAD_TABLE_PINNED_MIGRATION, new DatabaseMigrationJob());
}
if (lastSeenVersion < Version.GROUP_DECLINE_INVITE_FIX) {
jobs.put(Version.GROUP_DECLINE_INVITE_FIX, new DatabaseMigrationJob());
}
return jobs;
}