Strongly type UUIDs as ACIs.

This commit is contained in:
Greyson Parrelli
2021-10-28 15:39:36 -04:00
parent 6c7d837964
commit 5bb48caafd
120 changed files with 1020 additions and 947 deletions

View File

@@ -60,6 +60,7 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.signalservice.api.push.exceptions.ConflictException;
import org.whispersystems.signalservice.api.util.UuidUtil;
@@ -92,7 +93,7 @@ final class GroupManagerV2 {
private final GroupsV2Operations groupsV2Operations;
private final GroupsV2Authorization authorization;
private final GroupsV2StateProcessor groupsV2StateProcessor;
private final UUID selfUuid;
private final ACI selfAci;
private final GroupCandidateHelper groupCandidateHelper;
GroupManagerV2(@NonNull Context context) {
@@ -102,7 +103,7 @@ final class GroupManagerV2 {
this.groupsV2Operations = ApplicationDependencies.getGroupsV2Operations();
this.authorization = ApplicationDependencies.getGroupsV2Authorization();
this.groupsV2StateProcessor = ApplicationDependencies.getGroupsV2StateProcessor();
this.selfUuid = Recipient.self().getUuid().get();
this.selfAci = Recipient.self().requireAci();
this.groupCandidateHelper = new GroupCandidateHelper(context);
}
@@ -113,7 +114,7 @@ final class GroupManagerV2 {
return groupsV2Api.getGroupJoinInfo(groupSecretParams,
Optional.fromNullable(password).transform(GroupLinkPassword::serialize),
authorization.getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams));
authorization.getAuthorizationForToday(selfAci, groupSecretParams));
}
@WorkerThread
@@ -127,7 +128,7 @@ final class GroupManagerV2 {
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
return groupsV2Api.getGroupExternalCredential(authorization.getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams));
return groupsV2Api.getGroupExternalCredential(authorization.getAuthorizationForToday(selfAci, groupSecretParams));
}
@WorkerThread
@@ -140,7 +141,7 @@ final class GroupManagerV2 {
Map<UUID, UuidCiphertext> uuidCipherTexts = new HashMap<>();
for (Recipient recipient : recipients) {
uuidCipherTexts.put(recipient.requireUuid(), clientZkGroupCipher.encryptUuid(recipient.requireUuid()));
uuidCipherTexts.put(recipient.requireAci().uuid(), clientZkGroupCipher.encryptUuid(recipient.requireAci().uuid()));
}
return uuidCipherTexts;
@@ -195,7 +196,7 @@ final class GroupManagerV2 {
return latest;
}
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), Recipient.self().requireUuid());
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), selfAci.uuid());
if (!selfInFullMemberList.isPresent()) {
return latest;
@@ -267,7 +268,7 @@ final class GroupManagerV2 {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient.getId(), true);
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder(GroupChangeReconstruct.reconstructGroupChange(DecryptedGroup.newBuilder().build(), decryptedGroup))
.setEditor(UuidUtil.toByteString(selfUuid))
.setEditor(selfAci.toByteString())
.build();
RecipientAndThread recipientAndThread = sendGroupUpdate(masterKey, new GroupMutation(null, groupChange, decryptedGroup), null);
@@ -312,7 +313,7 @@ final class GroupManagerV2 {
groupCandidates = GroupCandidate.withoutProfileKeyCredentials(groupCandidates);
}
return commitChangeWithConflictResolution(groupOperations.createModifyGroupMembershipChange(groupCandidates, selfUuid));
return commitChangeWithConflictResolution(groupOperations.createModifyGroupMembershipChange(groupCandidates, selfAci.uuid()));
}
@WorkerThread
@@ -356,7 +357,7 @@ final class GroupManagerV2 {
}
if (avatarChanged) {
String cdnKey = avatarBytes != null ? groupsV2Api.uploadAvatar(avatarBytes, groupSecretParams, authorization.getAuthorizationForToday(selfUuid, groupSecretParams))
String cdnKey = avatarBytes != null ? groupsV2Api.uploadAvatar(avatarBytes, groupSecretParams, authorization.getAuthorizationForToday(selfAci, groupSecretParams))
: "";
change.setModifyAvatar(GroupChange.Actions.ModifyAvatarAction.newBuilder()
.setAvatar(cdnKey));
@@ -387,7 +388,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
Set<UUID> uuids = Stream.of(recipientIds)
.map(r -> Recipient.resolved(r).getUuid().get())
.map(r -> Recipient.resolved(r).requireAci().uuid())
.collect(Collectors.toSet());
return commitChangeWithConflictResolution(groupOperations.createApproveGroupJoinRequest(uuids));
@@ -398,7 +399,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
Set<UUID> uuids = Stream.of(recipientIds)
.map(r -> Recipient.resolved(r).getUuid().get())
.map(r -> Recipient.resolved(r).requireAci().uuid())
.collect(Collectors.toSet());
return commitChangeWithConflictResolution(groupOperations.createRefuseGroupJoinRequest(uuids));
@@ -410,7 +411,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
Recipient recipient = Recipient.resolved(recipientId);
return commitChangeWithConflictResolution(groupOperations.createChangeMemberRole(recipient.getUuid().get(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT));
return commitChangeWithConflictResolution(groupOperations.createChangeMemberRole(recipient.requireAci().uuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT));
}
@WorkerThread
@@ -420,7 +421,7 @@ final class GroupManagerV2 {
Recipient self = Recipient.self();
GroupDatabase.GroupRecord groupRecord = groupDatabase.getGroup(groupId).get();
List<DecryptedPendingMember> pendingMembersList = groupRecord.requireV2GroupProperties().getDecryptedGroup().getPendingMembersList();
Optional<DecryptedPendingMember> selfPendingMember = DecryptedGroupUtil.findPendingByUuid(pendingMembersList, selfUuid);
Optional<DecryptedPendingMember> selfPendingMember = DecryptedGroupUtil.findPendingByUuid(pendingMembersList, selfAci.uuid());
if (selfPendingMember.isPresent()) {
try {
@@ -439,7 +440,7 @@ final class GroupManagerV2 {
{
Recipient recipient = Recipient.resolved(recipientId);
return commitChangeWithConflictResolution(groupOperations.createRemoveMembersChange(Collections.singleton(recipient.getUuid().get())));
return commitChangeWithConflictResolution(groupOperations.createRemoveMembersChange(Collections.singleton(recipient.requireAci().uuid())));
}
@WorkerThread
@@ -447,9 +448,9 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{
Recipient self = Recipient.self();
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).getUuid().get()).toList();
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireAci().uuid()).toList();
return commitChangeWithConflictResolution(groupOperations.createLeaveAndPromoteMembersToAdmin(self.getUuid().get(),
return commitChangeWithConflictResolution(groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.uuid(),
newAdminRecipients));
}
@@ -459,7 +460,7 @@ final class GroupManagerV2 {
{
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup();
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfUuid);
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.uuid());
if (!selfInGroup.isPresent()) {
Log.w(TAG, "Self not in group " + groupId);
@@ -489,7 +490,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup();
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), Recipient.self().getUuid().get());
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.uuid());
if (selfInGroup.isPresent()) {
Log.w(TAG, "Self already in group");
@@ -553,7 +554,7 @@ final class GroupManagerV2 {
private @NonNull GroupManager.GroupActionResult commitChangeWithConflictResolution(@NonNull GroupChange.Actions.Builder change)
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{
change.setSourceUuid(UuidUtil.toByteString(Recipient.self().getUuid().get()));
change.setSourceUuid(UuidUtil.toByteString(selfAci.uuid()));
for (int attempt = 0; attempt < 5; attempt++) {
try {
@@ -602,7 +603,7 @@ final class GroupManagerV2 {
GroupChange.Actions changeActions = change.build();
return GroupChangeUtil.resolveConflict(groupUpdateResult.getLatestServer(),
groupOperations.decryptChange(changeActions, selfUuid),
groupOperations.decryptChange(changeActions, selfAci.uuid()),
changeActions);
} catch (VerificationFailedException | InvalidGroupStateException ex) {
throw new GroupChangeFailedException(ex);
@@ -622,7 +623,7 @@ final class GroupManagerV2 {
try {
previousGroupState = v2GroupProperties.getDecryptedGroup();
decryptedChange = groupOperations.decryptChange(changeActions, selfUuid);
decryptedChange = groupOperations.decryptChange(changeActions, selfAci.uuid());
decryptedGroupState = DecryptedGroupUtil.apply(previousGroupState, decryptedChange);
} catch (VerificationFailedException | InvalidGroupStateException | NotAbleToApplyGroupV2ChangeException e) {
Log.w(TAG, e);
@@ -644,7 +645,7 @@ final class GroupManagerV2 {
throws GroupNotAMemberException, GroupChangeFailedException, IOException, GroupInsufficientRightsException
{
try {
return groupsV2Api.patchGroup(change, authorization.getAuthorizationForToday(selfUuid, groupSecretParams), Optional.absent());
return groupsV2Api.patchGroup(change, authorization.getAuthorizationForToday(selfAci, groupSecretParams), Optional.absent());
} catch (NotInGroupException e) {
Log.w(TAG, e);
throw new GroupNotAMemberException(e);
@@ -727,9 +728,9 @@ final class GroupManagerV2 {
disappearingMessageTimerSeconds);
try {
groupsV2Api.putNewGroup(newGroup, authorization.getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams));
groupsV2Api.putNewGroup(newGroup, authorization.getAuthorizationForToday(selfAci, groupSecretParams));
DecryptedGroup decryptedGroup = groupsV2Api.getGroup(groupSecretParams, ApplicationDependencies.getGroupsV2Authorization().getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams));
DecryptedGroup decryptedGroup = groupsV2Api.getGroup(groupSecretParams, ApplicationDependencies.getGroupsV2Authorization().getAuthorizationForToday(selfAci, groupSecretParams));
if (decryptedGroup == null) {
throw new GroupChangeFailedException();
}
@@ -922,7 +923,7 @@ final class GroupManagerV2 {
.setRevision(GroupsV2StateProcessor.PLACEHOLDER_REVISION);
Recipient self = Recipient.self();
ByteString selfUuid = UuidUtil.toByteString(self.requireUuid());
ByteString selfUuid = selfAci.toByteString();
ByteString profileKey = ByteString.copyFrom(Objects.requireNonNull(self.getProfileKey()));
if (requestToJoin) {
@@ -956,7 +957,7 @@ final class GroupManagerV2 {
GroupChange.Actions.Builder change = requestToJoin ? groupOperations.createGroupJoinRequest(profileKeyCredential)
: groupOperations.createGroupJoinDirect(profileKeyCredential);
change.setSourceUuid(UuidUtil.toByteString(Recipient.self().getUuid().get()));
change.setSourceUuid(selfAci.toByteString());
return commitJoinChangeWithConflictResolution(currentRevision, change);
}
@@ -1000,7 +1001,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, IOException, GroupLinkNotActiveException
{
try {
return groupsV2Api.patchGroup(change, authorization.getAuthorizationForToday(selfUuid, groupSecretParams), Optional.fromNullable(password).transform(GroupLinkPassword::serialize));
return groupsV2Api.patchGroup(change, authorization.getAuthorizationForToday(selfAci, groupSecretParams), Optional.fromNullable(password).transform(GroupLinkPassword::serialize));
} catch (NotInGroupException | VerificationFailedException e) {
Log.w(TAG, e);
throw new GroupChangeFailedException(e);
@@ -1044,7 +1045,7 @@ final class GroupManagerV2 {
throws IOException, VerificationFailedException, InvalidGroupStateException
{
try {
groupsV2Api.getGroup(groupSecretParams, authorization.getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams));
groupsV2Api.getGroup(groupSecretParams, authorization.getAuthorizationForToday(selfAci, groupSecretParams));
return true;
} catch (NotInGroupException ex) {
return false;
@@ -1055,7 +1056,7 @@ final class GroupManagerV2 {
void cancelJoinRequest()
throws GroupChangeFailedException, IOException
{
Set<UUID> uuids = Collections.singleton(Recipient.self().getUuid().get());
Set<UUID> uuids = Collections.singleton(selfAci.uuid());
GroupChange signedGroupChange;
try {
@@ -1158,7 +1159,7 @@ final class GroupManagerV2 {
private static @NonNull List<RecipientId> getPendingMemberRecipientIds(@NonNull List<DecryptedPendingMember> newPendingMembersList) {
return Stream.of(DecryptedGroupUtil.pendingToUuidList(newPendingMembersList))
.map(uuid-> RecipientId.from(uuid,null))
.map(uuid -> RecipientId.from(ACI.from(uuid), null))
.toList();
}

View File

@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
@@ -85,27 +86,26 @@ public final class GroupProtoUtil {
@WorkerThread
public static Recipient uuidByteStringToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) {
UUID uuid = UUIDUtil.deserialize(uuidByteString.toByteArray());
ACI aci = ACI.fromByteString(uuidByteString);
if (uuid.equals(GroupsV2Operations.UNKNOWN_UUID)) {
if (aci.isUnknown()) {
return Recipient.UNKNOWN;
}
return Recipient.externalPush(context, uuid, null, false);
return Recipient.externalPush(context, aci, null, false);
}
@WorkerThread
public static @NonNull RecipientId uuidByteStringToRecipientId(@NonNull ByteString uuidByteString) {
UUID uuid = UUIDUtil.deserialize(uuidByteString.toByteArray());
ACI aci = ACI.fromByteString(uuidByteString);
if (uuid.equals(GroupsV2Operations.UNKNOWN_UUID)) {
if (aci.isUnknown()) {
return RecipientId.UNKNOWN;
}
return RecipientId.from(uuid, null);
return RecipientId.from(aci, null);
}
public static boolean isMember(@NonNull UUID uuid, @NonNull List<DecryptedMember> membersList) {
ByteString uuidBytes = UuidUtil.toByteString(uuid);

View File

@@ -232,10 +232,10 @@ public final class GroupsV1MigrationUtil {
* True if the user meets all the requirements to be auto-migrated, otherwise false.
*/
public static boolean isAutoMigratable(@NonNull Recipient recipient) {
return recipient.hasUuid() &&
recipient.getGroupsV2Capability() == Recipient.Capability.SUPPORTED &&
return recipient.hasAci() &&
recipient.getGroupsV2Capability() == Recipient.Capability.SUPPORTED &&
recipient.getGroupsV1MigrationCapability() == Recipient.Capability.SUPPORTED &&
recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED &&
recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED &&
recipient.getProfileKey() != null;
}

View File

@@ -9,6 +9,7 @@ import org.signal.zkgroup.groups.GroupSecretParams;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString;
import org.whispersystems.signalservice.api.groupsv2.NoCredentialForRedemptionTimeException;
import org.whispersystems.signalservice.api.push.ACI;
import java.io.IOException;
import java.util.Map;
@@ -27,7 +28,7 @@ public final class GroupsV2Authorization {
this.cache = cache;
}
public GroupsV2AuthorizationString getAuthorizationForToday(@NonNull UUID self,
public GroupsV2AuthorizationString getAuthorizationForToday(@NonNull ACI self,
@NonNull GroupSecretParams groupSecretParams)
throws IOException, VerificationFailedException
{
@@ -65,7 +66,7 @@ public final class GroupsV2Authorization {
return (int) TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis());
}
private GroupsV2AuthorizationString getAuthorization(UUID self,
private GroupsV2AuthorizationString getAuthorization(ACI self,
GroupSecretParams groupSecretParams,
Map<Integer, AuthCredentialResponse> credentials,
int today)

View File

@@ -86,7 +86,7 @@ public final class GroupsV2CapabilityChecker {
}
}
if (!member.hasUuid()) {
if (!member.hasAci()) {
noUuidCount++;
}
}

View File

@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Collections;
@@ -108,7 +109,7 @@ public final class LiveGroup {
return Stream.of(requestingMembersList)
.map(requestingMember -> {
Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), UuidUtil.fromByteString(requestingMember.getUuid()), null, false);
Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), ACI.fromByteString(requestingMember.getUuid()), null, false);
return new GroupMemberEntry.RequestingMember(recipient, selfAdmin);
})
.toList();

View File

@@ -55,7 +55,7 @@ final class PendingMemberInvitesRepository {
List<DecryptedPendingMember> pendingMembersList = decryptedGroup.getPendingMembersList();
List<SinglePendingMemberInvitedByYou> byMe = new ArrayList<>(pendingMembersList.size());
List<MultiplePendingMembersInvitedByAnother> byOthers = new ArrayList<>(pendingMembersList.size());
ByteString self = ByteString.copyFrom(UUIDUtil.serialize(Recipient.self().getUuid().get()));
ByteString self = Recipient.self().requireAci().toByteString();
boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self());
Stream.of(pendingMembersList)

View File

@@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.util.Util;
import java.io.IOException;
import java.util.Collections;
@@ -96,8 +95,8 @@ final class GroupsV1MigrationRepository {
group = group.fresh();
List<Recipient> ineligible = Stream.of(group.getParticipants())
.filter(r -> !r.hasUuid() ||
r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED ||
.filter(r -> !r.hasAci() ||
r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED ||
r.getGroupsV1MigrationCapability() != Recipient.Capability.SUPPORTED ||
r.getRegistered() != RecipientDatabase.RegisteredState.REGISTERED)
.toList();

View File

@@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
import org.whispersystems.signalservice.api.push.ACI;
import java.io.IOException;
import java.util.Collection;
@@ -47,13 +48,13 @@ public final class GroupCandidateHelper {
{
final Recipient recipient = Recipient.resolved(recipientId);
UUID uuid = recipient.getUuid().orNull();
if (uuid == null) {
ACI aci = recipient.getAci().orNull();
if (aci == null) {
throw new AssertionError("Non UUID members should have need detected by now");
}
Optional<ProfileKeyCredential> profileKeyCredential = Optional.fromNullable(recipient.getProfileKeyCredential());
GroupCandidate candidate = new GroupCandidate(uuid, profileKeyCredential);
GroupCandidate candidate = new GroupCandidate(aci.uuid(), profileKeyCredential);
if (!candidate.hasProfileKeyCredential()) {
ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.getProfileKey());
@@ -61,7 +62,7 @@ public final class GroupCandidateHelper {
if (profileKey != null) {
Log.i(TAG, String.format("No profile key credential on recipient %s, fetching", recipient.getId()));
Optional<ProfileKeyCredential> profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(uuid, profileKey, Locale.getDefault());
Optional<ProfileKeyCredential> profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(aci, profileKey, Locale.getDefault());
if (profileKeyCredentialOptional.isPresent()) {
boolean updatedProfileKey = recipientDatabase.setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get());

View File

@@ -12,6 +12,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.profiles.ProfileKey;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.LinkedHashMap;
@@ -30,8 +31,8 @@ public final class ProfileKeySet {
private static final String TAG = Log.tag(ProfileKeySet.class);
private final Map<UUID, ProfileKey> profileKeys = new LinkedHashMap<>();
private final Map<UUID, ProfileKey> authoritativeProfileKeys = new LinkedHashMap<>();
private final Map<ACI, ProfileKey> profileKeys = new LinkedHashMap<>();
private final Map<ACI, ProfileKey> authoritativeProfileKeys = new LinkedHashMap<>();
/**
* Add new profile keys from a group change.
@@ -96,20 +97,20 @@ public final class ProfileKeySet {
}
if (memberUuid.equals(changeSource)) {
authoritativeProfileKeys.put(memberUuid, profileKey);
profileKeys.remove(memberUuid);
authoritativeProfileKeys.put(ACI.from(memberUuid), profileKey);
profileKeys.remove(ACI.from(memberUuid));
} else {
if (!authoritativeProfileKeys.containsKey(memberUuid)) {
profileKeys.put(memberUuid, profileKey);
if (!authoritativeProfileKeys.containsKey(ACI.from(memberUuid))) {
profileKeys.put(ACI.from(memberUuid), profileKey);
}
}
}
public Map<UUID, ProfileKey> getProfileKeys() {
public Map<ACI, ProfileKey> getProfileKeys() {
return profileKeys;
}
public Map<UUID, ProfileKey> getAuthoritativeProfileKeys() {
public Map<ACI, ProfileKey> getAuthoritativeProfileKeys() {
return authoritativeProfileKeys;
}
}

View File

@@ -49,6 +49,7 @@ import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.exceptions.GroupNotFoundException;
import org.whispersystems.signalservice.internal.push.exceptions.NotInGroupException;
@@ -206,7 +207,7 @@ public final class GroupsV2StateProcessor {
}
if (inputGroupState == null) {
if (localState != null && DecryptedGroupUtil.isPendingOrRequesting(localState, Recipient.self().getUuid().get())) {
if (localState != null && DecryptedGroupUtil.isPendingOrRequesting(localState, Recipient.self().requireAci().uuid())) {
Log.w(TAG, "Unable to query server for group " + groupId + " server says we're not in group, but we think we are a pending or requesting member");
} else {
Log.w(TAG, "Unable to query server for group " + groupId + " server says we're not in group, inserting leave message");
@@ -250,7 +251,7 @@ public final class GroupsV2StateProcessor {
throws IOException, GroupNotAMemberException, GroupDoesNotExistException
{
try {
return groupsV2Api.getGroup(groupSecretParams, groupsV2Authorization.getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams));
return groupsV2Api.getGroup(groupSecretParams, groupsV2Authorization.getAuthorizationForToday(Recipient.self().requireAci(), groupSecretParams));
} catch (GroupNotFoundException e) {
throw new GroupDoesNotExistException(e);
} catch (NotInGroupException e) {
@@ -265,7 +266,7 @@ public final class GroupsV2StateProcessor {
throws IOException, GroupNotAMemberException, GroupDoesNotExistException
{
try {
return groupsV2Api.getGroupHistory(groupSecretParams, revision, groupsV2Authorization.getAuthorizationForToday(Recipient.self().requireUuid(), groupSecretParams))
return groupsV2Api.getGroupHistory(groupSecretParams, revision, groupsV2Authorization.getAuthorizationForToday(Recipient.self().requireAci(), groupSecretParams))
.get(0)
.getGroup()
.orNull();
@@ -285,7 +286,7 @@ public final class GroupsV2StateProcessor {
}
Recipient groupRecipient = Recipient.externalGroupExact(context, groupId);
UUID selfUuid = Recipient.self().getUuid().get();
UUID selfUuid = Recipient.self().requireAci().uuid();
DecryptedGroup decryptedGroup = groupDatabase.requireGroup(groupId)
.requireV2GroupProperties()
.getDecryptedGroup();
@@ -359,7 +360,7 @@ public final class GroupsV2StateProcessor {
@NonNull DecryptedGroup newLocalState)
{
if (inputGroupState.getLocalState() != null) {
boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), Recipient.self().getUuid().get()).isPresent();
boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), Recipient.self().requireAci().uuid()).isPresent();
if (wasAMemberAlready) {
Log.i(TAG, "Skipping profile sharing detection as was already a full member before update");
@@ -367,7 +368,7 @@ public final class GroupsV2StateProcessor {
}
}
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), Recipient.self().getUuid().get());
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), Recipient.self().requireAci().uuid());
if (selfAsMemberOptional.isPresent()) {
DecryptedMember selfAsMember = selfAsMemberOptional.get();
@@ -378,7 +379,7 @@ public final class GroupsV2StateProcessor {
.filter(c -> c != null && c.getRevision() == revisionJoinedAt)
.findFirst()
.map(c -> Optional.fromNullable(UuidUtil.fromByteStringOrNull(c.getEditor()))
.transform(a -> Recipient.externalPush(context, UuidUtil.fromByteStringOrNull(c.getEditor()), null, false)))
.transform(a -> Recipient.externalPush(context, ACI.fromByteStringOrNull(c.getEditor()), null, false)))
.orElse(Optional.absent());
if (addedByOptional.isPresent()) {
@@ -446,33 +447,33 @@ public final class GroupsV2StateProcessor {
private @NonNull GlobalGroupState queryServer(@Nullable DecryptedGroup localState, boolean latestOnly)
throws IOException, GroupNotAMemberException
{
UUID selfUuid = Recipient.self().getUuid().get();
ACI selfAci = Recipient.self().requireAci();
DecryptedGroup latestServerGroup;
List<ServerGroupLogEntry> history;
try {
latestServerGroup = groupsV2Api.getGroup(groupSecretParams, groupsV2Authorization.getAuthorizationForToday(selfUuid, groupSecretParams));
latestServerGroup = groupsV2Api.getGroup(groupSecretParams, groupsV2Authorization.getAuthorizationForToday(selfAci, groupSecretParams));
} catch (NotInGroupException | GroupNotFoundException e) {
throw new GroupNotAMemberException(e);
} catch (VerificationFailedException | InvalidGroupStateException e) {
throw new IOException(e);
}
if (latestOnly || !GroupProtoUtil.isMember(selfUuid, latestServerGroup.getMembersList())) {
if (latestOnly || !GroupProtoUtil.isMember(selfAci.uuid(), latestServerGroup.getMembersList())) {
history = Collections.singletonList(new ServerGroupLogEntry(latestServerGroup, null));
} else {
int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, selfUuid);
int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, selfAci.uuid());
int logsNeededFrom = localState != null ? Math.max(localState.getRevision(), revisionWeWereAdded) : revisionWeWereAdded;
history = getFullMemberHistory(selfUuid, logsNeededFrom);
history = getFullMemberHistory(selfAci, logsNeededFrom);
}
return new GlobalGroupState(localState, history);
}
private List<ServerGroupLogEntry> getFullMemberHistory(@NonNull UUID selfUuid, int logsNeededFromRevision) throws IOException {
private List<ServerGroupLogEntry> getFullMemberHistory(@NonNull ACI selfAci, int logsNeededFromRevision) throws IOException {
try {
Collection<DecryptedGroupHistoryEntry> groupStatesFromRevision = groupsV2Api.getGroupHistory(groupSecretParams, logsNeededFromRevision, groupsV2Authorization.getAuthorizationForToday(selfUuid, groupSecretParams));
Collection<DecryptedGroupHistoryEntry> groupStatesFromRevision = groupsV2Api.getGroupHistory(groupSecretParams, logsNeededFromRevision, groupsV2Authorization.getAuthorizationForToday(selfAci, groupSecretParams));
ArrayList<ServerGroupLogEntry> history = new ArrayList<>(groupStatesFromRevision.size());
boolean ignoreServerChanges = SignalStore.internalValues().gv2IgnoreServerChanges();
@@ -496,9 +497,9 @@ public final class GroupsV2StateProcessor {
}
private void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) {
Optional<UUID> editor = getEditor(decryptedGroupV2Context);
Optional<ACI> editor = getEditor(decryptedGroupV2Context).transform(ACI::from);
boolean outgoing = !editor.isPresent() || Recipient.self().requireUuid().equals(editor.get());
boolean outgoing = !editor.isPresent() || Recipient.self().requireAci().equals(editor.get());
if (outgoing) {
try {
@@ -536,7 +537,7 @@ public final class GroupsV2StateProcessor {
if (changeEditor.isPresent()) {
return changeEditor;
} else {
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), Recipient.self().requireUuid());
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), Recipient.self().requireAci().uuid());
if (pendingByUuid.isPresent()) {
return Optional.fromNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid()));
}