Fix export bugs causing validation errors.

This commit is contained in:
Cody Henthorne 2024-11-25 16:46:24 -05:00 committed by Greyson Parrelli
parent 3e699a132b
commit 84cb0d357b
4 changed files with 38 additions and 7 deletions

View file

@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.backup.v2.exporters.ChatItemArchiveExporter
import org.thoughtcrime.securesms.backup.v2.importer.ChatItemArchiveImporter
import org.thoughtcrime.securesms.database.GroupTable
import org.thoughtcrime.securesms.database.MessageTable
import org.thoughtcrime.securesms.database.MessageTypes
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.recipients.RecipientId
@ -78,6 +79,16 @@ fun MessageTable.getMessagesForBackup(db: SignalDatabase, backupTime: Long, medi
"""
)
// If someone re-registers with a new phone number, previous outgoing messages will no longer be associated with self.
// This cleans it up by changing the from to be the current self id for all outgoing messages.
db.rawWritableDatabase.execSQL(
"""
UPDATE ${MessageTable.TABLE_NAME}
SET ${MessageTable.FROM_RECIPIENT_ID} = ${selfRecipientId.toLong()}
WHERE (${MessageTable.TYPE} & ${MessageTypes.BASE_TYPE_MASK}) IN (${MessageTypes.OUTGOING_MESSAGE_TYPES.joinToString(",")})
"""
)
return ChatItemArchiveExporter(
db = db,
backupStartTime = backupTime,

View file

@ -237,7 +237,12 @@ class ChatItemArchiveExporter(
}
MessageTypes.isGroupV2(record.type) && MessageTypes.isGroupUpdate(record.type) -> {
builder.updateMessage = record.toRemoteGroupUpdate() ?: continue
val update = record.toRemoteGroupUpdate() ?: continue
if (update.groupChange!!.updates.isEmpty()) {
Log.w(TAG, "Group update record with ID ${record.id} missing updates. Skipping.")
continue
}
builder.updateMessage = update
}
MessageTypes.isGroupV1MigrationEvent(record.type) -> {
@ -541,7 +546,10 @@ private fun CallTable.Call.toRemoteCallUpdate(db: SignalDatabase, messageRecord:
CallTable.Event.NOT_ACCEPTED -> IndividualCall.State.NOT_ACCEPTED
CallTable.Event.ONGOING -> IndividualCall.State.ACCEPTED
CallTable.Event.DELETE -> return null
else -> IndividualCall.State.UNKNOWN_STATE
else -> {
Log.w(TAG, "Unable to map 1:1 call state from event: ${this.event.name}")
IndividualCall.State.UNKNOWN_STATE
}
},
startedCallTimestamp = this.timestamp,
read = messageRecord.read

View file

@ -6,6 +6,7 @@
package org.thoughtcrime.securesms.database.model
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.signal.core.util.StringUtil
import org.signal.core.util.isNullOrEmpty
import org.signal.storageservice.protos.groups.AccessControl
@ -50,7 +51,7 @@ import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedOtherUserToGroupUpd
import org.thoughtcrime.securesms.backup.v2.proto.SelfInvitedToGroupUpdate
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil
import org.whispersystems.signalservice.api.push.ServiceId.Companion.parseOrNull
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceIds
import org.whispersystems.signalservice.api.util.UuidUtil
import java.util.LinkedList
@ -131,7 +132,7 @@ object GroupsV2UpdateMessageConverter {
}
val updates: MutableList<GroupChangeChatUpdate.Update> = LinkedList()
var editorUnknown = change.editorServiceIdBytes.size == 0
val editorServiceId = if (editorUnknown) null else parseOrNull(change.editorServiceIdBytes)
val editorServiceId = if (editorUnknown) null else ServiceId.parseOrNull(change.editorServiceIdBytes)
if (editorServiceId == null || editorServiceId.isUnknown) {
editorUnknown = true
}
@ -253,10 +254,13 @@ object GroupsV2UpdateMessageConverter {
)
)
} else {
val serviceId = ServiceId.parseOrNull(invitee.serviceIdBytes)
revokedInvitees.add(
GroupInvitationRevokedUpdate.Invitee(
inviteeAci = invitee.serviceIdBytes
)
when (serviceId) {
is ServiceId.ACI -> GroupInvitationRevokedUpdate.Invitee(inviteeAci = serviceId.toByteString())
is ServiceId.PNI -> GroupInvitationRevokedUpdate.Invitee(inviteePni = serviceId.toByteStringWithoutPrefix())
else -> throw IllegalStateException()
}
)
}
}
@ -465,6 +469,7 @@ object GroupsV2UpdateMessageConverter {
}
)
}
AccessRequired.ADMINISTRATOR -> {
groupLinkEnabled = true
updates.add(
@ -485,6 +490,7 @@ object GroupsV2UpdateMessageConverter {
}
)
}
AccessRequired.UNSATISFIABLE -> {
updates.add(
GroupChangeChatUpdate.Update(
@ -494,6 +500,7 @@ object GroupsV2UpdateMessageConverter {
)
)
}
else -> {}
}
if (!groupLinkEnabled && change.newInviteLinkPassword.size > 0) {

View file

@ -1,12 +1,14 @@
package org.whispersystems.signalservice.api.push
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.signal.libsignal.protocol.ServiceId.InvalidServiceIdException
import org.signal.libsignal.protocol.SignalProtocolAddress
import org.signal.libsignal.protocol.logging.Log
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.push.ServiceId.PNI
import org.whispersystems.signalservice.api.util.UuidUtil
import org.whispersystems.signalservice.api.util.toByteArray
import java.util.UUID
import org.signal.libsignal.protocol.ServiceId as LibSignalServiceId
import org.signal.libsignal.protocol.ServiceId.Aci as LibSignalAci
@ -229,5 +231,8 @@ sealed class ServiceId(val libSignalServiceId: LibSignalServiceId) {
/** String version without the PNI: prefix. This is only for specific proto fields. For application storage, prefer [toString]. */
fun toStringWithoutPrefix(): String = rawUuid.toString()
/** [ByteString] version without the PNI byte prefix. */
fun toByteStringWithoutPrefix(): ByteString = rawUuid.toByteArray().toByteString()
}
}