Prevent accepted group message request from resetting when restored from storage.

This commit is contained in:
Cody Henthorne 2026-06-05 13:47:34 -04:00
parent 8560ab0515
commit f2fd3e63c8
3 changed files with 37 additions and 0 deletions

View File

@ -2128,6 +2128,15 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
}
fun isProfileSharing(groupId: GroupId): Boolean {
return readableDatabase
.select(PROFILE_SHARING)
.from(TABLE_NAME)
.where("$GROUP_ID = ?", groupId.toString())
.run()
.readToSingleBoolean(defaultValue = false)
}
fun setNotificationChannel(id: RecipientId, notificationChannel: String?) {
val contentValues = ContentValues(1).apply {
put(NOTIFICATION_CHANNEL, notificationChannel)

View File

@ -713,6 +713,11 @@ class GroupsV2StateProcessor private constructor(
return
}
if (SignalDatabase.recipients.isProfileSharing(groupId)) {
Log.i(TAG, "Profile sharing already enabled for $groupId. Leaving as-is.")
return
}
val selfAsMember = DecryptedGroupUtil.findMemberByAci(newLocalState.members, aci).orNull()
val selfAsPending = DecryptedGroupUtil.findPendingByServiceId(newLocalState.pendingMembers, aci).orNull()

View File

@ -142,6 +142,8 @@ class GroupsV2StateProcessorTest {
mockkObject(ProfileAndMessageHelper)
every { ProfileAndMessageHelper.create(any(), any(), any()) } returns profileAndMessageHelper
every { recipientTable.isProfileSharing(groupId) } answers { false }
every { groupsV2Operations.forGroup(secretParams) } answers { callOriginal() }
processor = GroupsV2StateProcessor.forGroup(serviceIds, masterKey, secretParams)
@ -1462,4 +1464,25 @@ class GroupsV2StateProcessorTest {
verify { groupTable.create(masterKey, result.latestServer!!, null, null) }
verify(exactly = 0) { recipientTable.rotateStorageId(any()) }
}
@Test
fun `when group already has profile sharing enabled, then setProfileSharing does not re-derive it from membership`() {
val joinedAtRevision = 1
val newLocalState = DecryptedGroup(
revision = joinedAtRevision,
members = listOf(member(otherAci), member(selfAci, joinedAt = joinedAtRevision))
)
val addedByOtherChange = DecryptedGroupChange(
revision = joinedAtRevision,
editorServiceIdBytes = otherAci.toByteString()
)
val groupStateDiff = GroupStateDiff(previousGroupState = null, changedGroupState = newLocalState, change = addedByOtherChange)
every { recipientTable.isProfileSharing(groupId) } answers { true }
profileAndMessageHelper.setProfileSharing(groupStateDiff, newLocalState, needsAvatarFetch = true)
verify { recipientTable.isProfileSharing(groupId) }
verify(exactly = 0) { recipientTable.setProfileSharing(any(), any()) }
}
}