diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt index 801cd2f48e..24499263f3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt @@ -513,7 +513,8 @@ object BackupRepository { eventTimer.emit("store-db-snapshot") val exportState = ExportState(backupTime = currentTime, mediaBackupEnabled = mediaBackupEnabled) - val selfRecipientId = dbSnapshot.recipientTable.getByAci(signalStoreSnapshot.accountValues.aci!!).get().toLong().let { RecipientId.from(it) } + val selfAci = signalStoreSnapshot.accountValues.aci!! + val selfRecipientId = dbSnapshot.recipientTable.getByAci(selfAci).get().toLong().let { RecipientId.from(it) } var frameCount = 0L @@ -542,7 +543,7 @@ object BackupRepository { } progressEmitter?.onRecipient() - RecipientArchiveProcessor.export(dbSnapshot, signalStoreSnapshot, exportState, selfRecipientId) { + RecipientArchiveProcessor.export(dbSnapshot, signalStoreSnapshot, exportState, selfRecipientId, selfAci) { writer.write(it) eventTimer.emit("recipient") frameCount++ diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/RecipientTableArchiveExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/RecipientTableArchiveExtensions.kt index 95f1a915a2..24c8c815bf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/RecipientTableArchiveExtensions.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/RecipientTableArchiveExtensions.kt @@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.recipients.RecipientId +import org.whispersystems.signalservice.api.push.ServiceId /** * Fetches all individual contacts for backups and returns the result as an iterator. @@ -76,7 +77,7 @@ fun RecipientTable.getContactsForBackup(selfId: Long): ContactArchiveExporter { return ContactArchiveExporter(cursor, selfId) } -fun RecipientTable.getGroupsForBackup(): GroupArchiveExporter { +fun RecipientTable.getGroupsForBackup(selfAci: ServiceId.ACI): GroupArchiveExporter { val cursor = readableDatabase .select( "${RecipientTable.TABLE_NAME}.${RecipientTable.ID}", @@ -87,6 +88,7 @@ fun RecipientTable.getGroupsForBackup(): GroupArchiveExporter { "${GroupTable.TABLE_NAME}.${GroupTable.V2_MASTER_KEY}", "${GroupTable.TABLE_NAME}.${GroupTable.SHOW_AS_STORY_STATE}", "${GroupTable.TABLE_NAME}.${GroupTable.TITLE}", + "${GroupTable.TABLE_NAME}.${GroupTable.ACTIVE}", "${GroupTable.TABLE_NAME}.${GroupTable.V2_DECRYPTED_GROUP}" ) .from( @@ -103,7 +105,7 @@ fun RecipientTable.getGroupsForBackup(): GroupArchiveExporter { ) .run() - return GroupArchiveExporter(cursor) + return GroupArchiveExporter(selfAci, cursor) } /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/GroupArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/GroupArchiveExporter.kt index 889c555f69..82d56442de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/GroupArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/GroupArchiveExporter.kt @@ -27,13 +27,14 @@ import org.thoughtcrime.securesms.database.GroupTable import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.RecipientTableCursorUtil import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor +import org.whispersystems.signalservice.api.push.ServiceId import java.io.Closeable /** * Provides a nice iterable interface over a [RecipientTable] cursor, converting rows to [ArchiveRecipient]s. * Important: Because this is backed by a cursor, you must close it. It's recommended to use `.use()` or try-with-resources. */ -class GroupArchiveExporter(private val cursor: Cursor) : Iterator, Closeable { +class GroupArchiveExporter(private val selfAci: ServiceId.ACI, private val cursor: Cursor) : Iterator, Closeable { override fun hasNext(): Boolean { return cursor.count > 0 && !cursor.isLast @@ -47,6 +48,7 @@ class GroupArchiveExporter(private val cursor: Cursor) : Iterator isActive || m.aciBytes != selfAciBytes } + return Group.GroupSnapshot( title = Group.GroupAttributeBlob(title = this.title), avatarUrl = this.avatar, disappearingMessagesTimer = this.disappearingMessagesTimer?.takeIf { it.duration > 0 }?.let { Group.GroupAttributeBlob(disappearingMessagesDuration = it.duration) }, accessControl = this.accessControl?.toRemote(), version = this.revision, - members = this.members.map { it.toRemote() }, + members = this.members.filter(memberFilter).map { it.toRemote() }, membersPendingProfileKey = this.pendingMembers.map { it.toRemote() }, membersPendingAdminApproval = this.requestingMembers.map { it.toRemote() }, inviteLinkPassword = this.inviteLinkPassword, diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/RecipientArchiveProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/RecipientArchiveProcessor.kt index 7af5c16e4e..e8fe24dac8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/RecipientArchiveProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/RecipientArchiveProcessor.kt @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId +import org.whispersystems.signalservice.api.push.ServiceId /** * Handles importing/exporting [ArchiveRecipient] frames for an archive. @@ -33,7 +34,7 @@ object RecipientArchiveProcessor { val TAG = Log.tag(RecipientArchiveProcessor::class.java) - fun export(db: SignalDatabase, signalStore: SignalStore, exportState: ExportState, selfRecipientId: RecipientId, emitter: BackupFrameEmitter) { + fun export(db: SignalDatabase, signalStore: SignalStore, exportState: ExportState, selfRecipientId: RecipientId, selfAci: ServiceId.ACI, emitter: BackupFrameEmitter) { val releaseChannelId = signalStore.releaseChannelValues.releaseChannelRecipientId if (releaseChannelId != null) { exportState.recipientIds.add(releaseChannelId.toLong()) @@ -58,7 +59,7 @@ object RecipientArchiveProcessor { } } - db.recipientTable.getGroupsForBackup().use { reader -> + db.recipientTable.getGroupsForBackup(selfAci).use { reader -> for (recipient in reader) { exportState.recipientIds.add(recipient.id) emitter.emit(Frame(recipient = recipient)) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt index f6affbe4b2..481f0b417b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/InputReadyState.kt @@ -21,7 +21,7 @@ class InputReadyState( val isUnauthorized: Boolean, val threadContainsSms: Boolean ) { - private val selfMemberLevel: GroupTable.MemberLevel? = groupRecord?.memberLevel(Recipient.self()) + private val selfMemberLevel: GroupTable.MemberLevel? = groupRecord?.let { if (it.isActive) it.memberLevel(Recipient.self()) else GroupTable.MemberLevel.NOT_A_MEMBER } val isAnnouncementGroup: Boolean? = groupRecord?.isAnnouncementGroup val isActiveGroup: Boolean? = if (selfMemberLevel == null) null else selfMemberLevel != GroupTable.MemberLevel.NOT_A_MEMBER diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV2UpdateSelfProfileKeyJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV2UpdateSelfProfileKeyJob.java index c697b36531..e33d67ed31 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV2UpdateSelfProfileKeyJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/GroupV2UpdateSelfProfileKeyJob.java @@ -119,13 +119,14 @@ public final class GroupV2UpdateSelfProfileKeyJob extends BaseJob { } ByteString selfUuidBytes = Recipient.self().requireAci().toByteString(); + boolean isActive = group.get().isActive(); DecryptedMember selfMember = group.get().requireV2GroupProperties().getDecryptedGroup().members .stream() .filter(m -> m.aciBytes.equals(selfUuidBytes)) .findFirst() .orElse(null); - if (selfMember != null && !selfMember.profileKey.equals(selfProfileKey)) { + if (isActive && selfMember != null && !selfMember.profileKey.equals(selfProfileKey)) { Log.w(TAG, "Profile key mismatch for group " + id + " -- enqueueing job"); foundMismatch = true; AppDependencies.getJobManager().add(GroupV2UpdateSelfProfileKeyJob.withQueueLimits(id));