Update Groups.proto to match shared spec.

This commit is contained in:
Greyson Parrelli
2026-01-13 14:01:35 -05:00
parent 2e4665e5c4
commit bd38c4f5d2
75 changed files with 779 additions and 757 deletions
@@ -11,9 +11,9 @@ import org.signal.core.util.readToList
import org.signal.core.util.requireLong import org.signal.core.util.requireLong
import org.signal.core.util.withinTransaction import org.signal.core.util.withinTransaction
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
@@ -12,8 +12,8 @@ import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.IncomingMessage
import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.profiles.ProfileName
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
@@ -3,9 +3,9 @@ package org.thoughtcrime.securesms.testing
import okio.ByteString.Companion.toByteString import okio.ByteString.Companion.toByteString
import org.signal.core.models.ServiceId.ACI import org.signal.core.models.ServiceId.ACI
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
@@ -14,14 +14,14 @@ import org.signal.core.util.requireInt
import org.signal.core.util.requireLong import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullBlob import org.signal.core.util.requireNonNullBlob
import org.signal.core.util.requireString import org.signal.core.util.requireString
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
import org.thoughtcrime.securesms.backup.v2.ArchiveGroup import org.thoughtcrime.securesms.backup.v2.ArchiveGroup
import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient
import org.thoughtcrime.securesms.backup.v2.proto.Group import org.thoughtcrime.securesms.backup.v2.proto.Group
@@ -11,15 +11,15 @@ import org.signal.core.util.Base64
import org.signal.core.util.toInt import org.signal.core.util.toInt
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.libsignal.zkgroup.groups.GroupSecretParams import org.signal.libsignal.zkgroup.groups.GroupSecretParams
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import org.signal.storageservice.protos.groups.local.DecryptedTimer import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
import org.thoughtcrime.securesms.backup.v2.ArchiveGroup import org.thoughtcrime.securesms.backup.v2.ArchiveGroup
import org.thoughtcrime.securesms.backup.v2.proto.Group import org.thoughtcrime.securesms.backup.v2.proto.Group
import org.thoughtcrime.securesms.backup.v2.util.toLocal import org.thoughtcrime.securesms.backup.v2.util.toLocal
@@ -23,9 +23,9 @@ import org.signal.core.util.requireInt
import org.signal.core.util.requireLong import org.signal.core.util.requireLong
import org.signal.core.util.requireObject import org.signal.core.util.requireObject
import org.signal.core.util.requireString import org.signal.core.util.requireString
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
import org.thoughtcrime.securesms.database.CallTable import org.thoughtcrime.securesms.database.CallTable
import org.thoughtcrime.securesms.database.CallTable.Direction import org.thoughtcrime.securesms.database.CallTable.Direction
import org.thoughtcrime.securesms.database.CallTable.Event import org.thoughtcrime.securesms.database.CallTable.Event
@@ -10,7 +10,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.rx3.asObservable import kotlinx.coroutines.rx3.asObservable
import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery
import org.thoughtcrime.securesms.database.CallTable import org.thoughtcrime.securesms.database.CallTable
import org.thoughtcrime.securesms.database.MediaTable import org.thoughtcrime.securesms.database.MediaTable
@@ -41,9 +41,9 @@ import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.libsignal.zkgroup.groups.GroupSecretParams import org.signal.libsignal.zkgroup.groups.GroupSecretParams
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsement import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsement
import org.signal.libsignal.zkgroup.groupsend.GroupSendFullToken import org.signal.libsignal.zkgroup.groupsend.GroupSendFullToken
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.thoughtcrime.securesms.contacts.paged.ContactSearchSortOrder import org.thoughtcrime.securesms.contacts.paged.ContactSearchSortOrder
import org.thoughtcrime.securesms.contacts.paged.collections.ContactSearchIterator import org.thoughtcrime.securesms.contacts.paged.collections.ContactSearchIterator
import org.thoughtcrime.securesms.crypto.SenderKeyUtil import org.thoughtcrime.securesms.crypto.SenderKeyUtil
@@ -47,7 +47,7 @@ import org.signal.libsignal.protocol.InvalidKeyException
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential
import org.signal.libsignal.zkgroup.profiles.ProfileKey import org.signal.libsignal.zkgroup.profiles.ProfileKey
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.thoughtcrime.securesms.badges.Badges.toDatabaseBadge import org.thoughtcrime.securesms.badges.Badges.toDatabaseBadge
import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.color.MaterialColor import org.thoughtcrime.securesms.color.MaterialColor
@@ -10,7 +10,7 @@ import androidx.core.content.contentValuesOf
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.signal.core.util.requireLong import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullBlob import org.signal.core.util.requireNonNullBlob
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.thoughtcrime.securesms.database.SQLiteDatabase import org.thoughtcrime.securesms.database.SQLiteDatabase
/** /**
@@ -2,8 +2,8 @@ package org.thoughtcrime.securesms.database.model
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
import org.thoughtcrime.securesms.database.GroupTable import org.thoughtcrime.securesms.database.GroupTable
import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.groups.GroupAccessControl import org.thoughtcrime.securesms.groups.GroupAccessControl
@@ -10,14 +10,14 @@ import org.signal.core.models.ServiceId
import org.signal.core.util.BidiUtil import org.signal.core.util.BidiUtil
import org.signal.core.util.UuidUtil import org.signal.core.util.UuidUtil
import org.signal.core.util.isNullOrEmpty import org.signal.core.util.isNullOrEmpty
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate
import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate
import org.thoughtcrime.securesms.backup.v2.proto.GroupAnnouncementOnlyChangeUpdate import org.thoughtcrime.securesms.backup.v2.proto.GroupAnnouncementOnlyChangeUpdate
@@ -12,17 +12,17 @@ import androidx.annotation.VisibleForTesting;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import org.signal.core.util.BidiUtil; import org.signal.core.util.BidiUtil;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate; import org.thoughtcrime.securesms.backup.v2.proto.GenericGroupUpdate;
import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate; import org.thoughtcrime.securesms.backup.v2.proto.GroupAdminStatusUpdate;
@@ -35,8 +35,8 @@ import com.annimon.stream.Stream;
import org.signal.core.util.Base64; import org.signal.core.util.Base64;
import org.signal.core.util.BidiUtil; import org.signal.core.util.BidiUtil;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate; import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate; import org.thoughtcrime.securesms.backup.v2.proto.GroupCreationUpdate;
@@ -4,7 +4,7 @@ import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
public final class GV2AccessLevelUtil { public final class GV2AccessLevelUtil {
@@ -11,8 +11,8 @@ import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams; import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext; import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.storageservice.protos.groups.GroupExternalCredential; import org.signal.storageservice.storage.protos.groups.ExternalGroupCredential;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.thoughtcrime.securesms.database.GroupTable; import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.GroupRecord; import org.thoughtcrime.securesms.database.model.GroupRecord;
@@ -395,11 +395,11 @@ public final class GroupManager {
} }
@WorkerThread @WorkerThread
public static @NonNull GroupExternalCredential getGroupExternalCredential(@NonNull Context context, public static @NonNull ExternalGroupCredential getExternalGroupCredential(@NonNull Context context,
@NonNull GroupId.V2 groupId) @NonNull GroupId.V2 groupId)
throws IOException, VerificationFailedException throws IOException, VerificationFailedException
{ {
return new GroupManagerV2(context).getGroupExternalCredential(groupId); return new GroupManagerV2(context).getExternalGroupCredential(groupId);
} }
@WorkerThread @WorkerThread
@@ -16,17 +16,17 @@ import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext; import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential; import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.GroupChangeResponse; import org.signal.storageservice.storage.protos.groups.GroupChangeResponse;
import org.signal.storageservice.protos.groups.GroupExternalCredential; import org.signal.storageservice.storage.protos.groups.ExternalGroupCredential;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.database.GroupTable; import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
@@ -150,7 +150,7 @@ final class GroupManagerV2 {
} }
@WorkerThread @WorkerThread
@NonNull GroupExternalCredential getGroupExternalCredential(@NonNull GroupId.V2 groupId) @NonNull ExternalGroupCredential getExternalGroupCredential(@NonNull GroupId.V2 groupId)
throws IOException, VerificationFailedException throws IOException, VerificationFailedException
{ {
GroupMasterKey groupMasterKey = SignalDatabase.groups() GroupMasterKey groupMasterKey = SignalDatabase.groups()
@@ -160,7 +160,7 @@ final class GroupManagerV2 {
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
return groupsV2Api.getGroupExternalCredential(authorization.getAuthorizationForToday(serviceIds, groupSecretParams)); return groupsV2Api.getExternalGroupCredential(authorization.getAuthorizationForToday(serviceIds, groupSecretParams));
} }
@WorkerThread @WorkerThread
@@ -589,7 +589,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{ {
boolean refetchedAddMemberCredentials = false; boolean refetchedAddMemberCredentials = false;
change.sourceServiceId(UuidUtil.toByteString(authServiceId.getRawUuid())); change.sourceUserId(UuidUtil.toByteString(authServiceId.getRawUuid()));
for (int attempt = 0; attempt < 5; attempt++) { for (int attempt = 0; attempt < 5; attempt++) {
try { try {
@@ -677,7 +677,7 @@ final class GroupManagerV2 {
final GroupRecord groupRecord = groupDatabase.requireGroup(groupId); final GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
final GroupTable.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties(); final GroupTable.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
final int nextRevision = v2GroupProperties.getGroupRevision() + 1; final int nextRevision = v2GroupProperties.getGroupRevision() + 1;
final GroupChange.Actions changeActions = change.revision(nextRevision).build(); final GroupChange.Actions changeActions = change.version(nextRevision).build();
final DecryptedGroupChange decryptedChange; final DecryptedGroupChange decryptedChange;
final DecryptedGroup decryptedGroupState; final DecryptedGroup decryptedGroupState;
final DecryptedGroup previousGroupState; final DecryptedGroup previousGroupState;
@@ -689,7 +689,7 @@ final class GroupManagerV2 {
previousGroupState = v2GroupProperties.getDecryptedGroup(); previousGroupState = v2GroupProperties.getDecryptedGroup();
GroupChangeResponse changeResponse = commitToServer(changeActions); GroupChangeResponse changeResponse = commitToServer(changeActions);
GroupChange signedGroupChange = changeResponse.groupChange; GroupChange signedGroupChange = changeResponse.group_change;
try { try {
decryptedChange = groupOperations.decryptChange(signedGroupChange, DecryptChangeVerificationMode.alreadyTrusted()).get(); decryptedChange = groupOperations.decryptChange(signedGroupChange, DecryptChangeVerificationMode.alreadyTrusted()).get();
decryptedGroupState = DecryptedGroupUtil.apply(previousGroupState, decryptedChange); decryptedGroupState = DecryptedGroupUtil.apply(previousGroupState, decryptedChange);
@@ -698,7 +698,7 @@ final class GroupManagerV2 {
throw new IOException(e); throw new IOException(e);
} }
groupDatabase.update(groupId, decryptedGroupState, groupsV2Operations.forGroup(groupSecretParams).receiveGroupSendEndorsements(selfAci, decryptedGroupState, changeResponse.groupSendEndorsementsResponse)); groupDatabase.update(groupId, decryptedGroupState, groupsV2Operations.forGroup(groupSecretParams).receiveGroupSendEndorsements(selfAci, decryptedGroupState, changeResponse.group_send_endorsements_response));
GroupMutation groupMutation = new GroupMutation(previousGroupState, decryptedChange, decryptedGroupState); GroupMutation groupMutation = new GroupMutation(previousGroupState, decryptedChange, decryptedGroupState);
RecipientAndThread recipientAndThread = sendGroupUpdateHelper.sendGroupUpdate(groupMasterKey, groupMutation, signedGroupChange, sendToMembers); RecipientAndThread recipientAndThread = sendGroupUpdateHelper.sendGroupUpdate(groupMasterKey, groupMutation, signedGroupChange, sendToMembers);
@@ -885,7 +885,7 @@ final class GroupManagerV2 {
try { try {
groupChangeResponse = joinGroupOnServer(requestToJoin, joinInfo.revision); groupChangeResponse = joinGroupOnServer(requestToJoin, joinInfo.revision);
signedGroupChange = groupChangeResponse.groupChange; signedGroupChange = groupChangeResponse.group_change;
if (requestToJoin) { if (requestToJoin) {
Log.i(TAG, String.format("Successfully requested to join %s on server", groupId)); Log.i(TAG, String.format("Successfully requested to join %s on server", groupId));
@@ -1086,7 +1086,7 @@ final class GroupManagerV2 {
GroupChange.Actions.Builder change = requestToJoin ? groupOperations.createGroupJoinRequest(expiringProfileKeyCredential) GroupChange.Actions.Builder change = requestToJoin ? groupOperations.createGroupJoinRequest(expiringProfileKeyCredential)
: groupOperations.createGroupJoinDirect(expiringProfileKeyCredential); : groupOperations.createGroupJoinDirect(expiringProfileKeyCredential);
change.sourceServiceId(selfAci.toByteString()); change.sourceUserId(selfAci.toByteString());
return commitJoinChangeWithConflictResolution(currentRevision, change); return commitJoinChangeWithConflictResolution(currentRevision, change);
} }
@@ -1096,13 +1096,13 @@ final class GroupManagerV2 {
{ {
for (int attempt = 0; attempt < 5; attempt++) { for (int attempt = 0; attempt < 5; attempt++) {
try { try {
GroupChange.Actions changeActions = change.revision(currentRevision + 1) GroupChange.Actions changeActions = change.version(currentRevision + 1)
.build(); .build();
Log.i(TAG, "Trying to join group at V" + changeActions.revision); Log.i(TAG, "Trying to join group at V" + changeActions.version);
GroupChangeResponse changeResponse = commitJoinToServer(changeActions); GroupChangeResponse changeResponse = commitJoinToServer(changeActions);
Log.i(TAG, "Successfully joined group at V" + changeActions.revision); Log.i(TAG, "Successfully joined group at V" + changeActions.version);
return changeResponse; return changeResponse;
} catch (GroupPatchNotAcceptedException e) { } catch (GroupPatchNotAcceptedException e) {
Log.w(TAG, "Patch not accepted", e); Log.w(TAG, "Patch not accepted", e);
@@ -1225,13 +1225,13 @@ final class GroupManagerV2 {
for (int attempt = 0; attempt < 5; attempt++) { for (int attempt = 0; attempt < 5; attempt++) {
try { try {
GroupChange.Actions changeActions = change.revision(currentRevision + 1) GroupChange.Actions changeActions = change.version(currentRevision + 1)
.build(); .build();
Log.i(TAG, "Trying to cancel request group at V" + changeActions.revision); Log.i(TAG, "Trying to cancel request group at V" + changeActions.version);
GroupChange signedGroupChange = commitJoinToServer(changeActions).groupChange; GroupChange signedGroupChange = commitJoinToServer(changeActions).group_change;
Log.i(TAG, "Successfully cancelled group join at V" + changeActions.revision); Log.i(TAG, "Successfully cancelled group join at V" + changeActions.version);
return signedGroupChange; return signedGroupChange;
} catch (GroupPatchNotAcceptedException e) { } catch (GroupPatchNotAcceptedException e) {
throw new GroupChangeFailedException(e); throw new GroupChangeFailedException(e);
@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.groups;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
public final class GroupMutation { public final class GroupMutation {
@Nullable private final DecryptedGroup previousGroupState; @Nullable private final DecryptedGroup previousGroupState;
@@ -5,11 +5,11 @@ import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate; import org.thoughtcrime.securesms.backup.v2.proto.GroupChangeChatUpdate;
import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter; import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter;
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context; import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
@@ -13,9 +13,9 @@ import com.annimon.stream.ComparatorCompat;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.GroupTable; import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
@@ -12,8 +12,8 @@ import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext; import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.thoughtcrime.securesms.database.GroupTable; import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.groups.GroupChangeException; import org.thoughtcrime.securesms.groups.GroupChangeException;
@@ -3,8 +3,8 @@ package org.thoughtcrime.securesms.groups.ui.invitesandrequests.joining;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
public final class GroupDetails { public final class GroupDetails {
private final DecryptedGroupJoinInfo joinInfo; private final DecryptedGroupJoinInfo joinInfo;
@@ -9,7 +9,7 @@ import androidx.annotation.WorkerThread;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.libsignal.zkgroup.VerificationFailedException; import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException; import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
@@ -6,8 +6,8 @@ import androidx.annotation.Nullable;
import org.signal.core.util.Base64; import org.signal.core.util.Base64;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.storageservice.protos.groups.GroupInviteLink; import org.signal.storageservice.storage.protos.groups.GroupInviteLink;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@@ -62,8 +62,8 @@ public final class GroupInviteLinkUrl {
GroupInviteLink groupInviteLink = GroupInviteLink.ADAPTER.decode(bytes); GroupInviteLink groupInviteLink = GroupInviteLink.ADAPTER.decode(bytes);
//noinspection SwitchStatementWithTooFewBranches //noinspection SwitchStatementWithTooFewBranches
if (groupInviteLink.v1Contents != null) { if (groupInviteLink.contentsV1 != null) {
GroupInviteLink.GroupInviteLinkContentsV1 groupInviteLinkContentsV1 = groupInviteLink.v1Contents; GroupInviteLink.GroupInviteLinkContentsV1 groupInviteLinkContentsV1 = groupInviteLink.contentsV1;
GroupMasterKey groupMasterKey = new GroupMasterKey(groupInviteLinkContentsV1.groupMasterKey.toByteArray()); GroupMasterKey groupMasterKey = new GroupMasterKey(groupInviteLinkContentsV1.groupMasterKey.toByteArray());
GroupLinkPassword password = GroupLinkPassword.fromBytes(groupInviteLinkContentsV1.inviteLinkPassword.toByteArray()); GroupLinkPassword password = GroupLinkPassword.fromBytes(groupInviteLinkContentsV1.inviteLinkPassword.toByteArray());
@@ -106,7 +106,7 @@ public final class GroupInviteLinkUrl {
protected static @NonNull String createUrl(@NonNull GroupMasterKey groupMasterKey, @NonNull GroupLinkPassword password) { protected static @NonNull String createUrl(@NonNull GroupMasterKey groupMasterKey, @NonNull GroupLinkPassword password) {
GroupInviteLink groupInviteLink = new GroupInviteLink.Builder() GroupInviteLink groupInviteLink = new GroupInviteLink.Builder()
.v1Contents(new GroupInviteLink.GroupInviteLinkContentsV1.Builder() .contentsV1(new GroupInviteLink.GroupInviteLinkContentsV1.Builder()
.groupMasterKey(ByteString.of(groupMasterKey.serialize())) .groupMasterKey(ByteString.of(groupMasterKey.serialize()))
.inviteLinkPassword(ByteString.of(password.serialize())) .inviteLinkPassword(ByteString.of(password.serialize()))
.build()) .build())
@@ -6,10 +6,10 @@ import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.core.models.ServiceId; import org.signal.core.models.ServiceId;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
@@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.groups.v2.processing package org.thoughtcrime.securesms.groups.v2.processing
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog
/** /**
@@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.groups.v2.processing package org.thoughtcrime.securesms.groups.v2.processing
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
/** /**
* Pair of a group state and optionally the corresponding change. * Pair of a group state and optionally the corresponding change.
@@ -1,8 +1,8 @@
package org.thoughtcrime.securesms.groups.v2.processing package org.thoughtcrime.securesms.groups.v2.processing
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog
/** /**
@@ -4,8 +4,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct; import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
@@ -4,7 +4,7 @@
*/ */
package org.thoughtcrime.securesms.groups.v2.processing package org.thoughtcrime.securesms.groups.v2.processing
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
/** /**
* Result of updating a local group state via P2P group change or a server pull. * Result of updating a local group state via P2P group change or a server pull.
@@ -16,8 +16,8 @@ import org.signal.libsignal.zkgroup.InvalidInputException
import org.signal.libsignal.zkgroup.VerificationFailedException import org.signal.libsignal.zkgroup.VerificationFailedException
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.libsignal.zkgroup.groups.GroupSecretParams import org.signal.libsignal.zkgroup.groups.GroupSecretParams
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.GroupRecord import org.thoughtcrime.securesms.database.model.GroupRecord
import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter
@@ -6,7 +6,7 @@ import androidx.annotation.Nullable;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.GroupRecord; import org.thoughtcrime.securesms.database.model.GroupRecord;
import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.dependencies.AppDependencies;
@@ -10,7 +10,7 @@ import com.annimon.stream.Collectors;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.thoughtcrime.securesms.database.RecipientTable; import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
@@ -21,7 +21,7 @@ import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.ringrtc.CallLinkEpoch; import org.signal.ringrtc.CallLinkEpoch;
import org.signal.ringrtc.CallLinkRootKey; import org.signal.ringrtc.CallLinkRootKey;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment; import org.thoughtcrime.securesms.attachments.UriAttachment;
@@ -8,7 +8,7 @@ import androidx.annotation.WorkerThread;
import org.signal.core.util.Result; import org.signal.core.util.Result;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.thoughtcrime.securesms.database.GroupTable; import org.thoughtcrime.securesms.database.GroupTable;
import org.thoughtcrime.securesms.database.MessageTable; import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.RecipientTable; import org.thoughtcrime.securesms.database.RecipientTable;
@@ -8,7 +8,7 @@ import org.signal.core.util.isNotEmpty
import org.signal.core.util.orNull import org.signal.core.util.orNull
import org.signal.libsignal.protocol.message.DecryptionErrorMessage import org.signal.libsignal.protocol.message.DecryptionErrorMessage
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.thoughtcrime.securesms.attachments.Attachment import org.thoughtcrime.securesms.attachments.Attachment
import org.thoughtcrime.securesms.attachments.Cdn import org.thoughtcrime.securesms.attachments.Cdn
import org.thoughtcrime.securesms.attachments.PointerAttachment import org.thoughtcrime.securesms.attachments.PointerAttachment
@@ -7,9 +7,9 @@ import com.annimon.stream.Stream;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context; import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras; import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras;
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil; import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil;
@@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException; import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
@@ -34,7 +34,7 @@ import org.signal.ringrtc.HttpHeader;
import org.signal.ringrtc.NetworkRoute; import org.signal.ringrtc.NetworkRoute;
import org.signal.ringrtc.PeekInfo; import org.signal.ringrtc.PeekInfo;
import org.signal.ringrtc.Remote; import org.signal.ringrtc.Remote;
import org.signal.storageservice.protos.groups.GroupExternalCredential; import org.signal.storageservice.storage.protos.groups.ExternalGroupCredential;
import org.thoughtcrime.securesms.calls.quality.CallQuality; import org.thoughtcrime.securesms.calls.quality.CallQuality;
import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent; import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent;
import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil;
@@ -466,7 +466,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
try { try {
Recipient group = Recipient.resolved(id); Recipient group = Recipient.resolved(id);
GroupId.V2 groupId = group.requireGroupId().requireV2(); GroupId.V2 groupId = group.requireGroupId().requireV2();
GroupExternalCredential credential = GroupManager.getGroupExternalCredential(context, groupId); ExternalGroupCredential credential = GroupManager.getExternalGroupCredential(context, groupId);
List<GroupCall.GroupMemberInfo> members = Stream.of(GroupManager.getUuidCipherTexts(context, groupId)) List<GroupCall.GroupMemberInfo> members = Stream.of(GroupManager.getUuidCipherTexts(context, groupId))
.map(entry -> new GroupCall.GroupMemberInfo(entry.getKey(), entry.getValue().serialize())) .map(entry -> new GroupCall.GroupMemberInfo(entry.getKey(), entry.getValue().serialize()))
@@ -506,7 +506,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
try { try {
Recipient group = Recipient.resolved(info.getRecipientId()); Recipient group = Recipient.resolved(info.getRecipientId());
GroupId.V2 groupId = group.requireGroupId().requireV2(); GroupId.V2 groupId = group.requireGroupId().requireV2();
GroupExternalCredential credential = GroupManager.getGroupExternalCredential(context, groupId); ExternalGroupCredential credential = GroupManager.getExternalGroupCredential(context, groupId);
List<GroupCall.GroupMemberInfo> members = GroupManager.getUuidCipherTexts(context, groupId) List<GroupCall.GroupMemberInfo> members = GroupManager.getUuidCipherTexts(context, groupId)
.entrySet() .entrySet()
@@ -527,7 +527,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
void requestGroupMembershipToken(@NonNull GroupId.V2 groupId, int groupCallHashCode) { void requestGroupMembershipToken(@NonNull GroupId.V2 groupId, int groupCallHashCode) {
networkExecutor.execute(() -> { networkExecutor.execute(() -> {
try { try {
GroupExternalCredential credential = GroupManager.getGroupExternalCredential(context, groupId); ExternalGroupCredential credential = GroupManager.getExternalGroupCredential(context, groupId);
process((s, p) -> p.handleGroupMembershipProofResponse(s, groupCallHashCode, credential.token.getBytes(Charsets.UTF_8))); process((s, p) -> p.handleGroupMembershipProofResponse(s, groupCallHashCode, credential.token.getBytes(Charsets.UTF_8)));
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "Unable to get group membership proof from service", e); Log.w(TAG, "Unable to get group membership proof from service", e);
@@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.sms;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.thoughtcrime.securesms.mms.MessageGroupContext; import org.thoughtcrime.securesms.mms.MessageGroupContext;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.signal.core.models.ServiceId; import org.signal.core.models.ServiceId;
@@ -5,11 +5,11 @@ import okio.ByteString
import org.signal.core.util.UuidUtil import org.signal.core.util.UuidUtil
import org.signal.core.util.requireBlob import org.signal.core.util.requireBlob
import org.signal.spinner.ColumnTransformer import org.signal.spinner.ColumnTransformer
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
object GV2Transformer : ColumnTransformer { object GV2Transformer : ColumnTransformer {
override fun matches(tableName: String?, columnName: String): Boolean { override fun matches(tableName: String?, columnName: String): Boolean {
@@ -3,17 +3,17 @@ package org.thoughtcrime.securesms.database
import okio.ByteString.Companion.toByteString import okio.ByteString.Companion.toByteString
import org.signal.core.models.ServiceId import org.signal.core.models.ServiceId
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.GroupChange import org.signal.storageservice.storage.protos.groups.GroupChange
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import org.signal.storageservice.protos.groups.local.DecryptedString import org.signal.storageservice.storage.protos.groups.local.DecryptedString
import org.signal.storageservice.protos.groups.local.DecryptedTimer import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
import org.thoughtcrime.securesms.database.model.GroupRecord import org.thoughtcrime.securesms.database.model.GroupRecord
import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
@@ -80,12 +80,12 @@ class GroupChangeData(private val revision: Int, private val groupOperations: Gr
get() { get() {
return groupChangeBuilder return groupChangeBuilder
.changeEpoch(changeEpoch) .changeEpoch(changeEpoch)
.actions(actionsBuilder.revision(revision).build().encodeByteString()) .actions(actionsBuilder.version(revision).build().encodeByteString())
.build() .build()
} }
fun source(serviceId: ServiceId) { fun source(serviceId: ServiceId) {
actionsBuilder.sourceServiceId = groupOperations.encryptServiceId(serviceId) actionsBuilder.sourceUserId = groupOperations.encryptServiceId(serviceId)
} }
fun deleteMember(serviceId: ServiceId) { fun deleteMember(serviceId: ServiceId) {
@@ -17,17 +17,17 @@ import org.signal.core.models.ServiceId
import org.signal.core.models.ServiceId.ACI import org.signal.core.models.ServiceId.ACI
import org.signal.core.models.ServiceId.PNI import org.signal.core.models.ServiceId.PNI
import org.signal.core.util.BidiUtil import org.signal.core.util.BidiUtil
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired.ADMINISTRATOR import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired.ADMINISTRATOR
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired.ANY import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired.ANY
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired.MEMBER import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired.MEMBER
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired.UNKNOWN import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired.UNKNOWN
import org.signal.storageservice.protos.groups.AccessControl.AccessRequired.UNSATISFIABLE import org.signal.storageservice.storage.protos.groups.AccessControl.AccessRequired.UNSATISFIABLE
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter.translateDecryptedChangeNewGroup import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter.translateDecryptedChangeNewGroup
import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter.translateDecryptedChangeUpdate import org.thoughtcrime.securesms.database.model.GroupsV2UpdateMessageConverter.translateDecryptedChangeUpdate
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
@@ -27,9 +27,9 @@ import org.signal.libsignal.protocol.logging.SignalProtocolLogger
import org.signal.libsignal.protocol.logging.SignalProtocolLoggerProvider import org.signal.libsignal.protocol.logging.SignalProtocolLoggerProvider
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.libsignal.zkgroup.groups.GroupSecretParams import org.signal.libsignal.zkgroup.groups.GroupSecretParams
import org.signal.storageservice.protos.groups.GroupChangeResponse import org.signal.storageservice.storage.protos.groups.GroupChangeResponse
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.thoughtcrime.securesms.TestZkGroupServer import org.thoughtcrime.securesms.TestZkGroupServer
import org.thoughtcrime.securesms.database.GroupStateTestData import org.thoughtcrime.securesms.database.GroupStateTestData
import org.thoughtcrime.securesms.database.GroupTable import org.thoughtcrime.securesms.database.GroupTable
@@ -123,7 +123,7 @@ class GroupManagerV2Test_edit {
every { groupTable.requireGroup(groupId) } returns data.groupRecord.get() every { groupTable.requireGroup(groupId) } returns data.groupRecord.get()
every { groupTable.update(any<GroupId.V2>(), any(), any()) } returns Unit every { groupTable.update(any<GroupId.V2>(), any(), any()) } returns Unit
every { sendGroupUpdateHelper.sendGroupUpdate(masterKey, any(), any(), any()) } returns GroupManagerV2.RecipientAndThread(Recipient.UNKNOWN, 1) every { sendGroupUpdateHelper.sendGroupUpdate(masterKey, any(), any(), any()) } returns GroupManagerV2.RecipientAndThread(Recipient.UNKNOWN, 1)
every { groupsV2API.patchGroup(any(), any(), any()) } returns GroupChangeResponse(groupChange = data.groupChange!!) every { groupsV2API.patchGroup(any(), any(), any()) } returns GroupChangeResponse(group_change = data.groupChange!!)
} }
private fun editGroup(perform: GroupManagerV2.GroupEditor.() -> Unit) { private fun editGroup(perform: GroupManagerV2.GroupEditor.() -> Unit) {
@@ -5,17 +5,17 @@ import androidx.annotation.Nullable;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
@@ -11,7 +11,7 @@ import okio.ByteString
import org.junit.Test import org.junit.Test
import org.signal.core.util.Base64.encodeUrlSafeWithoutPadding import org.signal.core.util.Base64.encodeUrlSafeWithoutPadding
import org.signal.libsignal.zkgroup.InvalidInputException import org.signal.libsignal.zkgroup.InvalidInputException
import org.signal.storageservice.protos.groups.GroupInviteLink import org.signal.storageservice.storage.protos.groups.GroupInviteLink
import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl.InvalidGroupLinkException import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl.InvalidGroupLinkException
import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl.UnknownGroupLinkVersionException import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl.UnknownGroupLinkVersionException
import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.Util
@@ -116,7 +116,7 @@ class GroupInviteLinkUrl_InvalidGroupLinkException_Test {
): String { ): String {
return encodeUrlSafeWithoutPadding( return encodeUrlSafeWithoutPadding(
GroupInviteLink.Builder() GroupInviteLink.Builder()
.v1Contents( .contentsV1(
GroupInviteLink.GroupInviteLinkContentsV1.Builder() GroupInviteLink.GroupInviteLinkContentsV1.Builder()
.groupMasterKey(ByteString.of(*groupMasterKey)) .groupMasterKey(ByteString.of(*groupMasterKey))
.inviteLinkPassword(ByteString.of(*passwordBytes)) .inviteLinkPassword(ByteString.of(*passwordBytes))
@@ -12,10 +12,10 @@ import org.junit.Test
import org.signal.core.models.ServiceId import org.signal.core.models.ServiceId
import org.signal.core.util.UuidUtil import org.signal.core.util.UuidUtil
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedString import org.signal.storageservice.storage.protos.groups.local.DecryptedString
import org.thoughtcrime.securesms.testutil.LogRecorder import org.thoughtcrime.securesms.testutil.LogRecorder
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog
import java.util.UUID import java.util.UUID
@@ -32,11 +32,11 @@ import org.signal.libsignal.protocol.logging.SignalProtocolLoggerProvider
import org.signal.libsignal.zkgroup.VerificationFailedException import org.signal.libsignal.zkgroup.VerificationFailedException
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.libsignal.zkgroup.groups.GroupSecretParams import org.signal.libsignal.zkgroup.groups.GroupSecretParams
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedString import org.signal.storageservice.storage.protos.groups.local.DecryptedString
import org.signal.storageservice.protos.groups.local.DecryptedTimer import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer
import org.thoughtcrime.securesms.database.GroupStateTestData import org.thoughtcrime.securesms.database.GroupStateTestData
import org.thoughtcrime.securesms.database.GroupTable import org.thoughtcrime.securesms.database.GroupTable
import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.RecipientTable
@@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.sms;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.junit.Test; import org.junit.Test;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context; import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
import org.thoughtcrime.securesms.groups.v2.ChangeBuilder; import org.thoughtcrime.securesms.groups.v2.ChangeBuilder;
import org.thoughtcrime.securesms.mms.MessageGroupContext; import org.thoughtcrime.securesms.mms.MessageGroupContext;
@@ -4,11 +4,11 @@ import okio.ByteString.Companion.toByteString
import org.signal.core.models.ServiceId import org.signal.core.models.ServiceId
import org.signal.core.models.ServiceId.ACI import org.signal.core.models.ServiceId.ACI
import org.signal.libsignal.zkgroup.groups.GroupMasterKey import org.signal.libsignal.zkgroup.groups.GroupMasterKey
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import org.whispersystems.signalservice.internal.push.GroupContextV2 import org.whispersystems.signalservice.internal.push.GroupContextV2
import java.util.UUID import java.util.UUID
@@ -1,11 +1,11 @@
package org.whispersystems.signalservice.api.groupsv2 package org.whispersystems.signalservice.api.groupsv2
import org.signal.storageservice.protos.groups.AccessControl import org.signal.storageservice.storage.protos.groups.AccessControl
import org.signal.storageservice.protos.groups.Member import org.signal.storageservice.storage.protos.groups.Member
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import org.signal.storageservice.protos.groups.local.EnabledState import org.signal.storageservice.storage.protos.groups.local.EnabledState
internal class DecryptedGroupChangeActionsBuilderChangeSetModifier(private val result: DecryptedGroupChange.Builder) : ChangeSetModifier { internal class DecryptedGroupChangeActionsBuilderChangeSetModifier(private val result: DecryptedGroupChange.Builder) : ChangeSetModifier {
override fun removeAddMembers(i: Int) { override fun removeAddMembers(i: Int) {
@@ -1,7 +1,7 @@
package org.whispersystems.signalservice.api.groupsv2 package org.whispersystems.signalservice.api.groupsv2
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
/** /**
* A changelog from the server representing a specific group state revision. The * A changelog from the server representing a specific group state revision. The
@@ -7,9 +7,9 @@ package org.whispersystems.signalservice.api.groupsv2
import org.signal.core.models.ServiceId import org.signal.core.models.ServiceId
import org.signal.core.models.ServiceId.ACI import org.signal.core.models.ServiceId.ACI
import org.signal.storageservice.protos.groups.local.DecryptedMember import org.signal.storageservice.storage.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember
import java.util.Optional import java.util.Optional
fun Collection<DecryptedMember>.toAciListWithUnknowns(): List<ACI> { fun Collection<DecryptedMember>.toAciListWithUnknowns(): List<ACI> {
@@ -6,7 +6,7 @@
package org.whispersystems.signalservice.api.groupsv2 package org.whispersystems.signalservice.api.groupsv2
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse
import org.signal.storageservice.protos.groups.local.DecryptedGroup import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup
/** /**
* Decrypted response from server operations that includes our global group state and * Decrypted response from server operations that includes our global group state and
@@ -1,18 +1,18 @@
package org.whispersystems.signalservice.api.groupsv2; package org.whispersystems.signalservice.api.groupsv2;
import org.signal.libsignal.protocol.logging.Log; import org.signal.libsignal.protocol.logging.Log;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.models.ServiceId; import org.signal.core.models.ServiceId;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceIds; import org.whispersystems.signalservice.api.push.ServiceIds;
@@ -299,11 +299,11 @@ public final class DecryptedGroupUtil {
applyModifyMemberProfileKeyActions(builder, change.modifiedProfileKeys); applyModifyMemberProfileKeyActions(builder, change.modifiedProfileKeys);
applyAddPendingMemberActions(builder, change.newPendingMembers); applyAddMemberPendingProfileKeyActions(builder, change.newPendingMembers);
applyDeletePendingMemberActions(builder, change.deletePendingMembers); applyDeleteMemberPendingProfileKeyActions(builder, change.deletePendingMembers);
applyPromotePendingMemberActions(builder, change.promotePendingMembers); applyPromoteMemberPendingProfileKeyActions(builder, change.promotePendingMembers);
applyModifyTitleAction(builder, change); applyModifyTitleAction(builder, change);
@@ -325,7 +325,7 @@ public final class DecryptedGroupUtil {
applyDeleteRequestingMembers(builder, change.deleteRequestingMembers); applyDeleteRequestingMembers(builder, change.deleteRequestingMembers);
applyPromoteRequestingMemberActions(builder, change.promoteRequestingMembers); applyPromoteMemberPendingAdminApprovalActions(builder, change.promoteRequestingMembers);
applyInviteLinkPassword(builder, change); applyInviteLinkPassword(builder, change);
@@ -409,7 +409,7 @@ public final class DecryptedGroupUtil {
builder.members(members); builder.members(members);
} }
private static void applyAddPendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMember> newPendingMembersList) throws NotAbleToApplyGroupV2ChangeException { private static void applyAddMemberPendingProfileKeyActions(DecryptedGroup.Builder builder, List<DecryptedPendingMember> newPendingMembersList) throws NotAbleToApplyGroupV2ChangeException {
Set<ByteString> fullMemberSet = getMemberAciSet(builder.members); Set<ByteString> fullMemberSet = getMemberAciSet(builder.members);
Set<ByteString> pendingMemberCipherTexts = getPendingMemberCipherTextSet(builder.pendingMembers); Set<ByteString> pendingMemberCipherTexts = getPendingMemberCipherTextSet(builder.pendingMembers);
List<DecryptedPendingMember> pendingMembers = new ArrayList<>(builder.pendingMembers); List<DecryptedPendingMember> pendingMembers = new ArrayList<>(builder.pendingMembers);
@@ -427,7 +427,7 @@ public final class DecryptedGroupUtil {
builder.pendingMembers(pendingMembers); builder.pendingMembers(pendingMembers);
} }
private static void applyDeletePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMemberRemoval> deletePendingMembersList) { private static void applyDeleteMemberPendingProfileKeyActions(DecryptedGroup.Builder builder, List<DecryptedPendingMemberRemoval> deletePendingMembersList) {
List<DecryptedPendingMember> pendingMembers = new ArrayList<>(builder.pendingMembers); List<DecryptedPendingMember> pendingMembers = new ArrayList<>(builder.pendingMembers);
for (DecryptedPendingMemberRemoval removedMember : deletePendingMembersList) { for (DecryptedPendingMemberRemoval removedMember : deletePendingMembersList) {
@@ -444,7 +444,7 @@ public final class DecryptedGroupUtil {
builder.pendingMembers(pendingMembers); builder.pendingMembers(pendingMembers);
} }
private static void applyPromotePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedMember> promotePendingMembersList) throws NotAbleToApplyGroupV2ChangeException { private static void applyPromoteMemberPendingProfileKeyActions(DecryptedGroup.Builder builder, List<DecryptedMember> promotePendingMembersList) throws NotAbleToApplyGroupV2ChangeException {
List<DecryptedMember> members = new ArrayList<>(builder.members); List<DecryptedMember> members = new ArrayList<>(builder.members);
List<DecryptedPendingMember> pendingMembers = new ArrayList<>(builder.pendingMembers); List<DecryptedPendingMember> pendingMembers = new ArrayList<>(builder.pendingMembers);
@@ -541,7 +541,7 @@ public final class DecryptedGroupUtil {
builder.requestingMembers(requestingMembers); builder.requestingMembers(requestingMembers);
} }
private static void applyPromoteRequestingMemberActions(DecryptedGroup.Builder builder, List<DecryptedApproveMember> promoteRequestingMembers) throws NotAbleToApplyGroupV2ChangeException { private static void applyPromoteMemberPendingAdminApprovalActions(DecryptedGroup.Builder builder, List<DecryptedApproveMember> promoteRequestingMembers) throws NotAbleToApplyGroupV2ChangeException {
List<DecryptedMember> members = new ArrayList<>(builder.members); List<DecryptedMember> members = new ArrayList<>(builder.members);
List<DecryptedRequestingMember> requestingMembers = new ArrayList<>(builder.requestingMembers); List<DecryptedRequestingMember> requestingMembers = new ArrayList<>(builder.requestingMembers);
@@ -1,8 +1,8 @@
package org.whispersystems.signalservice.api.groupsv2 package org.whispersystems.signalservice.api.groupsv2
import org.signal.storageservice.protos.groups.GroupChange import org.signal.storageservice.storage.protos.groups.GroupChange
import org.signal.storageservice.protos.groups.GroupChange.Actions.AddMemberAction import org.signal.storageservice.storage.protos.groups.GroupChange.Actions.AddMemberAction
import org.signal.storageservice.protos.groups.GroupChange.Actions.AddRequestingMemberAction import org.signal.storageservice.storage.protos.groups.GroupChange.Actions.AddMemberPendingAdminApprovalAction
internal class GroupChangeActionsBuilderChangeSetModifier(private val result: GroupChange.Actions.Builder) : ChangeSetModifier { internal class GroupChangeActionsBuilderChangeSetModifier(private val result: GroupChange.Actions.Builder) : ChangeSetModifier {
override fun removeAddMembers(i: Int) { override fun removeAddMembers(i: Int) {
@@ -12,7 +12,7 @@ internal class GroupChangeActionsBuilderChangeSetModifier(private val result: Gr
override fun moveAddToPromote(i: Int) { override fun moveAddToPromote(i: Int) {
val addMemberAction: AddMemberAction = result.addMembers[i] val addMemberAction: AddMemberAction = result.addMembers[i]
result.addMembers = result.addMembers.removeIndex(i) result.addMembers = result.addMembers.removeIndex(i)
result.promotePendingMembers += GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(addMemberAction.added!!.presentation).build() result.promoteMembersPendingProfileKey += GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(addMemberAction.added!!.presentation).build()
} }
override fun removeDeleteMembers(i: Int) { override fun removeDeleteMembers(i: Int) {
@@ -28,15 +28,15 @@ internal class GroupChangeActionsBuilderChangeSetModifier(private val result: Gr
} }
override fun removeAddPendingMembers(i: Int) { override fun removeAddPendingMembers(i: Int) {
result.addPendingMembers = result.addPendingMembers.removeIndex(i) result.addMembersPendingProfileKey = result.addMembersPendingProfileKey.removeIndex(i)
} }
override fun removeDeletePendingMembers(i: Int) { override fun removeDeletePendingMembers(i: Int) {
result.deletePendingMembers = result.deletePendingMembers.removeIndex(i) result.deleteMembersPendingProfileKey = result.deleteMembersPendingProfileKey.removeIndex(i)
} }
override fun removePromotePendingMembers(i: Int) { override fun removePromotePendingMembers(i: Int) {
result.promotePendingMembers = result.promotePendingMembers.removeIndex(i) result.promoteMembersPendingProfileKey = result.promoteMembersPendingProfileKey.removeIndex(i)
} }
override fun clearModifyTitle() { override fun clearModifyTitle() {
@@ -48,7 +48,7 @@ internal class GroupChangeActionsBuilderChangeSetModifier(private val result: Gr
} }
override fun clearModifyDisappearingMessagesTimer() { override fun clearModifyDisappearingMessagesTimer() {
result.modifyDisappearingMessagesTimer = null result.modifyDisappearingMessageTimer= null
} }
override fun clearModifyAttributesAccess() { override fun clearModifyAttributesAccess() {
@@ -64,21 +64,21 @@ internal class GroupChangeActionsBuilderChangeSetModifier(private val result: Gr
} }
override fun removeAddRequestingMembers(i: Int) { override fun removeAddRequestingMembers(i: Int) {
result.addRequestingMembers = result.addRequestingMembers.removeIndex(i) result.addMembersPendingAdminApproval = result.addMembersPendingAdminApproval.removeIndex(i)
} }
override fun moveAddRequestingMembersToPromote(i: Int) { override fun moveAddRequestingMembersToPromote(i: Int) {
val addMemberAction: AddRequestingMemberAction = result.addRequestingMembers[i] val addMemberAction: AddMemberPendingAdminApprovalAction = result.addMembersPendingAdminApproval[i]
result.addRequestingMembers = result.addRequestingMembers.removeIndex(i) result.addMembersPendingAdminApproval = result.addMembersPendingAdminApproval.removeIndex(i)
result.promotePendingMembers += GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(addMemberAction.added!!.presentation).build() result.promoteMembersPendingProfileKey += GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(addMemberAction.added!!.presentation).build()
} }
override fun removeDeleteRequestingMembers(i: Int) { override fun removeDeleteRequestingMembers(i: Int) {
result.deleteRequestingMembers = result.deleteRequestingMembers.removeIndex(i) result.deleteMembersPendingAdminApproval = result.deleteMembersPendingAdminApproval.removeIndex(i)
} }
override fun removePromoteRequestingMembers(i: Int) { override fun removePromoteRequestingMembers(i: Int) {
result.promoteRequestingMembers = result.promoteRequestingMembers.removeIndex(i) result.promoteMembersPendingAdminApproval = result.promoteMembersPendingAdminApproval.removeIndex(i)
} }
override fun clearModifyDescription() { override fun clearModifyDescription() {
@@ -86,19 +86,19 @@ internal class GroupChangeActionsBuilderChangeSetModifier(private val result: Gr
} }
override fun clearModifyAnnouncementsOnly() { override fun clearModifyAnnouncementsOnly() {
result.modifyAnnouncementsOnly = null result.modify_announcements_only = null
} }
override fun removeAddBannedMembers(i: Int) { override fun removeAddBannedMembers(i: Int) {
result.addBannedMembers = result.addBannedMembers.removeIndex(i) result.add_members_banned = result.add_members_banned.removeIndex(i)
} }
override fun removeDeleteBannedMembers(i: Int) { override fun removeDeleteBannedMembers(i: Int) {
result.deleteBannedMembers = result.deleteBannedMembers.removeIndex(i) result.delete_members_banned = result.delete_members_banned.removeIndex(i)
} }
override fun removePromotePendingPniAciMembers(i: Int) { override fun removePromotePendingPniAciMembers(i: Int) {
result.promotePendingPniAciMembers = result.promotePendingPniAciMembers.removeIndex(i) result.promote_members_pending_pni_aci_profile_key = result.promote_members_pending_pni_aci_profile_key.removeIndex(i)
} }
private fun <T> List<T>.removeIndex(i: Int): List<T> { private fun <T> List<T>.removeIndex(i: Int): List<T> {
@@ -1,15 +1,15 @@
package org.whispersystems.signalservice.api.groupsv2; package org.whispersystems.signalservice.api.groupsv2;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -1,15 +1,15 @@
package org.whispersystems.signalservice.api.groupsv2; package org.whispersystems.signalservice.api.groupsv2;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -29,24 +29,24 @@ public final class GroupChangeUtil {
change.deleteMembers.size() == 0 && // field 4 change.deleteMembers.size() == 0 && // field 4
change.modifyMemberRoles.size() == 0 && // field 5 change.modifyMemberRoles.size() == 0 && // field 5
change.modifyMemberProfileKeys.size() == 0 && // field 6 change.modifyMemberProfileKeys.size() == 0 && // field 6
change.addPendingMembers.size() == 0 && // field 7 change.addMembersPendingProfileKey.size() == 0 && // field 7
change.deletePendingMembers.size() == 0 && // field 8 change.deleteMembersPendingProfileKey.size() == 0 && // field 8
change.promotePendingMembers.size() == 0 && // field 9 change.promoteMembersPendingProfileKey.size() == 0 && // field 9
change.modifyTitle == null && // field 10 change.modifyTitle == null && // field 10
change.modifyAvatar == null && // field 11 change.modifyAvatar == null && // field 11
change.modifyDisappearingMessagesTimer == null && // field 12 change.modifyDisappearingMessageTimer == null && // field 12
change.modifyAttributesAccess == null && // field 13 change.modifyAttributesAccess == null && // field 13
change.modifyMemberAccess == null && // field 14 change.modifyMemberAccess == null && // field 14
change.modifyAddFromInviteLinkAccess == null && // field 15 change.modifyAddFromInviteLinkAccess == null && // field 15
change.addRequestingMembers.size() == 0 && // field 16 change.addMembersPendingAdminApproval.size() == 0 && // field 16
change.deleteRequestingMembers.size() == 0 && // field 17 change.deleteMembersPendingAdminApproval.size() == 0 && // field 17
change.promoteRequestingMembers.size() == 0 && // field 18 change.promoteMembersPendingAdminApproval.size() == 0 && // field 18
change.modifyInviteLinkPassword == null && // field 19 change.modifyInviteLinkPassword == null && // field 19
change.modifyDescription == null && // field 20 change.modifyDescription == null && // field 20
change.modifyAnnouncementsOnly == null && // field 21 change.modify_announcements_only == null && // field 21
change.addBannedMembers.size() == 0 && // field 22 change.add_members_banned.size() == 0 && // field 22
change.deleteBannedMembers.size() == 0 && // field 23 change.delete_members_banned.size() == 0 && // field 23
change.promotePendingPniAciMembers.size() == 0; // field 24 change.promote_members_pending_pni_aci_profile_key.size() == 0; // field 24
} }
/** /**
@@ -58,7 +58,7 @@ public final class GroupChangeUtil {
* Membership additions and removals also respect last writer wins and are removed if they have * Membership additions and removals also respect last writer wins and are removed if they have
* already been applied. e.g. you add someone but they are already added. * already been applied. e.g. you add someone but they are already added.
* <p> * <p>
* Membership additions will be altered to {@link GroupChange.Actions.PromotePendingMemberAction} * Membership additions will be altered to {@link GroupChange.Actions.PromoteMemberPendingProfileKeyAction}
* if someone has invited them since. * if someone has invited them since.
* *
* @param groupState Latest group state in plaintext. * @param groupState Latest group state in plaintext.
@@ -10,18 +10,18 @@ import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredentialResponse;
import org.signal.libsignal.zkgroup.groups.ClientZkGroupCipher; import org.signal.libsignal.zkgroup.groups.ClientZkGroupCipher;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams; import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse; import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse;
import org.signal.storageservice.protos.groups.AvatarUploadAttributes; import org.signal.storageservice.storage.protos.groups.AvatarUploadAttributes;
import org.signal.storageservice.protos.groups.Group; import org.signal.storageservice.storage.protos.groups.Group;
import org.signal.storageservice.protos.groups.GroupAttributeBlob; import org.signal.storageservice.storage.protos.groups.GroupAttributeBlob;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.GroupChangeResponse; import org.signal.storageservice.storage.protos.groups.GroupChangeResponse;
import org.signal.storageservice.protos.groups.GroupChanges; import org.signal.storageservice.storage.protos.groups.GroupChanges;
import org.signal.storageservice.protos.groups.GroupExternalCredential; import org.signal.storageservice.storage.protos.groups.ExternalGroupCredential;
import org.signal.storageservice.protos.groups.GroupJoinInfo; import org.signal.storageservice.storage.protos.groups.GroupJoinInfo;
import org.signal.storageservice.protos.groups.GroupResponse; import org.signal.storageservice.storage.protos.groups.GroupResponse;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.whispersystems.signalservice.api.NetworkResult; import org.whispersystems.signalservice.api.NetworkResult;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
import org.signal.core.models.ServiceId.PNI; import org.signal.core.models.ServiceId.PNI;
@@ -88,14 +88,14 @@ public class GroupsV2Api {
String cdnKey = uploadAvatar(newGroup.getAvatar().get(), newGroup.getGroupSecretParams(), authorization); String cdnKey = uploadAvatar(newGroup.getAvatar().get(), newGroup.getGroupSecretParams(), authorization);
group = group.newBuilder() group = group.newBuilder()
.avatar(cdnKey) .avatarUrl(cdnKey)
.build(); .build();
} }
GroupResponse response = socket.putNewGroupsV2Group(group, authorization); GroupResponse response = socket.putNewGroupsV2Group(group, authorization);
return groupsOperations.forGroup(newGroup.getGroupSecretParams()) return groupsOperations.forGroup(newGroup.getGroupSecretParams())
.decryptGroup(Objects.requireNonNull(response.group), response.groupSendEndorsementsResponse.toByteArray()); .decryptGroup(Objects.requireNonNull(response.group), response.group_send_endorsements_response.toByteArray());
} }
public NetworkResult<DecryptedGroupResponse> getGroupAsResult(GroupSecretParams groupSecretParams, GroupsV2AuthorizationString authorization) { public NetworkResult<DecryptedGroupResponse> getGroupAsResult(GroupSecretParams groupSecretParams, GroupsV2AuthorizationString authorization) {
@@ -109,7 +109,7 @@ public class GroupsV2Api {
GroupResponse response = socket.getGroupsV2Group(authorization); GroupResponse response = socket.getGroupsV2Group(authorization);
return groupsOperations.forGroup(groupSecretParams) return groupsOperations.forGroup(groupSecretParams)
.decryptGroup(Objects.requireNonNull(response.group), response.groupSendEndorsementsResponse.toByteArray()); .decryptGroup(Objects.requireNonNull(response.group), response.group_send_endorsements_response.toByteArray());
} }
public GroupHistoryPage getGroupHistoryPage(GroupSecretParams groupSecretParams, public GroupHistoryPage getGroupHistoryPage(GroupSecretParams groupSecretParams,
@@ -130,7 +130,7 @@ public class GroupsV2Api {
result.add(new DecryptedGroupChangeLog(decryptedGroup, decryptedChange)); result.add(new DecryptedGroupChangeLog(decryptedGroup, decryptedChange));
} }
byte[] groupSendEndorsementsResponseBytes = group.getGroupChanges().groupSendEndorsementsResponse.toByteArray(); byte[] groupSendEndorsementsResponseBytes = group.getGroupChanges().group_send_endorsements_response.toByteArray();
GroupSendEndorsementsResponse groupSendEndorsementsResponse = groupSendEndorsementsResponseBytes.length > 0 ? new GroupSendEndorsementsResponse(groupSendEndorsementsResponseBytes) : null; GroupSendEndorsementsResponse groupSendEndorsementsResponse = groupSendEndorsementsResponseBytes.length > 0 ? new GroupSendEndorsementsResponse(groupSendEndorsementsResponseBytes) : null;
return new GroupHistoryPage(result, groupSendEndorsementsResponse, GroupHistoryPage.PagingData.forGroupHistory(group)); return new GroupHistoryPage(result, groupSendEndorsementsResponse, GroupHistoryPage.PagingData.forGroupHistory(group));
@@ -182,10 +182,10 @@ public class GroupsV2Api {
return socket.patchGroupsV2Group(groupChange, authorization.toString(), groupLinkPassword); return socket.patchGroupsV2Group(groupChange, authorization.toString(), groupLinkPassword);
} }
public GroupExternalCredential getGroupExternalCredential(GroupsV2AuthorizationString authorization) public ExternalGroupCredential getExternalGroupCredential(GroupsV2AuthorizationString authorization)
throws IOException throws IOException
{ {
return socket.getGroupExternalCredential(authorization); return socket.getExternalGroupCredential(authorization);
} }
private static CredentialResponseMaps parseCredentialResponse(CredentialResponse credentialResponse) private static CredentialResponseMaps parseCredentialResponse(CredentialResponse credentialResponse)
@@ -16,28 +16,28 @@ import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential; import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialPresentation; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialPresentation;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.BannedMember; import org.signal.storageservice.storage.protos.groups.MemberBanned;
import org.signal.storageservice.protos.groups.Group; import org.signal.storageservice.storage.protos.groups.Group;
import org.signal.storageservice.protos.groups.GroupAttributeBlob; import org.signal.storageservice.storage.protos.groups.GroupAttributeBlob;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.GroupJoinInfo; import org.signal.storageservice.storage.protos.groups.GroupJoinInfo;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.PendingMember; import org.signal.storageservice.storage.protos.groups.MemberPendingProfileKey;
import org.signal.storageservice.protos.groups.RequestingMember; import org.signal.storageservice.storage.protos.groups.MemberPendingAdminApproval;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.models.ServiceId; import org.signal.core.models.ServiceId;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
import org.signal.core.models.ServiceId.PNI; import org.signal.core.models.ServiceId.PNI;
@@ -110,7 +110,7 @@ public final class GroupsV2Operations {
final GroupOperations groupOperations = forGroup(groupSecretParams); final GroupOperations groupOperations = forGroup(groupSecretParams);
Group.Builder group = new Group.Builder() Group.Builder group = new Group.Builder()
.revision(0) .version(0)
.publicKey(ByteString.of(groupSecretParams.getPublicParams().serialize())) .publicKey(ByteString.of(groupSecretParams.getPublicParams().serialize()))
.title(groupOperations.encryptTitle(title)) .title(groupOperations.encryptTitle(title))
.disappearingMessagesTimer(groupOperations.encryptTimer(disappearingMessageTimerSeconds)) .disappearingMessagesTimer(groupOperations.encryptTimer(disappearingMessageTimerSeconds))
@@ -120,7 +120,7 @@ public final class GroupsV2Operations {
.build()); .build());
List<Member> groupMembers = new ArrayList<>(); List<Member> groupMembers = new ArrayList<>();
List<PendingMember> groupPendingMembers = new ArrayList<>(); List<MemberPendingProfileKey> groupPendingMembers = new ArrayList<>();
groupMembers.add(groupOperations.member(self.requireExpiringProfileKeyCredential(), Member.Role.ADMINISTRATOR).build()); groupMembers.add(groupOperations.member(self.requireExpiringProfileKeyCredential(), Member.Role.ADMINISTRATOR).build());
@@ -135,7 +135,7 @@ public final class GroupsV2Operations {
} }
group.members(groupMembers) group.members(groupMembers)
.pendingMembers(groupPendingMembers); .membersPendingProfileKey(groupPendingMembers);
return new NewGroup(groupSecretParams, group.build(), avatar); return new NewGroup(groupSecretParams, group.build(), avatar);
} }
@@ -186,7 +186,7 @@ public final class GroupsV2Operations {
: createUnbanServiceIdsChange(membersToUnban); : createUnbanServiceIdsChange(membersToUnban);
List<GroupChange.Actions.AddMemberAction> addGroupMembers = new ArrayList<>(actions.addMembers); List<GroupChange.Actions.AddMemberAction> addGroupMembers = new ArrayList<>(actions.addMembers);
List<GroupChange.Actions.AddPendingMemberAction> addGroupPendingMembers = new ArrayList<>(actions.addPendingMembers); List<GroupChange.Actions.AddMemberPendingProfileKeyAction> addGroupPendingMembers = new ArrayList<>(actions.addMembersPendingProfileKey);
for (GroupCandidate credential : membersToAdd) { for (GroupCandidate credential : membersToAdd) {
Member.Role newMemberRole = Member.Role.DEFAULT; Member.Role newMemberRole = Member.Role.DEFAULT;
ExpiringProfileKeyCredential expiringProfileKeyCredential = credential.getExpiringProfileKeyCredential().orElse(null); ExpiringProfileKeyCredential expiringProfileKeyCredential = credential.getExpiringProfileKeyCredential().orElse(null);
@@ -194,7 +194,7 @@ public final class GroupsV2Operations {
if (expiringProfileKeyCredential != null) { if (expiringProfileKeyCredential != null) {
addGroupMembers.add(new GroupChange.Actions.AddMemberAction.Builder().added(groupOperations.member(expiringProfileKeyCredential, newMemberRole).build()).build()); addGroupMembers.add(new GroupChange.Actions.AddMemberAction.Builder().added(groupOperations.member(expiringProfileKeyCredential, newMemberRole).build()).build());
} else { } else {
addGroupPendingMembers.add(new GroupChange.Actions.AddPendingMemberAction.Builder().added(groupOperations.invitee(credential.getServiceId(), newMemberRole) addGroupPendingMembers.add(new GroupChange.Actions.AddMemberPendingProfileKeyAction.Builder().added(groupOperations.invitee(credential.getServiceId(), newMemberRole)
.addedByUserId(encryptServiceId(selfAci)) .addedByUserId(encryptServiceId(selfAci))
.build()) .build())
.build()); .build());
@@ -202,14 +202,14 @@ public final class GroupsV2Operations {
} }
return actions.addMembers(addGroupMembers) return actions.addMembers(addGroupMembers)
.addPendingMembers(addGroupPendingMembers); .addMembersPendingProfileKey(addGroupPendingMembers);
} }
public GroupChange.Actions.Builder createGroupJoinRequest(ExpiringProfileKeyCredential expiringProfileKeyCredential) { public GroupChange.Actions.Builder createGroupJoinRequest(ExpiringProfileKeyCredential expiringProfileKeyCredential) {
GroupOperations groupOperations = forGroup(groupSecretParams); GroupOperations groupOperations = forGroup(groupSecretParams);
GroupChange.Actions.Builder actions = new GroupChange.Actions.Builder(); GroupChange.Actions.Builder actions = new GroupChange.Actions.Builder();
actions.addRequestingMembers = Collections.singletonList(new GroupChange.Actions.AddRequestingMemberAction.Builder().added(groupOperations.requestingMember(expiringProfileKeyCredential).build()).build()); actions.addMembersPendingAdminApproval = Collections.singletonList(new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(groupOperations.requestingMember(expiringProfileKeyCredential).build()).build());
return actions; return actions;
} }
@@ -227,20 +227,20 @@ public final class GroupsV2Operations {
GroupChange.Actions.Builder actions = alsoBan ? createBanServiceIdsChange(requestsToRemove, false, bannedMembers) GroupChange.Actions.Builder actions = alsoBan ? createBanServiceIdsChange(requestsToRemove, false, bannedMembers)
: new GroupChange.Actions.Builder(); : new GroupChange.Actions.Builder();
List<GroupChange.Actions.DeleteRequestingMemberAction> deleteRequestingMemberActions = new ArrayList<>(actions.deleteRequestingMembers); List<GroupChange.Actions.DeleteMemberPendingAdminApprovalAction> DeleteMemberPendingAdminApprovalActions = new ArrayList<>(actions.deleteMembersPendingAdminApproval);
for (ServiceId serviceId : requestsToRemove) { for (ServiceId serviceId : requestsToRemove) {
if (serviceId instanceof ACI) { if (serviceId instanceof ACI) {
deleteRequestingMemberActions.add(new GroupChange.Actions.DeleteRequestingMemberAction.Builder().deletedUserId(encryptServiceId(serviceId)).build()); DeleteMemberPendingAdminApprovalActions.add(new GroupChange.Actions.DeleteMemberPendingAdminApprovalAction.Builder().deletedUserId(encryptServiceId(serviceId)).build());
} }
} }
return actions.deleteRequestingMembers(deleteRequestingMemberActions); return actions.deleteMembersPendingAdminApproval(DeleteMemberPendingAdminApprovalActions);
} }
public GroupChange.Actions.Builder createApproveGroupJoinRequest(Set<UUID> requestsToApprove) { public GroupChange.Actions.Builder createApproveGroupJoinRequest(Set<UUID> requestsToApprove) {
GroupChange.Actions.Builder actions = new GroupChange.Actions.Builder(); GroupChange.Actions.Builder actions = new GroupChange.Actions.Builder();
actions.promoteRequestingMembers = requestsToApprove.stream() actions.promoteMembersPendingAdminApproval = requestsToApprove.stream()
.map(uuid -> new GroupChange.Actions.PromoteRequestingMemberAction.Builder().role(Member.Role.DEFAULT) .map(uuid -> new GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.Builder().role(Member.Role.DEFAULT)
.userId(encryptServiceId(ACI.from(uuid))) .userId(encryptServiceId(ACI.from(uuid)))
.build()) .build())
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -271,7 +271,7 @@ public final class GroupsV2Operations {
public GroupChange.Actions.Builder createModifyGroupTimerChange(int timerDurationSeconds) { public GroupChange.Actions.Builder createModifyGroupTimerChange(int timerDurationSeconds) {
return new GroupChange.Actions.Builder() return new GroupChange.Actions.Builder()
.modifyDisappearingMessagesTimer(new GroupChange.Actions.ModifyDisappearingMessagesTimerAction.Builder().timer(encryptTimer(timerDurationSeconds)).build()); .modifyDisappearingMessageTimer(new GroupChange.Actions.ModifyDisappearingMessageTimerAction.Builder().timer(encryptTimer(timerDurationSeconds)).build());
} }
public GroupChange.Actions.Builder createUpdateProfileKeyCredentialChange(ExpiringProfileKeyCredential expiringProfileKeyCredential) { public GroupChange.Actions.Builder createUpdateProfileKeyCredentialChange(ExpiringProfileKeyCredential expiringProfileKeyCredential) {
@@ -287,8 +287,8 @@ public final class GroupsV2Operations {
public GroupChange.Actions.Builder createAcceptInviteChange(ExpiringProfileKeyCredential credential) { public GroupChange.Actions.Builder createAcceptInviteChange(ExpiringProfileKeyCredential credential) {
ProfileKeyCredentialPresentation presentation = clientZkProfileOperations.createProfileKeyCredentialPresentation(random, groupSecretParams, credential); ProfileKeyCredentialPresentation presentation = clientZkProfileOperations.createProfileKeyCredentialPresentation(random, groupSecretParams, credential);
return new GroupChange.Actions.Builder().promotePendingMembers(Collections.singletonList( return new GroupChange.Actions.Builder().promoteMembersPendingProfileKey(Collections.singletonList(
new GroupChange.Actions.PromotePendingMemberAction.Builder() new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder()
.presentation(ByteString.of(presentation.serialize())) .presentation(ByteString.of(presentation.serialize()))
.build() .build()
)); ));
@@ -297,16 +297,16 @@ public final class GroupsV2Operations {
public GroupChange.Actions.Builder createAcceptPniInviteChange(ExpiringProfileKeyCredential credential) { public GroupChange.Actions.Builder createAcceptPniInviteChange(ExpiringProfileKeyCredential credential) {
ByteString presentation = ByteString.of(clientZkProfileOperations.createProfileKeyCredentialPresentation(random, groupSecretParams, credential).serialize()); ByteString presentation = ByteString.of(clientZkProfileOperations.createProfileKeyCredentialPresentation(random, groupSecretParams, credential).serialize());
return new GroupChange.Actions.Builder().promotePendingPniAciMembers(Collections.singletonList( return new GroupChange.Actions.Builder().promote_members_pending_pni_aci_profile_key(Collections.singletonList(
new GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.Builder().presentation(presentation).build() new GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction.Builder().presentation(presentation).build()
)); ));
} }
public GroupChange.Actions.Builder createRemoveInvitationChange(final Set<UuidCiphertext> uuidCipherTextsFromInvitesToRemove) { public GroupChange.Actions.Builder createRemoveInvitationChange(final Set<UuidCiphertext> uuidCipherTextsFromInvitesToRemove) {
GroupChange.Actions.Builder builder = new GroupChange.Actions.Builder(); GroupChange.Actions.Builder builder = new GroupChange.Actions.Builder();
builder.deletePendingMembers = uuidCipherTextsFromInvitesToRemove.stream() builder.deleteMembersPendingProfileKey = uuidCipherTextsFromInvitesToRemove.stream()
.map(uuidCipherText -> new GroupChange.Actions.DeletePendingMemberAction.Builder().deletedUserId(ByteString.of(uuidCipherText.serialize())) .map(uuidCipherText -> new GroupChange.Actions.DeleteMemberPendingProfileKeyAction.Builder().deletedUserId(ByteString.of(uuidCipherText.serialize()))
.build()) .build())
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -342,8 +342,8 @@ public final class GroupsV2Operations {
} }
public GroupChange.Actions.Builder createAnnouncementGroupChange(boolean isAnnouncementGroup) { public GroupChange.Actions.Builder createAnnouncementGroupChange(boolean isAnnouncementGroup) {
return new GroupChange.Actions.Builder().modifyAnnouncementsOnly( return new GroupChange.Actions.Builder().modify_announcements_only(
new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder().announcementsOnly(isAnnouncementGroup).build() new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder().announcements_only(isAnnouncementGroup).build()
); );
} }
@@ -360,18 +360,18 @@ public final class GroupsV2Operations {
.map(m -> m.serviceIdBytes) .map(m -> m.serviceIdBytes)
.collect(Collectors.toList()); .collect(Collectors.toList());
List<GroupChange.Actions.DeleteBannedMemberAction> deleteBannedMemberActions = new ArrayList<>(builder.deleteBannedMembers); List<GroupChange.Actions.DeleteMemberBannedAction> deleteBannedMemberActions = new ArrayList<>(builder.delete_members_banned);
for (ByteString serviceIdBinary : unban) { for (ByteString serviceIdBinary : unban) {
deleteBannedMemberActions.add(new GroupChange.Actions.DeleteBannedMemberAction.Builder().deletedUserId(encryptServiceId(ServiceId.parseOrThrow(serviceIdBinary.toByteArray()))).build()); deleteBannedMemberActions.add(new GroupChange.Actions.DeleteMemberBannedAction.Builder().deletedUserId(encryptServiceId(ServiceId.parseOrThrow(serviceIdBinary.toByteArray()))).build());
} }
builder.deleteBannedMembers(deleteBannedMemberActions); builder.delete_members_banned(deleteBannedMemberActions);
} }
List<GroupChange.Actions.AddBannedMemberAction> addBannedMemberActions = new ArrayList<>(builder.addBannedMembers); List<GroupChange.Actions.AddMemberBannedAction> AddMemberBannedActions = new ArrayList<>(builder.add_members_banned);
for (ServiceId banServiceId : banServiceIds) { for (ServiceId banServiceId : banServiceIds) {
addBannedMemberActions.add(new GroupChange.Actions.AddBannedMemberAction.Builder().added(new BannedMember.Builder().userId(encryptServiceId(banServiceId)).build()).build()); AddMemberBannedActions.add(new GroupChange.Actions.AddMemberBannedAction.Builder().added(new MemberBanned.Builder().userId(encryptServiceId(banServiceId)).build()).build());
} }
builder.addBannedMembers(addBannedMemberActions); builder.add_members_banned(AddMemberBannedActions);
return builder; return builder;
} }
@@ -379,8 +379,8 @@ public final class GroupsV2Operations {
public GroupChange.Actions.Builder createUnbanServiceIdsChange(Set<ServiceId> serviceIds) { public GroupChange.Actions.Builder createUnbanServiceIdsChange(Set<ServiceId> serviceIds) {
GroupChange.Actions.Builder builder = new GroupChange.Actions.Builder(); GroupChange.Actions.Builder builder = new GroupChange.Actions.Builder();
builder.deleteBannedMembers = serviceIds.stream() builder.delete_members_banned = serviceIds.stream()
.map(serviceId -> new GroupChange.Actions.DeleteBannedMemberAction.Builder().deletedUserId(encryptServiceId(serviceId)).build()) .map(serviceId -> new GroupChange.Actions.DeleteMemberBannedAction.Builder().deletedUserId(encryptServiceId(serviceId)).build())
.collect(Collectors.toList()); .collect(Collectors.toList());
return builder; return builder;
@@ -415,20 +415,20 @@ public final class GroupsV2Operations {
.presentation(ByteString.of(presentation.serialize())); .presentation(ByteString.of(presentation.serialize()));
} }
private RequestingMember.Builder requestingMember(ExpiringProfileKeyCredential credential) { private MemberPendingAdminApproval.Builder requestingMember(ExpiringProfileKeyCredential credential) {
ProfileKeyCredentialPresentation presentation = clientZkProfileOperations.createProfileKeyCredentialPresentation(new SecureRandom(), groupSecretParams, credential); ProfileKeyCredentialPresentation presentation = clientZkProfileOperations.createProfileKeyCredentialPresentation(new SecureRandom(), groupSecretParams, credential);
return new RequestingMember.Builder().presentation(ByteString.of(presentation.serialize())); return new MemberPendingAdminApproval.Builder().presentation(ByteString.of(presentation.serialize()));
} }
public PendingMember.Builder invitee(ServiceId serviceId, Member.Role role) { public MemberPendingProfileKey.Builder invitee(ServiceId serviceId, Member.Role role) {
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encrypt(serviceId.getLibSignalServiceId()); UuidCiphertext uuidCiphertext = clientZkGroupCipher.encrypt(serviceId.getLibSignalServiceId());
Member member = new Member.Builder().role(role) Member member = new Member.Builder().role(role)
.userId(ByteString.of(uuidCiphertext.serialize())) .userId(ByteString.of(uuidCiphertext.serialize()))
.build(); .build();
return new PendingMember.Builder().member(member); return new MemberPendingProfileKey.Builder().member(member);
} }
public @Nonnull DecryptedGroupResponse decryptGroup(@Nonnull Group group, @Nonnull byte[] groupSendEndorsementsBytes) public @Nonnull DecryptedGroupResponse decryptGroup(@Nonnull Group group, @Nonnull byte[] groupSendEndorsementsBytes)
@@ -443,13 +443,13 @@ public final class GroupsV2Operations {
public DecryptedGroup decryptGroup(Group group) public DecryptedGroup decryptGroup(Group group)
throws VerificationFailedException, InvalidGroupStateException throws VerificationFailedException, InvalidGroupStateException
{ {
List<Member> membersList = group.members; List<Member> membersList = group.members;
List<PendingMember> pendingMembersList = group.pendingMembers; List<MemberPendingProfileKey> pendingMembersList = group.membersPendingProfileKey;
List<RequestingMember> requestingMembersList = group.requestingMembers; List<MemberPendingAdminApproval> requestingMembersList = group.membersPendingAdminApproval;
List<DecryptedMember> decryptedMembers = new ArrayList<>(membersList.size()); List<DecryptedMember> decryptedMembers = new ArrayList<>(membersList.size());
List<DecryptedPendingMember> decryptedPendingMembers = new ArrayList<>(pendingMembersList.size()); List<DecryptedPendingMember> decryptedPendingMembers = new ArrayList<>(pendingMembersList.size());
List<DecryptedRequestingMember> decryptedRequestingMembers = new ArrayList<>(requestingMembersList.size()); List<DecryptedRequestingMember> decryptedRequestingMembers = new ArrayList<>(requestingMembersList.size());
List<DecryptedBannedMember> decryptedBannedMembers = new ArrayList<>(group.bannedMembers.size()); List<DecryptedBannedMember> decryptedBannedMembers = new ArrayList<>(group.members_banned.size());
for (Member member : membersList) { for (Member member : membersList) {
try { try {
@@ -459,25 +459,25 @@ public final class GroupsV2Operations {
} }
} }
for (PendingMember member : pendingMembersList) { for (MemberPendingProfileKey member : pendingMembersList) {
decryptedPendingMembers.add(decryptMember(member)); decryptedPendingMembers.add(decryptMember(member));
} }
for (RequestingMember member : requestingMembersList) { for (MemberPendingAdminApproval member : requestingMembersList) {
decryptedRequestingMembers.add(decryptRequestingMember(member)); decryptedRequestingMembers.add(decryptRequestingMember(member));
} }
for (BannedMember member : group.bannedMembers) { for (MemberBanned member : group.members_banned) {
decryptedBannedMembers.add(new DecryptedBannedMember.Builder().serviceIdBytes(decryptServiceIdToBinary(member.userId)).timestamp(member.timestamp).build()); decryptedBannedMembers.add(new DecryptedBannedMember.Builder().serviceIdBytes(decryptServiceIdToBinary(member.userId)).timestamp(member.timestamp).build());
} }
return new DecryptedGroup.Builder() return new DecryptedGroup.Builder()
.title(decryptTitle(group.title)) .title(decryptTitle(group.title))
.description(decryptDescription(group.description)) .description(decryptDescription(group.description))
.isAnnouncementGroup(group.announcementsOnly ? EnabledState.ENABLED : EnabledState.DISABLED) .isAnnouncementGroup(group.announcements_only ? EnabledState.ENABLED : EnabledState.DISABLED)
.avatar(group.avatar) .avatar(group.avatarUrl)
.accessControl(group.accessControl) .accessControl(group.accessControl)
.revision(group.revision) .revision(group.version)
.members(decryptedMembers) .members(decryptedMembers)
.pendingMembers(decryptedPendingMembers) .pendingMembers(decryptedPendingMembers)
.requestingMembers(decryptedRequestingMembers) .requestingMembers(decryptedRequestingMembers)
@@ -506,7 +506,7 @@ public final class GroupsV2Operations {
if (verification.verify()) { if (verification.verify()) {
GroupIdentifier groupId = verification.groupId(); GroupIdentifier groupId = verification.groupId();
if (groupId == null || !Arrays.equals(groupId.serialize(), actions.groupId.toByteArray())) { if (groupId == null || !Arrays.equals(groupId.serialize(), actions.group_id.toByteArray())) {
throw new VerificationFailedException("Invalid group id"); throw new VerificationFailedException("Invalid group id");
} }
} }
@@ -530,18 +530,18 @@ public final class GroupsV2Operations {
if (source != null) { if (source != null) {
editorServiceId = source; editorServiceId = source;
} else { } else {
editorServiceId = decryptServiceId(actions.sourceServiceId); editorServiceId = decryptServiceId(actions.sourceUserId);
} }
builder.editorServiceIdBytes(editorServiceId.toByteString()); builder.editorServiceIdBytes(editorServiceId.toByteString());
// Field 2 // Field 2
builder.revision(actions.revision); builder.revision(actions.version);
// Field 3 // Field 3
List<DecryptedMember> newMembers = new ArrayList<>(actions.addMembers.size()); List<DecryptedMember> newMembers = new ArrayList<>(actions.addMembers.size());
for (GroupChange.Actions.AddMemberAction addMemberAction : actions.addMembers) { for (GroupChange.Actions.AddMemberAction addMemberAction : actions.addMembers) {
try { try {
newMembers.add(decryptMember(addMemberAction.added).joinedAtRevision(actions.revision).build()); newMembers.add(decryptMember(addMemberAction.added).joinedAtRevision(actions.version).build());
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
throw new InvalidGroupStateException(e); throw new InvalidGroupStateException(e);
} }
@@ -593,9 +593,9 @@ public final class GroupsV2Operations {
builder.modifiedProfileKeys(modifiedProfileKeys); builder.modifiedProfileKeys(modifiedProfileKeys);
// Field 7 // Field 7
List<DecryptedPendingMember> newPendingMembers = new ArrayList<>(actions.addPendingMembers.size()); List<DecryptedPendingMember> newPendingMembers = new ArrayList<>(actions.addMembersPendingProfileKey.size());
for (GroupChange.Actions.AddPendingMemberAction addPendingMemberAction : actions.addPendingMembers) { for (GroupChange.Actions.AddMemberPendingProfileKeyAction AddMemberPendingProfileKeyAction : actions.addMembersPendingProfileKey) {
PendingMember added = addPendingMemberAction.added; MemberPendingProfileKey added = AddMemberPendingProfileKeyAction.added;
Member member = added.member; Member member = added.member;
ByteString serviceIdCipherText = member.userId; ByteString serviceIdCipherText = member.userId;
ServiceId serviceId = decryptServiceIdOrUnknown(serviceIdCipherText); ServiceId serviceId = decryptServiceIdOrUnknown(serviceIdCipherText);
@@ -611,9 +611,9 @@ public final class GroupsV2Operations {
builder.newPendingMembers(newPendingMembers); builder.newPendingMembers(newPendingMembers);
// Field 8 // Field 8
List<DecryptedPendingMemberRemoval> deletePendingMembers = new ArrayList<>(actions.deletePendingMembers.size()); List<DecryptedPendingMemberRemoval> deletePendingMembers = new ArrayList<>(actions.deleteMembersPendingProfileKey.size());
for (GroupChange.Actions.DeletePendingMemberAction deletePendingMemberAction : actions.deletePendingMembers) { for (GroupChange.Actions.DeleteMemberPendingProfileKeyAction DeleteMemberPendingProfileKeyAction : actions.deleteMembersPendingProfileKey) {
ByteString serviceIdCipherText = deletePendingMemberAction.deletedUserId; ByteString serviceIdCipherText = DeleteMemberPendingProfileKeyAction.deletedUserId;
ServiceId serviceId = decryptServiceIdOrUnknown(serviceIdCipherText); ServiceId serviceId = decryptServiceIdOrUnknown(serviceIdCipherText);
deletePendingMembers.add(new DecryptedPendingMemberRemoval.Builder() deletePendingMembers.add(new DecryptedPendingMemberRemoval.Builder()
@@ -624,19 +624,19 @@ public final class GroupsV2Operations {
builder.deletePendingMembers(deletePendingMembers); builder.deletePendingMembers(deletePendingMembers);
// Field 9 // Field 9
List<DecryptedMember> promotePendingMembers = new ArrayList<>(actions.promotePendingMembers.size()); List<DecryptedMember> promotePendingMembers = new ArrayList<>(actions.promoteMembersPendingProfileKey.size());
for (GroupChange.Actions.PromotePendingMemberAction promotePendingMemberAction : actions.promotePendingMembers) { for (GroupChange.Actions.PromoteMemberPendingProfileKeyAction PromoteMemberPendingProfileKeyAction : actions.promoteMembersPendingProfileKey) {
try { try {
ACI aci; ACI aci;
ProfileKey profileKey; ProfileKey profileKey;
if (promotePendingMemberAction.user_id.size() == 0 || promotePendingMemberAction.profile_key.size() == 0) { if (PromoteMemberPendingProfileKeyAction.user_id.size() == 0 || PromoteMemberPendingProfileKeyAction.profile_key.size() == 0) {
ProfileKeyCredentialPresentation presentation = new ProfileKeyCredentialPresentation(promotePendingMemberAction.presentation.toByteArray()); ProfileKeyCredentialPresentation presentation = new ProfileKeyCredentialPresentation(PromoteMemberPendingProfileKeyAction.presentation.toByteArray());
aci = decryptAci(ByteString.of(presentation.getUuidCiphertext().serialize())); aci = decryptAci(ByteString.of(presentation.getUuidCiphertext().serialize()));
profileKey = decryptProfileKey(ByteString.of(presentation.getProfileKeyCiphertext().serialize()), aci); profileKey = decryptProfileKey(ByteString.of(presentation.getProfileKeyCiphertext().serialize()), aci);
} else { } else {
aci = decryptAci(promotePendingMemberAction.user_id); aci = decryptAci(PromoteMemberPendingProfileKeyAction.user_id);
profileKey = decryptProfileKey(promotePendingMemberAction.profile_key, aci); profileKey = decryptProfileKey(PromoteMemberPendingProfileKeyAction.profile_key, aci);
} }
promotePendingMembers.add(new DecryptedMember.Builder() promotePendingMembers.add(new DecryptedMember.Builder()
@@ -662,8 +662,8 @@ public final class GroupsV2Operations {
} }
// Field 12 // Field 12
if (actions.modifyDisappearingMessagesTimer != null) { if (actions.modifyDisappearingMessageTimer != null) {
int duration = decryptDisappearingMessagesTimer(actions.modifyDisappearingMessagesTimer.timer); int duration = decryptDisappearingMessagesTimer(actions.modifyDisappearingMessageTimer.timer);
builder.newTimer(new DecryptedTimer.Builder().duration(duration).build()); builder.newTimer(new DecryptedTimer.Builder().duration(duration).build());
} }
@@ -683,22 +683,22 @@ public final class GroupsV2Operations {
} }
// Field 16 // Field 16
List<DecryptedRequestingMember> newRequestingMembers = new ArrayList<>(actions.addRequestingMembers.size()); List<DecryptedRequestingMember> newRequestingMembers = new ArrayList<>(actions.addMembersPendingAdminApproval.size());
for (GroupChange.Actions.AddRequestingMemberAction request : actions.addRequestingMembers) { for (GroupChange.Actions.AddMemberPendingAdminApprovalAction request : actions.addMembersPendingAdminApproval) {
newRequestingMembers.add(decryptRequestingMember(request.added)); newRequestingMembers.add(decryptRequestingMember(request.added));
} }
builder.newRequestingMembers(newRequestingMembers); builder.newRequestingMembers(newRequestingMembers);
// Field 17 // Field 17
List<ByteString> deleteRequestingMembers = new ArrayList<>(actions.deleteRequestingMembers.size()); List<ByteString> deleteRequestingMembers = new ArrayList<>(actions.deleteMembersPendingAdminApproval.size());
for (GroupChange.Actions.DeleteRequestingMemberAction delete : actions.deleteRequestingMembers) { for (GroupChange.Actions.DeleteMemberPendingAdminApprovalAction delete : actions.deleteMembersPendingAdminApproval) {
deleteRequestingMembers.add(decryptServiceIdToBinary(delete.deletedUserId)); deleteRequestingMembers.add(decryptServiceIdToBinary(delete.deletedUserId));
} }
builder.deleteRequestingMembers(deleteRequestingMembers); builder.deleteRequestingMembers(deleteRequestingMembers);
// Field 18 // Field 18
List<DecryptedApproveMember> promoteRequestingMembers = new ArrayList<>(actions.promoteRequestingMembers.size()); List<DecryptedApproveMember> promoteRequestingMembers = new ArrayList<>(actions.promoteMembersPendingAdminApproval.size());
for (GroupChange.Actions.PromoteRequestingMemberAction promote : actions.promoteRequestingMembers) { for (GroupChange.Actions.PromoteMemberPendingAdminApprovalAction promote : actions.promoteMembersPendingAdminApproval) {
promoteRequestingMembers.add(new DecryptedApproveMember.Builder().role(promote.role).aciBytes(decryptAciToBinary(promote.userId)).build()); promoteRequestingMembers.add(new DecryptedApproveMember.Builder().role(promote.role).aciBytes(decryptAciToBinary(promote.userId)).build());
} }
builder.promoteRequestingMembers(promoteRequestingMembers); builder.promoteRequestingMembers(promoteRequestingMembers);
@@ -714,30 +714,30 @@ public final class GroupsV2Operations {
} }
// Field 21 // Field 21
if (actions.modifyAnnouncementsOnly != null) { if (actions.modify_announcements_only != null) {
builder.newIsAnnouncementGroup(actions.modifyAnnouncementsOnly.announcementsOnly ? EnabledState.ENABLED : EnabledState.DISABLED); builder.newIsAnnouncementGroup(actions.modify_announcements_only.announcements_only ? EnabledState.ENABLED : EnabledState.DISABLED);
} }
// Field 22 // Field 22
List<DecryptedBannedMember> newBannedMembers = new ArrayList<>(actions.addBannedMembers.size()); List<DecryptedBannedMember> newBannedMembers = new ArrayList<>(actions.add_members_banned.size());
for (GroupChange.Actions.AddBannedMemberAction action : actions.addBannedMembers) { for (GroupChange.Actions.AddMemberBannedAction action : actions.add_members_banned) {
newBannedMembers.add(new DecryptedBannedMember.Builder().serviceIdBytes(decryptServiceIdToBinary(action.added.userId)).timestamp(action.added.timestamp).build()); newBannedMembers.add(new DecryptedBannedMember.Builder().serviceIdBytes(decryptServiceIdToBinary(action.added.userId)).timestamp(action.added.timestamp).build());
} }
builder.newBannedMembers(newBannedMembers); builder.newBannedMembers(newBannedMembers);
// Field 23 // Field 23
List<DecryptedBannedMember> deleteBannedMembers = new ArrayList<>(actions.deleteBannedMembers.size()); List<DecryptedBannedMember> deleteBannedMembers = new ArrayList<>(actions.delete_members_banned.size());
for (GroupChange.Actions.DeleteBannedMemberAction action : actions.deleteBannedMembers) { for (GroupChange.Actions.DeleteMemberBannedAction action : actions.delete_members_banned) {
deleteBannedMembers.add(new DecryptedBannedMember.Builder().serviceIdBytes(decryptServiceIdToBinary(action.deletedUserId)).build()); deleteBannedMembers.add(new DecryptedBannedMember.Builder().serviceIdBytes(decryptServiceIdToBinary(action.deletedUserId)).build());
} }
builder.deleteBannedMembers(deleteBannedMembers); builder.deleteBannedMembers(deleteBannedMembers);
// Field 24 // Field 24
List<DecryptedMember> promotePendingPniAciMembers = new ArrayList<>(actions.promotePendingPniAciMembers.size()); List<DecryptedMember> promotePendingPniAciMembers = new ArrayList<>(actions.promote_members_pending_pni_aci_profile_key.size());
for (GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction promotePendingPniAciMemberAction : actions.promotePendingPniAciMembers) { for (GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction promotePendingPniAciMemberAction : actions.promote_members_pending_pni_aci_profile_key) {
ACI aci = decryptAci(promotePendingPniAciMemberAction.userId); ACI aci = decryptAci(promotePendingPniAciMemberAction.user_id);
ServiceId pni = decryptServiceId(promotePendingPniAciMemberAction.pni); ServiceId pni = decryptServiceId(promotePendingPniAciMemberAction.pni);
ProfileKey profileKey = decryptProfileKey(promotePendingPniAciMemberAction.profileKey, aci); ProfileKey profileKey = decryptProfileKey(promotePendingPniAciMemberAction.profile_key, aci);
if (!(pni instanceof PNI)) { if (!(pni instanceof PNI)) {
throw new InvalidGroupStateException(); throw new InvalidGroupStateException();
@@ -748,7 +748,7 @@ public final class GroupsV2Operations {
.aciBytes(aci.toByteString()) .aciBytes(aci.toByteString())
.role(Member.Role.DEFAULT) .role(Member.Role.DEFAULT)
.profileKey(ByteString.of(profileKey.serialize())) .profileKey(ByteString.of(profileKey.serialize()))
.joinedAtRevision(actions.revision) .joinedAtRevision(actions.version)
.pniBytes(pni.toByteString()) .pniBytes(pni.toByteString())
.build()); .build());
} }
@@ -766,7 +766,7 @@ public final class GroupsV2Operations {
Log.w(TAG, "Unable to replace PNI editor with ACI for add member update"); Log.w(TAG, "Unable to replace PNI editor with ACI for add member update");
builder.editorServiceIdBytes(ByteString.EMPTY); builder.editorServiceIdBytes(ByteString.EMPTY);
} }
} else if (actions.deletePendingMembers.isEmpty() && actions.promotePendingPniAciMembers.isEmpty()) { } else if (actions.deleteMembersPendingProfileKey.isEmpty() && actions.promote_members_pending_pni_aci_profile_key.isEmpty()) {
Log.w(TAG, "Received group change with PNI editor for a non-PNI editor eligible update, clearing editor"); Log.w(TAG, "Received group change with PNI editor for a non-PNI editor eligible update, clearing editor");
builder.editorServiceIdBytes(ByteString.EMPTY); builder.editorServiceIdBytes(ByteString.EMPTY);
} }
@@ -781,7 +781,7 @@ public final class GroupsV2Operations {
.avatar(joinInfo.avatar) .avatar(joinInfo.avatar)
.memberCount(joinInfo.memberCount) .memberCount(joinInfo.memberCount)
.addFromInviteLink(joinInfo.addFromInviteLink) .addFromInviteLink(joinInfo.addFromInviteLink)
.revision(joinInfo.revision) .revision(joinInfo.version)
.pendingAdminApproval(joinInfo.pendingAdminApproval) .pendingAdminApproval(joinInfo.pendingAdminApproval)
.description(decryptDescription(joinInfo.description)) .description(decryptDescription(joinInfo.description))
.build(); .build();
@@ -795,7 +795,7 @@ public final class GroupsV2Operations {
return new DecryptedMember.Builder() return new DecryptedMember.Builder()
.aciBytes(aci.toByteString()) .aciBytes(aci.toByteString())
.joinedAtRevision(member.joinedAtRevision) .joinedAtRevision(member.joinedAtVersion)
.profileKey(decryptProfileKeyToByteString(member.profileKey, aci)) .profileKey(decryptProfileKeyToByteString(member.profileKey, aci))
.role(member.role); .role(member.role);
} else { } else {
@@ -811,13 +811,13 @@ public final class GroupsV2Operations {
return new DecryptedMember.Builder() return new DecryptedMember.Builder()
.aciBytes(aci.toByteString()) .aciBytes(aci.toByteString())
.joinedAtRevision(member.joinedAtRevision) .joinedAtRevision(member.joinedAtVersion)
.profileKey(ByteString.of(profileKey.serialize())) .profileKey(ByteString.of(profileKey.serialize()))
.role(member.role); .role(member.role);
} }
} }
private DecryptedPendingMember decryptMember(PendingMember member) private DecryptedPendingMember decryptMember(MemberPendingProfileKey member)
throws InvalidGroupStateException, VerificationFailedException throws InvalidGroupStateException, VerificationFailedException
{ {
ByteString userIdCipherText = member.member.userId; ByteString userIdCipherText = member.member.userId;
@@ -839,7 +839,7 @@ public final class GroupsV2Operations {
.build(); .build();
} }
private DecryptedRequestingMember decryptRequestingMember(RequestingMember member) private DecryptedRequestingMember decryptRequestingMember(MemberPendingAdminApproval member)
throws InvalidGroupStateException, VerificationFailedException throws InvalidGroupStateException, VerificationFailedException
{ {
if (member.presentation.size() == 0) { if (member.presentation.size() == 0) {
@@ -956,7 +956,7 @@ public final class GroupsV2Operations {
ByteString encryptDescription(String description) { ByteString encryptDescription(String description) {
try { try {
GroupAttributeBlob blob = new GroupAttributeBlob.Builder().description(description).build(); GroupAttributeBlob blob = new GroupAttributeBlob.Builder().descriptionText(description).build();
return ByteString.of(clientZkGroupCipher.encryptBlob(blob.encode())); return ByteString.of(clientZkGroupCipher.encryptBlob(blob.encode()));
} catch (VerificationFailedException e) { } catch (VerificationFailedException e) {
@@ -965,7 +965,7 @@ public final class GroupsV2Operations {
} }
private String decryptDescription(ByteString cipherText) { private String decryptDescription(ByteString cipherText) {
String description = decryptBlob(cipherText).description; String description = decryptBlob(cipherText).descriptionText;
return description != null ? description.trim() : ""; return description != null ? description.trim() : "";
} }
@@ -14,15 +14,15 @@ import org.signal.core.util.Base64;
import org.signal.core.util.Hex; import org.signal.core.util.Hex;
import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.logging.Log; import org.signal.libsignal.protocol.logging.Log;
import org.signal.storageservice.protos.groups.AvatarUploadAttributes; import org.signal.storageservice.storage.protos.groups.AvatarUploadAttributes;
import org.signal.storageservice.protos.groups.Group; import org.signal.storageservice.storage.protos.groups.Group;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.GroupChangeResponse; import org.signal.storageservice.storage.protos.groups.GroupChangeResponse;
import org.signal.storageservice.protos.groups.GroupChanges; import org.signal.storageservice.storage.protos.groups.GroupChanges;
import org.signal.storageservice.protos.groups.GroupExternalCredential; import org.signal.storageservice.storage.protos.groups.ExternalGroupCredential;
import org.signal.storageservice.protos.groups.GroupJoinInfo; import org.signal.storageservice.storage.protos.groups.GroupJoinInfo;
import org.signal.storageservice.protos.groups.GroupResponse; import org.signal.storageservice.storage.protos.groups.GroupResponse;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.whispersystems.signalservice.api.NetworkResult; import org.whispersystems.signalservice.api.NetworkResult;
import org.whispersystems.signalservice.api.account.AccountAttributes; import org.whispersystems.signalservice.api.account.AccountAttributes;
import org.whispersystems.signalservice.api.account.PreKeyCollection; import org.whispersystems.signalservice.api.account.PreKeyCollection;
@@ -2066,7 +2066,7 @@ public class PushServiceSocket {
null, null,
GROUPS_V2_GET_CURRENT_HANDLER)) GROUPS_V2_GET_CURRENT_HANDLER))
{ {
return Member.ADAPTER.decode(readBodyBytes(response)).joinedAtRevision; return Member.ADAPTER.decode(readBodyBytes(response)).joinedAtVersion;
} }
} }
@@ -2084,7 +2084,7 @@ public class PushServiceSocket {
} }
} }
public GroupExternalCredential getGroupExternalCredential(GroupsV2AuthorizationString authorization) public ExternalGroupCredential getExternalGroupCredential(GroupsV2AuthorizationString authorization)
throws NonSuccessfulResponseCodeException, PushNetworkException, IOException, MalformedResponseException throws NonSuccessfulResponseCodeException, PushNetworkException, IOException, MalformedResponseException
{ {
try (Response response = makeStorageRequest(authorization.toString(), try (Response response = makeStorageRequest(authorization.toString(),
@@ -2093,7 +2093,7 @@ public class PushServiceSocket {
null, null,
NO_HANDLER)) NO_HANDLER))
{ {
return GroupExternalCredential.ADAPTER.decode(readBodyBytes(response)); return ExternalGroupCredential.ADAPTER.decode(readBodyBytes(response));
} }
} }
@@ -5,7 +5,9 @@
*/ */
syntax = "proto3"; syntax = "proto3";
option java_package = "org.signal.storageservice.protos.groups.local"; package signal;
option java_package = "org.signal.storageservice.storage.protos.groups.local";
option java_multiple_files = true; option java_multiple_files = true;
import "Groups.proto"; import "Groups.proto";
@@ -1,92 +1,135 @@
/** /*
* Copyright (C) 2019 Open Whisper Systems * Copyright 2020 Signal Messenger, LLC
* * SPDX-License-Identifier: AGPL-3.0-only
* Licensed according to the LICENSE file in this repository.
*/ */
syntax = "proto3"; syntax = "proto3";
option java_package = "org.signal.storageservice.protos.groups"; package signal;
option java_package = "org.signal.storageservice.storage.protos.groups";
option java_outer_classname = "GroupProtos";
option java_multiple_files = true; option java_multiple_files = true;
message AvatarUploadAttributes { message AvatarUploadAttributes {
string key = 1; string key = 1;
string credential = 2; string credential = 2;
string acl = 3; string acl = 3;
string algorithm = 4; string algorithm = 4;
string date = 5; string date = 5;
string policy = 6; string policy = 6;
string signature = 7; string signature = 7;
} }
// Stored data
message Member { message Member {
enum Role { enum Role {
UNKNOWN = 0; UNKNOWN = 0;
DEFAULT = 1; DEFAULT = 1;
ADMINISTRATOR = 2; ADMINISTRATOR = 2;
} }
bytes userId = 1; bytes userId = 1;
Role role = 2; Role role = 2;
bytes profileKey = 3; bytes profileKey = 3;
bytes presentation = 4; // Only set when sending to server bytes presentation = 4;
uint32 joinedAtRevision = 5; uint32 joinedAtVersion = 5;
} }
message PendingMember { message MemberPendingProfileKey {
Member member = 1; Member member = 1;
bytes addedByUserId = 2; bytes addedByUserId = 2;
uint64 timestamp = 3; uint64 timestamp = 3; // ms since epoch
} }
message RequestingMember { message MemberPendingAdminApproval {
bytes userId = 1; bytes userId = 1;
bytes profileKey = 2; bytes profileKey = 2;
bytes presentation = 3; // Only set when sending to server bytes presentation = 3;
uint64 timestamp = 4; uint64 timestamp = 4; // ms since epoch
} }
message BannedMember { message MemberBanned {
bytes userId = 1; bytes userId = 1;
uint64 timestamp = 2; uint64 timestamp = 2; // ms since epoch
} }
message AccessControl { message AccessControl {
enum AccessRequired { enum AccessRequired {
UNKNOWN = 0; UNKNOWN = 0;
ANY = 1; ANY = 1;
MEMBER = 2; MEMBER = 2;
ADMINISTRATOR = 3; ADMINISTRATOR = 3;
UNSATISFIABLE = 4; UNSATISFIABLE = 4;
} }
AccessRequired attributes = 1; AccessRequired attributes = 1;
AccessRequired members = 2; AccessRequired members = 2;
AccessRequired addFromInviteLink = 3; AccessRequired addFromInviteLink = 3;
} }
message Group { message Group {
bytes publicKey = 1; bytes publicKey = 1;
bytes title = 2; bytes title = 2;
string avatar = 3; bytes description = 11;
bytes disappearingMessagesTimer = 4; // The URL for this group's avatar. The content at this URL can be
AccessControl accessControl = 5; // decrypted/deserialized into a `GroupAttributeBlob`.
uint32 revision = 6; string avatarUrl = 3;
repeated Member members = 7; bytes disappearingMessagesTimer = 4;
repeated PendingMember pendingMembers = 8; AccessControl accessControl = 5;
repeated RequestingMember requestingMembers = 9; uint32 version = 6;
bytes inviteLinkPassword = 10; repeated Member members = 7;
bytes description = 11; repeated MemberPendingProfileKey membersPendingProfileKey = 8;
bool announcementsOnly = 12; repeated MemberPendingAdminApproval membersPendingAdminApproval = 9;
repeated BannedMember bannedMembers = 13; bytes inviteLinkPassword = 10;
bool announcements_only = 12;
repeated MemberBanned members_banned = 13;
// next: 14
} }
message GroupAttributeBlob {
oneof content {
string title = 1;
bytes avatar = 2;
uint32 disappearingMessagesDuration = 3;
string descriptionText = 4;
}
}
message GroupInviteLink {
message GroupInviteLinkContentsV1 {
bytes groupMasterKey = 1;
bytes inviteLinkPassword = 2;
}
oneof contents {
GroupInviteLinkContentsV1 contentsV1 = 1;
}
}
message GroupJoinInfo {
bytes publicKey = 1;
bytes title = 2;
bytes description = 8;
string avatar = 3;
uint32 memberCount = 4;
AccessControl.AccessRequired addFromInviteLink = 5;
uint32 version = 6;
bool pendingAdminApproval = 7;
// bool pendingAdminApprovalFull = 9;
// next: 10
}
// Deltas
message GroupChange { message GroupChange {
message Actions { message Actions {
message AddMemberAction { message AddMemberAction {
Member added = 1; Member added = 1;
bool joinFromInviteLink = 2; bool joinFromInviteLink = 2;
} }
message DeleteMemberAction { message DeleteMemberAction {
@@ -94,55 +137,55 @@ message GroupChange {
} }
message ModifyMemberRoleAction { message ModifyMemberRoleAction {
bytes userId = 1; bytes userId = 1;
Member.Role role = 2; Member.Role role = 2;
} }
message ModifyMemberProfileKeyAction { message ModifyMemberProfileKeyAction {
bytes presentation = 1; // Only set when sending to server bytes presentation = 1;
bytes user_id = 2; // Only set when receiving from server bytes user_id = 2;
bytes profile_key = 3; // Only set when receiving from server bytes profile_key = 3;
} }
message AddPendingMemberAction { message AddMemberPendingProfileKeyAction {
PendingMember added = 1; MemberPendingProfileKey added = 1;
} }
message DeletePendingMemberAction { message DeleteMemberPendingProfileKeyAction {
bytes deletedUserId = 1; bytes deletedUserId = 1;
} }
message PromotePendingMemberAction { message PromoteMemberPendingProfileKeyAction {
bytes presentation = 1; // Only set when sending to server bytes presentation = 1;
bytes user_id = 2; // Only set when receiving from server bytes user_id = 2;
bytes profile_key = 3; // Only set when receiving from server bytes profile_key = 3;
} }
message PromotePendingPniAciMemberProfileKeyAction { message PromoteMemberPendingPniAciProfileKeyAction {
bytes presentation = 1; // Only set when sending to server bytes presentation = 1;
bytes userId = 2; // Only set when receiving from server bytes user_id = 2;
bytes pni = 3; // Only set when receiving from server bytes pni = 3;
bytes profileKey = 4; // Only set when receiving from server bytes profile_key = 4;
} }
message AddRequestingMemberAction { message AddMemberPendingAdminApprovalAction {
RequestingMember added = 1; MemberPendingAdminApproval added = 1;
} }
message DeleteRequestingMemberAction { message DeleteMemberPendingAdminApprovalAction {
bytes deletedUserId = 1; bytes deletedUserId = 1;
} }
message PromoteRequestingMemberAction { message PromoteMemberPendingAdminApprovalAction {
bytes userId = 1; bytes userId = 1;
Member.Role role = 2; Member.Role role = 2;
} }
message AddBannedMemberAction { message AddMemberBannedAction {
BannedMember added = 1; MemberBanned added = 1;
} }
message DeleteBannedMemberAction { message DeleteMemberBannedAction {
bytes deletedUserId = 1; bytes deletedUserId = 1;
} }
@@ -158,7 +201,7 @@ message GroupChange {
string avatar = 1; string avatar = 1;
} }
message ModifyDisappearingMessagesTimerAction { message ModifyDisappearingMessageTimerAction {
bytes timer = 1; bytes timer = 1;
} }
@@ -179,92 +222,69 @@ message GroupChange {
} }
message ModifyAnnouncementsOnlyAction { message ModifyAnnouncementsOnlyAction {
bool announcementsOnly = 1; bool announcements_only = 1;
} }
bytes sourceServiceId = 1; bytes sourceUserId = 1;
bytes groupId = 25; // Only set when receiving from server // clients should not provide this value; the server will provide it in the response buffer to ensure the signature is binding to a particular group
uint32 revision = 2; // if clients set it during a request the server will respond with 400.
repeated AddMemberAction addMembers = 3; bytes group_id = 25;
repeated DeleteMemberAction deleteMembers = 4; uint32 version = 2;
repeated ModifyMemberRoleAction modifyMemberRoles = 5;
repeated ModifyMemberProfileKeyAction modifyMemberProfileKeys = 6; repeated AddMemberAction addMembers = 3;
repeated AddPendingMemberAction addPendingMembers = 7; repeated DeleteMemberAction deleteMembers = 4;
repeated DeletePendingMemberAction deletePendingMembers = 8; repeated ModifyMemberRoleAction modifyMemberRoles = 5;
repeated PromotePendingMemberAction promotePendingMembers = 9; repeated ModifyMemberProfileKeyAction modifyMemberProfileKeys = 6;
ModifyTitleAction modifyTitle = 10; repeated AddMemberPendingProfileKeyAction addMembersPendingProfileKey = 7;
ModifyAvatarAction modifyAvatar = 11; repeated DeleteMemberPendingProfileKeyAction deleteMembersPendingProfileKey = 8;
ModifyDisappearingMessagesTimerAction modifyDisappearingMessagesTimer = 12; repeated PromoteMemberPendingProfileKeyAction promoteMembersPendingProfileKey = 9;
ModifyAttributesAccessControlAction modifyAttributesAccess = 13; ModifyTitleAction modifyTitle = 10;
ModifyMembersAccessControlAction modifyMemberAccess = 14; ModifyAvatarAction modifyAvatar = 11;
ModifyAddFromInviteLinkAccessControlAction modifyAddFromInviteLinkAccess = 15; ModifyDisappearingMessageTimerAction modifyDisappearingMessageTimer = 12;
repeated AddRequestingMemberAction addRequestingMembers = 16; ModifyAttributesAccessControlAction modifyAttributesAccess = 13;
repeated DeleteRequestingMemberAction deleteRequestingMembers = 17; ModifyMembersAccessControlAction modifyMemberAccess = 14;
repeated PromoteRequestingMemberAction promoteRequestingMembers = 18; ModifyAddFromInviteLinkAccessControlAction modifyAddFromInviteLinkAccess = 15; // change epoch = 1
ModifyInviteLinkPasswordAction modifyInviteLinkPassword = 19; repeated AddMemberPendingAdminApprovalAction addMembersPendingAdminApproval = 16; // change epoch = 1
ModifyDescriptionAction modifyDescription = 20; repeated DeleteMemberPendingAdminApprovalAction deleteMembersPendingAdminApproval = 17; // change epoch = 1
ModifyAnnouncementsOnlyAction modifyAnnouncementsOnly = 21; repeated PromoteMemberPendingAdminApprovalAction promoteMembersPendingAdminApproval = 18; // change epoch = 1
repeated AddBannedMemberAction addBannedMembers = 22; ModifyInviteLinkPasswordAction modifyInviteLinkPassword = 19; // change epoch = 1
repeated DeleteBannedMemberAction deleteBannedMembers = 23; ModifyDescriptionAction modifyDescription = 20; // change epoch = 2
repeated PromotePendingPniAciMemberProfileKeyAction promotePendingPniAciMembers = 24; ModifyAnnouncementsOnlyAction modify_announcements_only = 21; // change epoch = 3
repeated AddMemberBannedAction add_members_banned = 22; // change epoch = 4
repeated DeleteMemberBannedAction delete_members_banned = 23; // change epoch = 4
repeated PromoteMemberPendingPniAciProfileKeyAction promote_members_pending_pni_aci_profile_key = 24; // change epoch = 5
// next: 26
} }
bytes actions = 1; bytes actions = 1;
bytes serverSignature = 2; bytes serverSignature = 2;
uint32 changeEpoch = 3; uint32 changeEpoch = 3;
} }
// External credentials
message ExternalGroupCredential {
string token = 1;
}
// API responses
message GroupResponse { message GroupResponse {
Group group = 1; Group group = 1;
bytes groupSendEndorsementsResponse = 2; bytes group_send_endorsements_response = 2;
} }
message GroupChanges { message GroupChanges {
message GroupChangeState { message GroupChangeState {
GroupChange groupChange = 1; GroupChange groupChange = 1;
Group groupState = 2; Group groupState = 2;
} }
repeated GroupChangeState groupChanges = 1; repeated GroupChangeState groupChanges = 1;
bytes groupSendEndorsementsResponse = 2; bytes group_send_endorsements_response = 2;
} }
message GroupChangeResponse { message GroupChangeResponse {
GroupChange groupChange = 1; GroupChange group_change = 1;
bytes groupSendEndorsementsResponse = 2; bytes group_send_endorsements_response = 2;
}
message GroupAttributeBlob {
oneof content {
string title = 1;
bytes avatar = 2;
uint32 disappearingMessagesDuration = 3;
string description = 4;
}
}
message GroupInviteLink {
message GroupInviteLinkContentsV1 {
bytes groupMasterKey = 1;
bytes inviteLinkPassword = 2;
}
oneof contents {
GroupInviteLinkContentsV1 v1Contents = 1;
}
}
message GroupJoinInfo {
bytes publicKey = 1;
bytes title = 2;
string avatar = 3;
uint32 memberCount = 4;
AccessControl.AccessRequired addFromInviteLink = 5;
uint32 revision = 6;
bool pendingAdminApproval = 7;
bytes description = 8;
}
message GroupExternalCredential {
string token = 1;
} }
@@ -7,9 +7,9 @@ import assertk.assertions.isNull
import okio.ByteString import okio.ByteString
import org.junit.Test import org.junit.Test
import org.signal.core.models.ServiceId import org.signal.core.models.ServiceId
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval
import org.whispersystems.signalservice.internal.util.Util import org.whispersystems.signalservice.internal.util.Util
import java.util.UUID import java.util.UUID
@@ -2,20 +2,20 @@ package org.whispersystems.signalservice.api.groupsv2;
import org.junit.Test; import org.junit.Test;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
@@ -1,14 +1,14 @@
package org.whispersystems.signalservice.api.groupsv2; package org.whispersystems.signalservice.api.groupsv2;
import org.junit.Test; import org.junit.Test;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
import java.util.List; import java.util.List;
@@ -2,12 +2,12 @@ package org.whispersystems.signalservice.api.groupsv2;
import org.junit.Test; import org.junit.Test;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
@@ -1,7 +1,7 @@
package org.whispersystems.signalservice.api.groupsv2; package org.whispersystems.signalservice.api.groupsv2;
import org.junit.Test; import org.junit.Test;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import java.util.List; import java.util.List;
@@ -69,7 +69,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_add_pending_members_field_7() { public void not_empty_with_add_pending_members_field_7() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.addPendingMembers(List.of(new GroupChange.Actions.AddPendingMemberAction())) .addMembersPendingProfileKey(List.of(new GroupChange.Actions.AddMemberPendingProfileKeyAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -78,7 +78,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_delete_pending_members_field_8() { public void not_empty_with_delete_pending_members_field_8() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.deletePendingMembers(List.of(new GroupChange.Actions.DeletePendingMemberAction())) .deleteMembersPendingProfileKey(List.of(new GroupChange.Actions.DeleteMemberPendingProfileKeyAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -87,7 +87,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_promote_delete_pending_members_field_9() { public void not_empty_with_promote_delete_pending_members_field_9() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.promotePendingMembers(List.of(new GroupChange.Actions.PromotePendingMemberAction())) .promoteMembersPendingProfileKey(List.of(new GroupChange.Actions.PromoteMemberPendingProfileKeyAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -114,7 +114,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_modify_disappearing_message_timer_field_12() { public void not_empty_with_modify_disappearing_message_timer_field_12() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.modifyDisappearingMessagesTimer(new GroupChange.Actions.ModifyDisappearingMessagesTimerAction()) .modifyDisappearingMessageTimer(new GroupChange.Actions.ModifyDisappearingMessageTimerAction())
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -150,7 +150,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_add_requesting_members_field_16() { public void not_empty_with_add_requesting_members_field_16() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.addRequestingMembers(List.of(new GroupChange.Actions.AddRequestingMemberAction())) .addMembersPendingAdminApproval(List.of(new GroupChange.Actions.AddMemberPendingAdminApprovalAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -159,7 +159,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_delete_requesting_members_field_17() { public void not_empty_with_delete_requesting_members_field_17() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.deleteRequestingMembers(List.of(new GroupChange.Actions.DeleteRequestingMemberAction())) .deleteMembersPendingAdminApproval(List.of(new GroupChange.Actions.DeleteMemberPendingAdminApprovalAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -168,7 +168,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_promote_requesting_members_field_18() { public void not_empty_with_promote_requesting_members_field_18() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.promoteRequestingMembers(List.of(new GroupChange.Actions.PromoteRequestingMemberAction())) .promoteMembersPendingAdminApproval(List.of(new GroupChange.Actions.PromoteMemberPendingAdminApprovalAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -195,7 +195,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_modify_description_field_21() { public void not_empty_with_modify_description_field_21() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.modifyAnnouncementsOnly(new GroupChange.Actions.ModifyAnnouncementsOnlyAction()) .modify_announcements_only(new GroupChange.Actions.ModifyAnnouncementsOnlyAction())
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -204,7 +204,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_add_banned_member_field_22() { public void not_empty_with_add_banned_member_field_22() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.addBannedMembers(List.of(new GroupChange.Actions.AddBannedMemberAction())) .add_members_banned(List.of(new GroupChange.Actions.AddMemberBannedAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -213,7 +213,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_delete_banned_member_field_23() { public void not_empty_with_delete_banned_member_field_23() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.deleteBannedMembers(List.of(new GroupChange.Actions.DeleteBannedMemberAction())) .delete_members_banned(List.of(new GroupChange.Actions.DeleteMemberBannedAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -222,7 +222,7 @@ public final class GroupChangeUtil_changeIsEmpty_Test {
@Test @Test
public void not_empty_with_promote_pending_pni_aci_members_field_24() { public void not_empty_with_promote_pending_pni_aci_members_field_24() {
GroupChange.Actions actions = new GroupChange.Actions.Builder() GroupChange.Actions actions = new GroupChange.Actions.Builder()
.promotePendingPniAciMembers(List.of(new GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction())) .promote_members_pending_pni_aci_profile_key(List.of(new GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction()))
.build(); .build();
assertFalse(GroupChangeUtil.changeIsEmpty(actions)); assertFalse(GroupChangeUtil.changeIsEmpty(actions));
@@ -2,17 +2,17 @@ package org.whispersystems.signalservice.api.groupsv2;
import org.junit.Test; import org.junit.Test;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.BannedMember; import org.signal.storageservice.storage.protos.groups.MemberBanned;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.PendingMember; import org.signal.storageservice.storage.protos.groups.MemberPendingProfileKey;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
@@ -250,15 +250,15 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.addPendingMembers(List.of(new GroupChange.Actions.AddPendingMemberAction.Builder().added(new PendingMember.Builder().member(encryptedMember(member1, randomProfileKey())).build()).build(), .addMembersPendingProfileKey(List.of(new GroupChange.Actions.AddMemberPendingProfileKeyAction.Builder().added(new MemberPendingProfileKey.Builder().member(encryptedMember(member1, randomProfileKey())).build()).build(),
new GroupChange.Actions.AddPendingMemberAction.Builder().added(new PendingMember.Builder().member(encryptedMember(member2, profileKey2)).build()).build(), new GroupChange.Actions.AddMemberPendingProfileKeyAction.Builder().added(new MemberPendingProfileKey.Builder().member(encryptedMember(member2, profileKey2)).build()).build(),
new GroupChange.Actions.AddPendingMemberAction.Builder().added(new PendingMember.Builder().member(encryptedMember(member3, randomProfileKey())).build()).build())) new GroupChange.Actions.AddMemberPendingProfileKeyAction.Builder().added(new MemberPendingProfileKey.Builder().member(encryptedMember(member3, randomProfileKey())).build()).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.addPendingMembers(List.of(new GroupChange.Actions.AddPendingMemberAction.Builder().added(new PendingMember.Builder().member(encryptedMember(member2, profileKey2)).build()).build())) .addMembersPendingProfileKey(List.of(new GroupChange.Actions.AddMemberPendingProfileKeyAction.Builder().added(new MemberPendingProfileKey.Builder().member(encryptedMember(member2, profileKey2)).build()).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -280,15 +280,15 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.deletePendingMembers(List.of(new GroupChange.Actions.DeletePendingMemberAction.Builder().deletedUserId(encrypt(member1)).build(), .deleteMembersPendingProfileKey(List.of(new GroupChange.Actions.DeleteMemberPendingProfileKeyAction.Builder().deletedUserId(encrypt(member1)).build(),
new GroupChange.Actions.DeletePendingMemberAction.Builder().deletedUserId(encrypt(member2)).build(), new GroupChange.Actions.DeleteMemberPendingProfileKeyAction.Builder().deletedUserId(encrypt(member2)).build(),
new GroupChange.Actions.DeletePendingMemberAction.Builder().deletedUserId(encrypt(member3)).build())) new GroupChange.Actions.DeleteMemberPendingProfileKeyAction.Builder().deletedUserId(encrypt(member3)).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.deletePendingMembers(List.of(new GroupChange.Actions.DeletePendingMemberAction.Builder().deletedUserId(encrypt(member2)).build())) .deleteMembersPendingProfileKey(List.of(new GroupChange.Actions.DeleteMemberPendingProfileKeyAction.Builder().deletedUserId(encrypt(member2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -311,16 +311,16 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.promotePendingMembers(List.of(new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member1, randomProfileKey())).build(), .promoteMembersPendingProfileKey(List.of(new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member1, randomProfileKey())).build(),
new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member2, profileKey2)).build(), new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member2, profileKey2)).build(),
new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member3, randomProfileKey())).build())) new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member3, randomProfileKey())).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.promotePendingMembers(List.of(new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member2, profileKey2)).build())) .promoteMembersPendingProfileKey(List.of(new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member2, profileKey2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -346,7 +346,7 @@ public final class GroupChangeUtil_resolveConflict_Test {
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.promotePendingMembers(List.of(new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member1, profileKey1)).build())) .promoteMembersPendingProfileKey(List.of(new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member1, profileKey1)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -439,7 +439,7 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.modifyDisappearingMessagesTimer(new GroupChange.Actions.ModifyDisappearingMessagesTimerAction.Builder().timer(ByteString.EMPTY).build()) .modifyDisappearingMessageTimer(new GroupChange.Actions.ModifyDisappearingMessageTimerAction.Builder().timer(ByteString.EMPTY).build())
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
@@ -458,7 +458,7 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.modifyDisappearingMessagesTimer(new GroupChange.Actions.ModifyDisappearingMessagesTimerAction.Builder().timer(ByteString.EMPTY).build()) .modifyDisappearingMessageTimer(new GroupChange.Actions.ModifyDisappearingMessageTimerAction.Builder().timer(ByteString.EMPTY).build())
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
@@ -567,15 +567,15 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.addRequestingMembers(List.of(new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member1, randomProfileKey())).build(), .addMembersPendingAdminApproval(List.of(new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member1, randomProfileKey())).build(),
new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build(), new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build(),
new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member3, randomProfileKey())).build())) new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member3, randomProfileKey())).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.addRequestingMembers(List.of(new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build())) .addMembersPendingAdminApproval(List.of(new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -599,17 +599,17 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.addRequestingMembers(List.of(new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member1, profileKey1)).build(), .addMembersPendingAdminApproval(List.of(new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member1, profileKey1)).build(),
new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build(), new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build(),
new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member3, profileKey3)).build())) new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member3, profileKey3)).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.promotePendingMembers(List.of(new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member3, profileKey3)).build(), .promoteMembersPendingProfileKey(List.of(new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member3, profileKey3)).build(),
new GroupChange.Actions.PromotePendingMemberAction.Builder().presentation(presentation(member1, profileKey1)).build())) new GroupChange.Actions.PromoteMemberPendingProfileKeyAction.Builder().presentation(presentation(member1, profileKey1)).build()))
.addRequestingMembers(List.of(new GroupChange.Actions.AddRequestingMemberAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build())) .addMembersPendingAdminApproval(List.of(new GroupChange.Actions.AddMemberPendingAdminApprovalAction.Builder().added(encryptedRequestingMember(member2, profileKey2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -630,15 +630,15 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.deleteRequestingMembers(List.of(new GroupChange.Actions.DeleteRequestingMemberAction.Builder().deletedUserId(encrypt(member1)).build(), .deleteMembersPendingAdminApproval(List.of(new GroupChange.Actions.DeleteMemberPendingAdminApprovalAction.Builder().deletedUserId(encrypt(member1)).build(),
new GroupChange.Actions.DeleteRequestingMemberAction.Builder().deletedUserId(encrypt(member2)).build(), new GroupChange.Actions.DeleteMemberPendingAdminApprovalAction.Builder().deletedUserId(encrypt(member2)).build(),
new GroupChange.Actions.DeleteRequestingMemberAction.Builder().deletedUserId(encrypt(member3)).build())) new GroupChange.Actions.DeleteMemberPendingAdminApprovalAction.Builder().deletedUserId(encrypt(member3)).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.deleteRequestingMembers(List.of(new GroupChange.Actions.DeleteRequestingMemberAction.Builder().deletedUserId(encrypt(member2)).build())) .deleteMembersPendingAdminApproval(List.of(new GroupChange.Actions.DeleteMemberPendingAdminApprovalAction.Builder().deletedUserId(encrypt(member2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -660,15 +660,15 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.promoteRequestingMembers(List.of(new GroupChange.Actions.PromoteRequestingMemberAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member1)).build(), .promoteMembersPendingAdminApproval(List.of(new GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member1)).build(),
new GroupChange.Actions.PromoteRequestingMemberAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member2)).build(), new GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member2)).build(),
new GroupChange.Actions.PromoteRequestingMemberAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member3)).build())) new GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member3)).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.promoteRequestingMembers(List.of(new GroupChange.Actions.PromoteRequestingMemberAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member2)).build())) .promoteMembersPendingAdminApproval(List.of(new GroupChange.Actions.PromoteMemberPendingAdminApprovalAction.Builder().role(Member.Role.DEFAULT).userId(UuidUtil.toByteString(member2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -741,7 +741,7 @@ public final class GroupChangeUtil_resolveConflict_Test {
.newIsAnnouncementGroup(EnabledState.ENABLED) .newIsAnnouncementGroup(EnabledState.ENABLED)
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.modifyAnnouncementsOnly(new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder().announcementsOnly(true).build()) .modify_announcements_only(new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder().announcements_only(true).build())
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
@@ -758,7 +758,7 @@ public final class GroupChangeUtil_resolveConflict_Test {
.newIsAnnouncementGroup(EnabledState.ENABLED) .newIsAnnouncementGroup(EnabledState.ENABLED)
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.modifyAnnouncementsOnly(new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder().announcementsOnly(true).build()) .modify_announcements_only(new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder().announcements_only(true).build())
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
@@ -783,16 +783,16 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.addBannedMembers(List.of(new GroupChange.Actions.AddBannedMemberAction.Builder().added(new BannedMember.Builder().userId(encrypt(member1)).build()).build(), .add_members_banned(List.of(new GroupChange.Actions.AddMemberBannedAction.Builder().added(new MemberBanned.Builder().userId(encrypt(member1)).build()).build(),
new GroupChange.Actions.AddBannedMemberAction.Builder().added(new BannedMember.Builder().userId(encrypt(member2)).build()).build(), new GroupChange.Actions.AddMemberBannedAction.Builder().added(new MemberBanned.Builder().userId(encrypt(member2)).build()).build(),
new GroupChange.Actions.AddBannedMemberAction.Builder().added(new BannedMember.Builder().userId(encrypt(member3)).build()).build())) new GroupChange.Actions.AddMemberBannedAction.Builder().added(new MemberBanned.Builder().userId(encrypt(member3)).build()).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.addBannedMembers(List.of(new GroupChange.Actions.AddBannedMemberAction.Builder().added(new BannedMember.Builder().userId(encrypt(member1)).build()).build(), .add_members_banned(List.of(new GroupChange.Actions.AddMemberBannedAction.Builder().added(new MemberBanned.Builder().userId(encrypt(member1)).build()).build(),
new GroupChange.Actions.AddBannedMemberAction.Builder().added(new BannedMember.Builder().userId(encrypt(member2)).build()).build())) new GroupChange.Actions.AddMemberBannedAction.Builder().added(new MemberBanned.Builder().userId(encrypt(member2)).build()).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -814,15 +814,15 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.deleteBannedMembers(List.of(new GroupChange.Actions.DeleteBannedMemberAction.Builder().deletedUserId(encrypt(member1)).build(), .delete_members_banned(List.of(new GroupChange.Actions.DeleteMemberBannedAction.Builder().deletedUserId(encrypt(member1)).build(),
new GroupChange.Actions.DeleteBannedMemberAction.Builder().deletedUserId(encrypt(member2)).build(), new GroupChange.Actions.DeleteMemberBannedAction.Builder().deletedUserId(encrypt(member2)).build(),
new GroupChange.Actions.DeleteBannedMemberAction.Builder().deletedUserId(encrypt(member3)).build())) new GroupChange.Actions.DeleteMemberBannedAction.Builder().deletedUserId(encrypt(member3)).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.deleteBannedMembers(List.of(new GroupChange.Actions.DeleteBannedMemberAction.Builder().deletedUserId(encrypt(member2)).build())) .delete_members_banned(List.of(new GroupChange.Actions.DeleteMemberBannedAction.Builder().deletedUserId(encrypt(member2)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
@@ -843,14 +843,14 @@ public final class GroupChangeUtil_resolveConflict_Test {
.build(); .build();
GroupChange.Actions change = new GroupChange.Actions.Builder() GroupChange.Actions change = new GroupChange.Actions.Builder()
.promotePendingPniAciMembers(List.of(new GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.Builder().presentation(presentation(member1.pniBytes, member1.profileKey)).build(), .promote_members_pending_pni_aci_profile_key(List.of(new GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction.Builder().presentation(presentation(member1.pniBytes, member1.profileKey)).build(),
new GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.Builder().presentation(presentation(member2.pniBytes, member2.profileKey)).build())) new GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction.Builder().presentation(presentation(member2.pniBytes, member2.profileKey)).build()))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = new GroupChange.Actions.Builder() GroupChange.Actions expected = new GroupChange.Actions.Builder()
.promotePendingPniAciMembers(List.of(new GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.Builder().presentation(presentation(member2.pniBytes, member2.profileKey)).build())) .promote_members_pending_pni_aci_profile_key(List.of(new GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction.Builder().presentation(presentation(member2.pniBytes, member2.profileKey)).build()))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
} }
@@ -2,13 +2,13 @@ package org.whispersystems.signalservice.api.groupsv2;
import org.junit.Test; import org.junit.Test;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
@@ -42,7 +42,7 @@ class GroupsV2Operations_ban_Test {
emptyList() emptyList()
) )
assertThat(banUuidsChange.addBannedMembers) assertThat(banUuidsChange.add_members_banned)
.single() .single()
.transform { it.added?.userId } .transform { it.added?.userId }
.isEqualTo(groupOperations.encryptServiceId(ban)) .isEqualTo(groupOperations.encryptServiceId(ban))
@@ -62,7 +62,7 @@ class GroupsV2Operations_ban_Test {
alreadyBanned alreadyBanned
) )
assertThat(banUuidsChange.addBannedMembers) assertThat(banUuidsChange.add_members_banned)
.single() .single()
.transform { it.added?.userId } .transform { it.added?.userId }
.isEqualTo(groupOperations.encryptServiceId(toBan)) .isEqualTo(groupOperations.encryptServiceId(toBan))
@@ -89,12 +89,12 @@ class GroupsV2Operations_ban_Test {
) )
val oldest = alreadyBanned.minBy { it.timestamp } val oldest = alreadyBanned.minBy { it.timestamp }
assertThat(banUuidsChange.deleteBannedMembers) assertThat(banUuidsChange.delete_members_banned)
.single() .single()
.transform { it.deletedUserId } .transform { it.deletedUserId }
.isEqualTo(groupOperations.encryptServiceId(ServiceId.parseOrThrow(oldest.serviceIdBytes))) .isEqualTo(groupOperations.encryptServiceId(ServiceId.parseOrThrow(oldest.serviceIdBytes)))
assertThat(banUuidsChange.addBannedMembers) assertThat(banUuidsChange.add_members_banned)
.single() .single()
.transform { it.added?.userId } .transform { it.added?.userId }
.isEqualTo(groupOperations.encryptServiceId(toBan)) .isEqualTo(groupOperations.encryptServiceId(toBan))
@@ -125,7 +125,7 @@ class GroupsV2Operations_ban_Test {
.subList(0, 2) .subList(0, 2)
.map { groupOperations.encryptServiceId(ServiceId.parseOrThrow(it.serviceIdBytes)) } .map { groupOperations.encryptServiceId(ServiceId.parseOrThrow(it.serviceIdBytes)) }
.toTypedArray() .toTypedArray()
assertThat(banUuidsChange.deleteBannedMembers) assertThat(banUuidsChange.delete_members_banned)
.transform { members -> .transform { members ->
members.map { member -> members.map { member ->
member.deletedUserId member.deletedUserId
@@ -136,7 +136,7 @@ class GroupsV2Operations_ban_Test {
val newBans = (0..1).map { i -> val newBans = (0..1).map { i ->
groupOperations.encryptServiceId(toBan[i]) groupOperations.encryptServiceId(toBan[i])
}.toTypedArray() }.toTypedArray()
assertThat(banUuidsChange.addBannedMembers) assertThat(banUuidsChange.add_members_banned)
.transform { members -> .transform { members ->
members.map { member -> members.map { member ->
member.added?.userId member.added?.userId
@@ -16,20 +16,20 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKeyCommitment;
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialPresentation; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialPresentation;
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequest; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequest;
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequestContext; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequestContext;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.storage.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.storage.protos.groups.local.DecryptedTimer;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
import org.signal.core.models.ServiceId.PNI; import org.signal.core.models.ServiceId.PNI;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
@@ -90,7 +90,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
@Test @Test
public void can_pass_revision_through_encrypt_and_decrypt_methods() { public void can_pass_revision_through_encrypt_and_decrypt_methods() {
assertDecryption(new GroupChange.Actions.Builder() assertDecryption(new GroupChange.Actions.Builder()
.revision(1), .version(1),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(1)); .revision(1));
} }
@@ -103,7 +103,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey);
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self) assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self)
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.newMembers(List.of(new DecryptedMember.Builder() .newMembers(List.of(new DecryptedMember.Builder()
@@ -121,7 +121,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey);
assertDecryption(groupOperations.createGroupJoinDirect(groupCandidate.getExpiringProfileKeyCredential().get()) assertDecryption(groupOperations.createGroupJoinDirect(groupCandidate.getExpiringProfileKeyCredential().get())
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.newMembers(List.of(new DecryptedMember.Builder() .newMembers(List.of(new DecryptedMember.Builder()
@@ -140,7 +140,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
GroupCandidate groupCandidate = groupCandidate(newMember, profileKey); GroupCandidate groupCandidate = groupCandidate(newMember, profileKey);
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self) assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self)
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.newMembers(List.of(new DecryptedMember.Builder() .newMembers(List.of(new DecryptedMember.Builder()
@@ -167,7 +167,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
ACI oldMember = ACI.from(UUID.randomUUID()); ACI oldMember = ACI.from(UUID.randomUUID());
assertDecryption(groupOperations.createRemoveMembersChange(Collections.singleton(oldMember), false, Collections.emptyList()) assertDecryption(groupOperations.createRemoveMembersChange(Collections.singleton(oldMember), false, Collections.emptyList())
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.deleteMembers(List.of(oldMember.toByteString()))); .deleteMembers(List.of(oldMember.toByteString())));
@@ -213,7 +213,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
GroupCandidate groupCandidate = groupCandidate(self, profileKey); GroupCandidate groupCandidate = groupCandidate(self, profileKey);
assertDecryption(groupOperations.createUpdateProfileKeyCredentialChange(groupCandidate.getExpiringProfileKeyCredential().get()) assertDecryption(groupOperations.createUpdateProfileKeyCredentialChange(groupCandidate.getExpiringProfileKeyCredential().get())
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.modifiedProfileKeys(List.of(new DecryptedMember.Builder() .modifiedProfileKeys(List.of(new DecryptedMember.Builder()
@@ -231,7 +231,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
GroupCandidate groupCandidate = new GroupCandidate(newMember, Optional.empty()); GroupCandidate groupCandidate = new GroupCandidate(newMember, Optional.empty());
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self) assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self)
.revision(13), .version(13),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(13) .revision(13)
.newPendingMembers(List.of(new DecryptedPendingMember.Builder() .newPendingMembers(List.of(new DecryptedPendingMember.Builder()
@@ -260,7 +260,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
byte[] uuidCiphertext = Util.getSecretBytes(60); byte[] uuidCiphertext = Util.getSecretBytes(60);
assertDecryption(new GroupChange.Actions.Builder() assertDecryption(new GroupChange.Actions.Builder()
.deletePendingMembers(List.of(new GroupChange.Actions.DeletePendingMemberAction.Builder() .deleteMembersPendingProfileKey(List.of(new GroupChange.Actions.DeleteMemberPendingProfileKeyAction.Builder()
.deletedUserId(ByteString.of(uuidCiphertext)).build())), .deletedUserId(ByteString.of(uuidCiphertext)).build())),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.deletePendingMembers(List.of(new DecryptedPendingMemberRemoval.Builder() .deletePendingMembers(List.of(new DecryptedPendingMemberRemoval.Builder()
@@ -342,7 +342,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
GroupCandidate groupCandidate = groupCandidate(newRequestingMember, profileKey); GroupCandidate groupCandidate = groupCandidate(newRequestingMember, profileKey);
assertDecryption(groupOperations.createGroupJoinRequest(groupCandidate.getExpiringProfileKeyCredential().get()) assertDecryption(groupOperations.createGroupJoinRequest(groupCandidate.getExpiringProfileKeyCredential().get())
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.newRequestingMembers(List.of(new DecryptedRequestingMember.Builder() .newRequestingMembers(List.of(new DecryptedRequestingMember.Builder()
@@ -356,7 +356,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
ACI newRequestingMember = ACI.from(UUID.randomUUID()); ACI newRequestingMember = ACI.from(UUID.randomUUID());
assertDecryption(groupOperations.createRefuseGroupJoinRequest(Collections.singleton(newRequestingMember), true, Collections.emptyList()) assertDecryption(groupOperations.createRefuseGroupJoinRequest(Collections.singleton(newRequestingMember), true, Collections.emptyList())
.revision(10), .version(10),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(10) .revision(10)
.deleteRequestingMembers(List.of(newRequestingMember.toByteString())) .deleteRequestingMembers(List.of(newRequestingMember.toByteString()))
@@ -368,7 +368,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
UUID newRequestingMember = UUID.randomUUID(); UUID newRequestingMember = UUID.randomUUID();
assertDecryption(groupOperations.createApproveGroupJoinRequest(Collections.singleton(newRequestingMember)) assertDecryption(groupOperations.createApproveGroupJoinRequest(Collections.singleton(newRequestingMember))
.revision(15), .version(15),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(15) .revision(15)
.promoteRequestingMembers(List.of(new DecryptedApproveMember.Builder() .promoteRequestingMembers(List.of(new DecryptedApproveMember.Builder()
@@ -399,8 +399,8 @@ public final class GroupsV2Operations_decrypt_change_Test {
@Test @Test
public void can_pass_through_new_announcment_only_field21() { public void can_pass_through_new_announcment_only_field21() {
assertDecryption(new GroupChange.Actions.Builder() assertDecryption(new GroupChange.Actions.Builder()
.modifyAnnouncementsOnly(new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder() .modify_announcements_only(new GroupChange.Actions.ModifyAnnouncementsOnlyAction.Builder()
.announcementsOnly(true) .announcements_only(true)
.build()), .build()),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.newIsAnnouncementGroup(EnabledState.ENABLED)); .newIsAnnouncementGroup(EnabledState.ENABLED));
@@ -411,7 +411,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
ACI ban = ACI.from(UUID.randomUUID()); ACI ban = ACI.from(UUID.randomUUID());
assertDecryption(groupOperations.createBanServiceIdsChange(Collections.singleton(ban), false, Collections.emptyList()) assertDecryption(groupOperations.createBanServiceIdsChange(Collections.singleton(ban), false, Collections.emptyList())
.revision(13), .version(13),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(13) .revision(13)
.newBannedMembers(List.of(new DecryptedBannedMember.Builder() .newBannedMembers(List.of(new DecryptedBannedMember.Builder()
@@ -424,7 +424,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
ACI ban = ACI.from(UUID.randomUUID()); ACI ban = ACI.from(UUID.randomUUID());
assertDecryption(groupOperations.createUnbanServiceIdsChange(Collections.singleton(ban)) assertDecryption(groupOperations.createUnbanServiceIdsChange(Collections.singleton(ban))
.revision(13), .version(13),
new DecryptedGroupChange.Builder() new DecryptedGroupChange.Builder()
.revision(13) .revision(13)
.deleteBannedMembers(List.of(new DecryptedBannedMember.Builder() .deleteBannedMembers(List.of(new DecryptedBannedMember.Builder()
@@ -438,12 +438,12 @@ public final class GroupsV2Operations_decrypt_change_Test {
ProfileKey profileKey = newProfileKey(); ProfileKey profileKey = newProfileKey();
GroupChange.Actions.Builder builder = new GroupChange.Actions.Builder() GroupChange.Actions.Builder builder = new GroupChange.Actions.Builder()
.sourceServiceId(groupOperations.encryptServiceId(memberPni)) .sourceUserId(groupOperations.encryptServiceId(memberPni))
.revision(5) .version(5)
.promotePendingPniAciMembers(List.of(new GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.Builder() .promote_members_pending_pni_aci_profile_key(List.of(new GroupChange.Actions.PromoteMemberPendingPniAciProfileKeyAction.Builder()
.userId(groupOperations.encryptServiceId(memberAci)) .user_id(groupOperations.encryptServiceId(memberAci))
.pni(groupOperations.encryptServiceId(memberPni)) .pni(groupOperations.encryptServiceId(memberPni))
.profileKey(encryptProfileKey(memberAci, profileKey)) .profile_key(encryptProfileKey(memberAci, profileKey))
.build())); .build()));
assertDecryptionWithEditorSet(builder, assertDecryptionWithEditorSet(builder,
@@ -498,7 +498,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
DecryptedGroupChange.Builder expectedDecrypted) DecryptedGroupChange.Builder expectedDecrypted)
{ {
ACI editor = ACI.from(UUID.randomUUID()); ACI editor = ACI.from(UUID.randomUUID());
assertDecryptionWithEditorSet(inputChange.sourceServiceId(groupOperations.encryptServiceId(editor)), expectedDecrypted.editorServiceIdBytes(editor.toByteString())); assertDecryptionWithEditorSet(inputChange.sourceUserId(groupOperations.encryptServiceId(editor)), expectedDecrypted.editorServiceIdBytes(editor.toByteString()));
} }
void assertDecryptionWithEditorSet(GroupChange.Actions.Builder inputChange, void assertDecryptionWithEditorSet(GroupChange.Actions.Builder inputChange,
@@ -5,9 +5,9 @@ import org.junit.Test;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams; import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.GroupJoinInfo; import org.signal.storageservice.storage.protos.groups.GroupJoinInfo;
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil; import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil;
@@ -102,7 +102,7 @@ public final class GroupsV2Operations_decrypt_groupJoinInfo_Test {
@Test @Test
public void revision_passed_though_6() { public void revision_passed_though_6() {
GroupJoinInfo groupJoinInfo = new GroupJoinInfo.Builder() GroupJoinInfo groupJoinInfo = new GroupJoinInfo.Builder()
.revision(11) .version(11)
.build(); .build();
DecryptedGroupJoinInfo decryptedGroupJoinInfo = groupOperations.decryptGroupJoinInfo(groupJoinInfo); DecryptedGroupJoinInfo decryptedGroupJoinInfo = groupOperations.decryptGroupJoinInfo(groupJoinInfo);
@@ -8,18 +8,18 @@ import org.signal.libsignal.zkgroup.groups.ClientZkGroupCipher;
import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams; import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.AccessControl; import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.protos.groups.BannedMember; import org.signal.storageservice.storage.protos.groups.MemberBanned;
import org.signal.storageservice.protos.groups.Group; import org.signal.storageservice.storage.protos.groups.Group;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.PendingMember; import org.signal.storageservice.storage.protos.groups.MemberPendingProfileKey;
import org.signal.storageservice.protos.groups.RequestingMember; import org.signal.storageservice.storage.protos.groups.MemberPendingAdminApproval;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.storage.protos.groups.local.EnabledState;
import org.signal.core.models.ServiceId.ACI; import org.signal.core.models.ServiceId.ACI;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil; import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil;
@@ -75,7 +75,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
@Test @Test
public void avatar_field_passed_through_3() throws VerificationFailedException, InvalidGroupStateException { public void avatar_field_passed_through_3() throws VerificationFailedException, InvalidGroupStateException {
Group group = new Group.Builder() Group group = new Group.Builder()
.avatar("AvatarCdnKey") .avatarUrl("AvatarCdnKey")
.build(); .build();
DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group);
@@ -113,7 +113,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
@Test @Test
public void set_revision_field_6() throws VerificationFailedException, InvalidGroupStateException { public void set_revision_field_6() throws VerificationFailedException, InvalidGroupStateException {
Group group = new Group.Builder() Group group = new Group.Builder()
.revision(99) .version(99)
.build(); .build();
DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group);
@@ -132,13 +132,13 @@ public final class GroupsV2Operations_decrypt_group_Test {
.members(List.of(new Member.Builder() .members(List.of(new Member.Builder()
.role(Member.Role.ADMINISTRATOR) .role(Member.Role.ADMINISTRATOR)
.userId(groupOperations.encryptServiceId(admin1)) .userId(groupOperations.encryptServiceId(admin1))
.joinedAtRevision(4) .joinedAtVersion(4)
.profileKey(encryptProfileKey(admin1, adminProfileKey)) .profileKey(encryptProfileKey(admin1, adminProfileKey))
.build(), .build(),
new Member.Builder() new Member.Builder()
.role(Member.Role.DEFAULT) .role(Member.Role.DEFAULT)
.userId(groupOperations.encryptServiceId(member1)) .userId(groupOperations.encryptServiceId(member1))
.joinedAtRevision(7) .joinedAtVersion(7)
.profileKey(encryptProfileKey(member1, memberProfileKey)) .profileKey(encryptProfileKey(member1, memberProfileKey))
.build())) .build()))
.build(); .build();
@@ -171,7 +171,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
ACI inviter2 = ACI.from(UUID.randomUUID()); ACI inviter2 = ACI.from(UUID.randomUUID());
Group group = new Group.Builder() Group group = new Group.Builder()
.pendingMembers(List.of(new PendingMember.Builder() .membersPendingProfileKey(List.of(new MemberPendingProfileKey.Builder()
.addedByUserId(groupOperations.encryptServiceId(inviter1)) .addedByUserId(groupOperations.encryptServiceId(inviter1))
.timestamp(100) .timestamp(100)
.member(new Member.Builder() .member(new Member.Builder()
@@ -179,7 +179,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
.userId(groupOperations.encryptServiceId(admin1)) .userId(groupOperations.encryptServiceId(admin1))
.build()) .build())
.build(), .build(),
new PendingMember.Builder() new MemberPendingProfileKey.Builder()
.addedByUserId(groupOperations.encryptServiceId(inviter1)) .addedByUserId(groupOperations.encryptServiceId(inviter1))
.timestamp(200) .timestamp(200)
.member(new Member.Builder() .member(new Member.Builder()
@@ -187,7 +187,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
.userId(groupOperations.encryptServiceId(member1)) .userId(groupOperations.encryptServiceId(member1))
.build()) .build())
.build(), .build(),
new PendingMember.Builder() new MemberPendingProfileKey.Builder()
.addedByUserId(groupOperations.encryptServiceId(inviter2)) .addedByUserId(groupOperations.encryptServiceId(inviter2))
.timestamp(1500) .timestamp(1500)
.member(new Member.Builder() .member(new Member.Builder()
@@ -232,12 +232,12 @@ public final class GroupsV2Operations_decrypt_group_Test {
ProfileKey memberProfileKey = newProfileKey(); ProfileKey memberProfileKey = newProfileKey();
Group group = new Group.Builder() Group group = new Group.Builder()
.requestingMembers(List.of(new RequestingMember.Builder() .membersPendingAdminApproval(List.of(new MemberPendingAdminApproval.Builder()
.userId(groupOperations.encryptServiceId(admin1)) .userId(groupOperations.encryptServiceId(admin1))
.profileKey(encryptProfileKey(admin1, adminProfileKey)) .profileKey(encryptProfileKey(admin1, adminProfileKey))
.timestamp(5000) .timestamp(5000)
.build(), .build(),
new RequestingMember.Builder() new MemberPendingAdminApproval.Builder()
.userId(groupOperations.encryptServiceId(member1)) .userId(groupOperations.encryptServiceId(member1))
.profileKey(encryptProfileKey(member1, memberProfileKey)) .profileKey(encryptProfileKey(member1, memberProfileKey))
.timestamp(15000) .timestamp(15000)
@@ -288,7 +288,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
@Test @Test
public void decrypt_announcements_field_12() throws VerificationFailedException, InvalidGroupStateException { public void decrypt_announcements_field_12() throws VerificationFailedException, InvalidGroupStateException {
Group group = new Group.Builder() Group group = new Group.Builder()
.announcementsOnly(true) .announcements_only(true)
.build(); .build();
DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group);
@@ -301,7 +301,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
ACI member1 = ACI.from(UUID.randomUUID()); ACI member1 = ACI.from(UUID.randomUUID());
Group group = new Group.Builder() Group group = new Group.Builder()
.bannedMembers(List.of(new BannedMember.Builder().userId(groupOperations.encryptServiceId(member1)).build())) .members_banned(List.of(new MemberBanned.Builder().userId(groupOperations.encryptServiceId(member1)).build()))
.build(); .build();
DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group);
@@ -2,15 +2,15 @@ package org.whispersystems.signalservice.api.groupsv2;
import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.storageservice.protos.groups.Member; import org.signal.storageservice.storage.protos.groups.Member;
import org.signal.storageservice.protos.groups.RequestingMember; import org.signal.storageservice.storage.protos.groups.MemberPendingAdminApproval;
import org.signal.storageservice.protos.groups.local.DecryptedApproveMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedApproveMember;
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedBannedMember;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole; import org.signal.storageservice.storage.protos.groups.local.DecryptedModifyMemberRole;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMemberRemoval;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.storage.protos.groups.local.DecryptedRequestingMember;
import org.signal.core.util.UuidUtil; import org.signal.core.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
@@ -88,8 +88,8 @@ final class ProtoTestUtils {
.build(); .build();
} }
static RequestingMember encryptedRequestingMember(UUID uuid, ProfileKey profileKey) { static MemberPendingAdminApproval encryptedRequestingMember(UUID uuid, ProfileKey profileKey) {
return new RequestingMember.Builder() return new MemberPendingAdminApproval.Builder()
.presentation(presentation(uuid, profileKey)) .presentation(presentation(uuid, profileKey))
.build(); .build();
} }