Adopt libsignal 0.30.0 and ServiceIds for group members.

Co-authored-by: Greyson Parrelli <greyson@signal.org>
This commit is contained in:
Jordan Rose
2023-07-31 10:28:18 -07:00
committed by Greyson Parrelli
parent b11d653fc0
commit a2c3b5d64e
44 changed files with 613 additions and 592 deletions

View File

@@ -60,7 +60,6 @@ import org.whispersystems.signalservice.api.util.UuidUtil
import java.io.Closeable
import java.security.SecureRandom
import java.util.Optional
import java.util.UUID
import java.util.stream.Collectors
import javax.annotation.CheckReturnValue
@@ -861,8 +860,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
writableDatabase.withinTransaction { db ->
val record = getGroup(groupIdV1).get()
val newMembers: MutableList<RecipientId> = DecryptedGroupUtil.membersToUuidList(decryptedGroup.membersList).toRecipientIds()
val pendingMembers: List<RecipientId> = DecryptedGroupUtil.pendingToUuidList(decryptedGroup.pendingMembersList).toRecipientIds()
val newMembers: MutableList<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(decryptedGroup.membersList).toRecipientIds()
val pendingMembers: List<RecipientId> = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.pendingMembersList).toRecipientIds()
newMembers.addAll(pendingMembers)
val droppedMembers: List<RecipientId> = SetUtil.difference(record.members, newMembers).toList()
@@ -915,11 +914,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
val change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().decryptedGroup, decryptedGroup)
val addedMembers: Set<RecipientId> = DecryptedGroupUtil.membersToUuidList(change.newMembersList).toRecipientIds().toSet()
val removedMembers: Set<RecipientId> = DecryptedGroupUtil.removedMembersUuidList(change).toRecipientIds().toSet()
val addedInvites: Set<RecipientId> = DecryptedGroupUtil.pendingToUuidList(change.newPendingMembersList).toRecipientIds().toSet()
val removedInvites: Set<RecipientId> = DecryptedGroupUtil.removedPendingMembersUuidList(change).toRecipientIds().toSet()
val acceptedInvites: Set<RecipientId> = DecryptedGroupUtil.membersToUuidList(change.promotePendingMembersList).toRecipientIds().toSet()
val addedMembers: Set<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(change.newMembersList).toRecipientIds().toSet()
val removedMembers: Set<RecipientId> = DecryptedGroupUtil.removedMembersServiceIdList(change).toRecipientIds().toSet()
val addedInvites: Set<RecipientId> = DecryptedGroupUtil.pendingToServiceIdList(change.newPendingMembersList).toRecipientIds().toSet()
val removedInvites: Set<RecipientId> = DecryptedGroupUtil.removedPendingMembersServiceIdList(change).toRecipientIds().toSet()
val acceptedInvites: Set<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(change.promotePendingMembersList).toRecipientIds().toSet()
unmigratedV1Members -= addedMembers
unmigratedV1Members -= removedMembers
@@ -934,7 +933,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
if (existingGroup.isPresent && existingGroup.get().isV2Group) {
val change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().decryptedGroup, decryptedGroup)
val removed: List<UUID> = DecryptedGroupUtil.removedMembersUuidList(change)
val removed: List<ServiceId> = DecryptedGroupUtil.removedMembersServiceIdList(change)
if (removed.isNotEmpty()) {
val distributionId = existingGroup.get().distributionId!!
@@ -1208,8 +1207,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
DecryptedGroup.parseFrom(decryptedGroupBytes)
}
val bannedMembers: Set<UUID> by lazy {
DecryptedGroupUtil.bannedMembersToUuidSet(decryptedGroup.bannedMembersList)
val bannedMembers: Set<ServiceId> by lazy {
DecryptedGroupUtil.bannedMembersToServiceIdSet(decryptedGroup.bannedMembersList)
}
fun isAdmin(recipient: Recipient): Boolean {
@@ -1243,7 +1242,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
}
if (memberLevel.isAbsent()) {
memberLevel = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, serviceId.get().rawUuid)
memberLevel = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, serviceId.get())
.map { MemberLevel.PENDING_MEMBER }
}
@@ -1265,7 +1264,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
fun getMemberRecipientIds(memberSet: MemberSet): List<RecipientId> {
val includeSelf = memberSet.includeSelf
val selfAciUuid = SignalStore.account().requireAci().rawUuid
val selfAci = SignalStore.account().requireAci()
val selfAciUuid = selfAci.rawUuid
val recipients: MutableList<RecipientId> = ArrayList(decryptedGroup.membersCount + decryptedGroup.pendingMembersCount)
var unknownMembers = 0
@@ -1280,11 +1280,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
}
if (memberSet.includePending) {
for (uuid in DecryptedGroupUtil.pendingToUuidList(decryptedGroup.pendingMembersList)) {
if (UuidUtil.UNKNOWN_UUID == uuid) {
for (serviceId in DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.pendingMembersList)) {
if (serviceId.isUnknown) {
unknownPending++
} else if (includeSelf || selfAciUuid != uuid) {
recipients += RecipientId.from(ACI.from(uuid))
} else if (includeSelf || selfAci != serviceId) {
recipients += RecipientId.from(serviceId)
}
}
}
@@ -1378,11 +1378,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
val aci = SignalStore.account().requireAci()
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, aci.rawUuid).isPresent ||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.pendingMembersList, aci.rawUuid).isPresent
DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, aci).isPresent
}
private fun List<UUID>.toRecipientIds(): MutableList<RecipientId> {
return uuidsToRecipientIds(this)
private fun List<ServiceId>.toRecipientIds(): MutableList<RecipientId> {
return serviceIdsToRecipientIds(this.asSequence())
}
private fun Collection<RecipientId>.serialize(): String {
@@ -1398,15 +1398,14 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
}
}
private fun uuidsToRecipientIds(uuids: List<UUID>): MutableList<RecipientId> {
return uuids
.asSequence()
.map { uuid ->
if (uuid == UuidUtil.UNKNOWN_UUID) {
private fun serviceIdsToRecipientIds(serviceIds: Sequence<ServiceId>): MutableList<RecipientId> {
return serviceIds
.map { serviceId ->
if (serviceId.isUnknown) {
Log.w(TAG, "Saw an unknown UUID when mapping to RecipientIds!")
null
} else {
val id = RecipientId.from(ACI.from(uuid))
val id = RecipientId.from(serviceId)
val remapped = RemappedRecords.getInstance().getRecipient(id)
if (remapped.isPresent) {
Log.w(TAG, "Saw that $id remapped to $remapped. Using the mapping.")
@@ -1422,8 +1421,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
}
private fun getV2GroupMembers(decryptedGroup: DecryptedGroup, shouldRetry: Boolean): List<RecipientId> {
val uuids: List<UUID> = DecryptedGroupUtil.membersToUuidList(decryptedGroup.membersList)
val ids: List<RecipientId> = uuidsToRecipientIds(uuids)
val ids: List<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(decryptedGroup.membersList).toRecipientIds()
return if (RemappedRecords.getInstance().areAnyRemapped(ids)) {
if (shouldRetry) {

View File

@@ -142,7 +142,6 @@ import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.isStory
import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage
import java.io.Closeable
import java.io.IOException
@@ -3089,10 +3088,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
val members: MutableSet<RecipientId> = mutableSetOf()
if (message.isGroupUpdate && message.isV2Group) {
// TODO [greyson][ServiceId] pending members could be ACI's or PNI's
members += message.requireGroupV2Properties().allActivePendingAndRemovedMembers
.distinct()
.map { uuid -> RecipientId.from(ACI.from(uuid)) }
.map { serviceId -> RecipientId.from(serviceId) }
.toList()
members -= Recipient.self().id

View File

@@ -176,7 +176,7 @@ class GroupRecord(
if (isV2Group) {
val serviceId = recipient.serviceId
if (serviceId.isPresent) {
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get().rawUuid)
return DecryptedGroupUtil.findPendingByServiceId(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get())
.isPresent
}
}

View File

@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceIds;
import org.whispersystems.signalservice.api.util.UuidUtil;
@@ -72,9 +73,9 @@ final class GroupsV2UpdateMessageProducer {
* When the revision of the group is 0, the change is very noisy and only the editor is useful.
*/
UpdateDescription describeNewGroup(@NonNull DecryptedGroup group, @NonNull DecryptedGroupChange decryptedGroupChange) {
Optional<DecryptedPendingMember> selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getAci().getRawUuid());
Optional<DecryptedPendingMember> selfPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfIds.getAci());
if (!selfPending.isPresent() && selfIds.getPni() != null) {
selfPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfIds.getPni().getRawUuid());
selfPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfIds.getPni());
}
if (selfPending.isPresent()) {
@@ -310,13 +311,13 @@ final class GroupsV2UpdateMessageProducer {
int notYouInviteCount = 0;
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
boolean newMemberIsYou = selfIds.matches(invitee.getUuid());
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary());
if (newMemberIsYou) {
updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, change.getEditor(), R.drawable.ic_update_group_add_16));
} else {
if (editorIsYou) {
updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, invitee.getUuid(), R.drawable.ic_update_group_add_16));
updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, invitee.getServiceIdBinary(), R.drawable.ic_update_group_add_16));
} else {
notYouInviteCount++;
}
@@ -332,7 +333,7 @@ final class GroupsV2UpdateMessageProducer {
int notYouInviteCount = 0;
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
boolean newMemberIsYou = selfIds.matches(invitee.getUuid());
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary());
if (newMemberIsYou) {
UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByUuid());
@@ -357,14 +358,14 @@ final class GroupsV2UpdateMessageProducer {
int notDeclineCount = 0;
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
boolean decline = invitee.getUuid().equals(change.getEditor());
boolean decline = invitee.getServiceIdBinary().equals(change.getEditor());
if (decline) {
if (editorIsYou) {
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));
}
} else if (selfIds.matches(invitee.getUuid())) {
} else if (selfIds.matches(invitee.getServiceIdBinary())) {
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, change.getEditor(), R.drawable.ic_update_group_decline_16));
} else {
notDeclineCount++;
@@ -384,7 +385,7 @@ final class GroupsV2UpdateMessageProducer {
int notDeclineCount = 0;
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
boolean inviteeWasYou = selfIds.matches(invitee.getUuid());
boolean inviteeWasYou = selfIds.matches(invitee.getServiceIdBinary());
if (inviteeWasYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
@@ -817,14 +818,14 @@ final class GroupsV2UpdateMessageProducer {
}
private UpdateDescription updateDescription(@StringRes int stringRes,
@NonNull ByteString uuid1Bytes,
@NonNull ByteString serviceId1Bytes,
@DrawableRes int iconResource)
{
ACI aci = ACI.parseOrUnknown(uuid1Bytes);
RecipientId recipientId = RecipientId.from(aci);
ACI serviceId = ACI.parseOrUnknown(serviceId1Bytes);
RecipientId recipientId = RecipientId.from(serviceId);
return UpdateDescription.mentioning(
Collections.singletonList(aci),
Collections.singletonList(serviceId),
() -> {
List<RecipientId> recipientIdList = Collections.singletonList(recipientId);
String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, null));
@@ -835,18 +836,18 @@ final class GroupsV2UpdateMessageProducer {
}
private UpdateDescription updateDescription(@StringRes int stringRes,
@NonNull ByteString uuid1Bytes,
@NonNull ByteString uuid2Bytes,
@NonNull ByteString serviceId1Bytes,
@NonNull ByteString serviceId2Bytes,
@DrawableRes int iconResource)
{
ACI aci1 = ACI.parseOrUnknown(uuid1Bytes);
ACI aci2 = ACI.parseOrUnknown(uuid2Bytes);
ACI serviceId1 = ACI.parseOrUnknown(serviceId1Bytes);
ACI serviceId2 = ACI.parseOrUnknown(serviceId2Bytes);
RecipientId recipientId1 = RecipientId.from(aci1);
RecipientId recipientId2 = RecipientId.from(aci2);
RecipientId recipientId1 = RecipientId.from(serviceId1);
RecipientId recipientId2 = RecipientId.from(serviceId2);
return UpdateDescription.mentioning(
Arrays.asList(aci1, aci2),
Arrays.asList(serviceId1, serviceId2),
() -> {
List<RecipientId> recipientIdList = Arrays.asList(recipientId1, recipientId2);
String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, null));
@@ -858,15 +859,15 @@ final class GroupsV2UpdateMessageProducer {
}
private UpdateDescription updateDescription(@StringRes int stringRes,
@NonNull ByteString uuid1Bytes,
@NonNull ByteString serviceId1Bytes,
@NonNull Object formatArg,
@DrawableRes int iconResource)
{
ACI aci = ACI.parseOrUnknown(uuid1Bytes);
RecipientId recipientId = RecipientId.from(aci);
ACI serviceId = ACI.parseOrUnknown(serviceId1Bytes);
RecipientId recipientId = RecipientId.from(serviceId);
return UpdateDescription.mentioning(
Collections.singletonList(aci),
Collections.singletonList(serviceId),
() -> {
List<RecipientId> recipientIdList = Collections.singletonList(recipientId);
String templateString = context.getString(stringRes, makePlaceholders(recipientIdList, Collections.singletonList(formatArg)));
@@ -879,15 +880,15 @@ final class GroupsV2UpdateMessageProducer {
private UpdateDescription updateDescription(@PluralsRes int stringRes,
int quantity,
@NonNull ByteString uuid1Bytes,
@NonNull ByteString serviceId1Bytes,
@NonNull Object formatArg,
@DrawableRes int iconResource)
{
ACI aci = ACI.parseOrUnknown(uuid1Bytes);
RecipientId recipientId = RecipientId.from(aci);
ACI serviceId = ACI.parseOrUnknown(serviceId1Bytes);
RecipientId recipientId = RecipientId.from(serviceId);
return UpdateDescription.mentioning(
Collections.singletonList(aci),
Collections.singletonList(serviceId),
() -> {
List<RecipientId> recipientIdList = Collections.singletonList(recipientId);
String templateString = context.getResources().getQuantityString(stringRes, quantity, makePlaceholders(recipientIdList, Collections.singletonList(formatArg)));

View File

@@ -346,7 +346,7 @@ public abstract class MessageRecord extends DisplayRecord {
}
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), SignalStore.account().requireAci().getRawUuid()).isPresent();
boolean invited = DecryptedGroupUtil.findPendingByServiceId(groupState.getPendingMembersList(), SignalStore.account().requireAci()).isPresent();
if (decryptedGroupV2Context.hasChange()) {
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());