From 4166e7931e6b6e79dbc6ecbbf4a7d0ba94e434bc Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Fri, 20 Nov 2020 13:26:17 -0500 Subject: [PATCH] Fix membership diffs that occur during a GV1->GV2 migration. Co-authored-by: Alan Evans --- .../securesms/database/GroupDatabase.java | 24 ++++++++++++++++++- .../database/model/MessageRecord.java | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java index ec4c145c84..4be2f5e6bc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -483,6 +483,11 @@ public final class GroupDatabase extends Database { /** * Migrates a V1 group to a V2 group. + * + * @param decryptedGroup The state that represents the group on the server. This will be used to + * determine if we need to save our old membership list and stuff. It will + * *not* be stored as the definitive group state as-is. In order to ensure + * proper diffing, we modify this model to have our V1 membership. */ public @NonNull GroupId.V2 migrateToV2(@NonNull GroupId.V1 groupIdV1, @NonNull DecryptedGroup decryptedGroup) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); @@ -513,7 +518,7 @@ public final class GroupDatabase extends Database { DatabaseFactory.getRecipientDatabase(context).updateGroupId(groupIdV1, groupIdV2); - update(groupMasterKey, decryptedGroup); + update(groupMasterKey, updateToHaveV1Membership(decryptedGroup, record.getMembers())); db.setTransactionSuccessful(); } finally { @@ -523,6 +528,23 @@ public final class GroupDatabase extends Database { return groupIdV2; } + private static DecryptedGroup updateToHaveV1Membership(@NonNull DecryptedGroup serverGroup, @NonNull List v1Members) { + DecryptedGroup.Builder builder = serverGroup.toBuilder(); + builder.clearMembers(); + + for (RecipientId v1MemberId : v1Members) { + Recipient v1Member = Recipient.resolved(v1MemberId); + if (v1Member.hasUuid()) { + builder.addMembers(DecryptedMember.newBuilder() + .setUuid(UuidUtil.toByteString(v1Member.getUuid().get())) + .setRole(Member.Role.ADMINISTRATOR) + .build()); + } + } + + return builder.build(); + } + public void update(@NonNull GroupMasterKey groupMasterKey, @NonNull DecryptedGroup decryptedGroup) { update(GroupId.v2(groupMasterKey), decryptedGroup); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index 885e21ed57..c95771bcbf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -197,7 +197,7 @@ public abstract class MessageRecord extends DisplayRecord { DecryptedGroupV2Context decryptedGroupV2Context = DecryptedGroupV2Context.parseFrom(decoded); GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().getUuid().get()); - if (decryptedGroupV2Context.hasChange() && decryptedGroupV2Context.getGroupState().getRevision() != 0) { + if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) { return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange())); } else { return updateMessageProducer.describeNewGroup(decryptedGroupV2Context.getGroupState(), decryptedGroupV2Context.getChange());