Adopt libsignal 0.30.0 and ServiceIds for group members.

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

View File

@@ -336,7 +336,7 @@ public final class GroupManager {
throws GroupChangeBusyException, IOException, GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException
{
try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) {
editor.unban(Collections.singleton(Recipient.resolved(recipientId).requireServiceId().getRawUuid()));
editor.unban(Collections.singleton(Recipient.resolved(recipientId).requireServiceId()));
}
}

View File

@@ -176,7 +176,7 @@ final class GroupManagerV2 {
Map<UUID, UuidCiphertext> uuidCipherTexts = new HashMap<>();
for (Recipient recipient : recipients) {
uuidCipherTexts.put(recipient.requireServiceId().getRawUuid(), clientZkGroupCipher.encryptUuid(recipient.requireServiceId().getRawUuid()));
uuidCipherTexts.put(recipient.requireServiceId().getRawUuid(), clientZkGroupCipher.encrypt(recipient.requireServiceId().getLibSignalServiceId()));
}
return uuidCipherTexts;
@@ -343,7 +343,7 @@ final class GroupManagerV2 {
}
@WorkerThread
@NonNull GroupManager.GroupActionResult addMembers(@NonNull Collection<RecipientId> newMembers, @NonNull Set<UUID> bannedMembers)
@NonNull GroupManager.GroupActionResult addMembers(@NonNull Collection<RecipientId> newMembers, @NonNull Set<ServiceId> bannedMembers)
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException, MembershipNotSuitableForV2Exception
{
if (!GroupsV2CapabilityChecker.allHaveServiceId(newMembers)) {
@@ -356,7 +356,7 @@ final class GroupManagerV2 {
groupCandidates = GroupCandidate.withoutExpiringProfileKeyCredentials(groupCandidates);
}
return commitChangeWithConflictResolution(selfAci, groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci.getRawUuid()));
return commitChangeWithConflictResolution(selfAci, groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci));
}
@WorkerThread
@@ -454,7 +454,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
Recipient recipient = Recipient.resolved(recipientId);
return commitChangeWithConflictResolution(selfAci, groupOperations.createChangeMemberRole(recipient.requireServiceId().getRawUuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT));
return commitChangeWithConflictResolution(selfAci, groupOperations.createChangeMemberRole(recipient.requireAci(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT));
}
@WorkerThread
@@ -464,8 +464,8 @@ final class GroupManagerV2 {
GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup();
Optional<DecryptedMember> selfMember = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), selfAci.getRawUuid());
Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfAci.getRawUuid());
Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), selfPni.getRawUuid());
Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfAci);
Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfPni);
Optional<DecryptedPendingMember> selfPendingMember = Optional.empty();
ServiceId serviceId = selfAci;
@@ -555,8 +555,8 @@ final class GroupManagerV2 {
return null;
}
Optional<DecryptedPendingMember> aciInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfAci.getRawUuid());
Optional<DecryptedPendingMember> pniInPending = DecryptedGroupUtil.findPendingByUuid(group.getPendingMembersList(), selfPni.getRawUuid());
Optional<DecryptedPendingMember> aciInPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfAci);
Optional<DecryptedPendingMember> pniInPending = DecryptedGroupUtil.findPendingByServiceId(group.getPendingMembersList(), selfPni);
GroupCandidate groupCandidate = groupCandidateHelper.recipientIdToCandidate(Recipient.self().getId());
@@ -584,10 +584,10 @@ final class GroupManagerV2 {
return commitChangeWithConflictResolution(selfAci, groupOperations.createBanUuidsChange(Collections.singleton(uuid), rejectJoinRequest, v2GroupProperties.getDecryptedGroup().getBannedMembersList()));
}
public GroupManager.GroupActionResult unban(Set<UUID> uuids)
public GroupManager.GroupActionResult unban(Set<ServiceId> serviceIds)
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{
return commitChangeWithConflictResolution(selfAci, groupOperations.createUnbanUuidsChange(uuids));
return commitChangeWithConflictResolution(selfAci, groupOperations.createUnbanServiceIdsChange(serviceIds));
}
@WorkerThread
@@ -704,7 +704,7 @@ final class GroupManagerV2 {
GroupChange.Actions changeActions = change.build();
return GroupChangeUtil.resolveConflict(groupUpdateResult.getLatestServer(),
groupOperations.decryptChange(changeActions, authServiceId.getRawUuid()),
groupOperations.decryptChange(changeActions, authServiceId),
changeActions);
} catch (VerificationFailedException | InvalidGroupStateException ex) {
throw new GroupChangeFailedException(ex);
@@ -1331,9 +1331,8 @@ final class GroupManagerV2 {
}
private static @NonNull List<RecipientId> getPendingMemberRecipientIds(@NonNull List<DecryptedPendingMember> newPendingMembersList) {
// TODO [greyson][ServiceId] Pending members can be ACI's or PNI's
return Stream.of(DecryptedGroupUtil.pendingToUuidList(newPendingMembersList))
.map(uuid -> RecipientId.from(ACI.from(uuid)))
return Stream.of(DecryptedGroupUtil.pendingToServiceIdList(newPendingMembersList))
.map(serviceId -> RecipientId.from(serviceId))
.toList();
}

View File

@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
@@ -30,17 +31,17 @@ public final class GroupProtoUtil {
private GroupProtoUtil() {
}
public static int findRevisionWeWereAdded(@NonNull PartialDecryptedGroup partialDecryptedGroup, @NonNull UUID uuid)
public static int findRevisionWeWereAdded(@NonNull PartialDecryptedGroup partialDecryptedGroup, @NonNull ACI self)
throws GroupNotAMemberException
{
ByteString bytes = UuidUtil.toByteString(uuid);
ByteString bytes = self.toByteString();
for (DecryptedMember decryptedMember : partialDecryptedGroup.getMembersList()) {
if (decryptedMember.getUuid().equals(bytes)) {
return decryptedMember.getJoinedAtRevision();
}
}
for (DecryptedPendingMember decryptedMember : partialDecryptedGroup.getPendingMembersList()) {
if (decryptedMember.getUuid().equals(bytes)) {
if (decryptedMember.getServiceIdBinary().equals(bytes)) {
// Assume latest, we don't have any information about when pending members were invited
return partialDecryptedGroup.getRevision();
}
@@ -80,12 +81,12 @@ public final class GroupProtoUtil {
@WorkerThread
public static Recipient pendingMemberToRecipient(@NonNull Context context, @NonNull DecryptedPendingMember pendingMember) {
return pendingMemberServiceIdToRecipient(context, pendingMember.getUuid());
return pendingMemberServiceIdToRecipient(context, pendingMember.getServiceIdBinary());
}
@WorkerThread
public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) {
ServiceId serviceId = ServiceId.parseOrThrow(uuidByteString);
public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString serviceIdBinary) {
ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary);
if (serviceId.isUnknown()) {
return Recipient.UNKNOWN;
@@ -95,8 +96,8 @@ public final class GroupProtoUtil {
}
@WorkerThread
public static @NonNull RecipientId uuidByteStringToRecipientId(@NonNull ByteString uuidByteString) {
ServiceId serviceId = ServiceId.parseOrThrow(uuidByteString);
public static @NonNull RecipientId serviceIdBinaryToRecipientId(@NonNull ByteString serviceIdBinary) {
ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary);
if (serviceId.isUnknown()) {
return RecipientId.UNKNOWN;

View File

@@ -126,13 +126,13 @@ public class GroupsV2Authorization {
}
CallLinkAuthCredential credential = authCredentialResponse.receive(
Recipient.self().requireServiceId().getRawUuid(),
Recipient.self().requireAci().getLibSignalAci(),
Instant.ofEpochSecond(todaySeconds),
genericServerPublicParams
);
return credential.present(
Recipient.self().requireServiceId().getRawUuid(),
Recipient.self().requireAci().getLibSignalAci(),
Instant.ofEpochSecond(todaySeconds),
genericServerPublicParams,
callLinkSecretParams

View File

@@ -144,7 +144,7 @@ public final class LiveGroup {
return Transformations.map(groupRecord, g -> g.isAdmin(Recipient.self()));
}
public LiveData<Set<UUID>> getBannedMembers() {
public LiveData<Set<ServiceId>> getBannedMembers() {
return Transformations.map(groupRecord, g -> g.isV2Group() ? g.requireV2GroupProperties().getBannedMembers() : Collections.emptySet());
}

View File

@@ -51,7 +51,7 @@ public class GroupCandidateHelper {
}
Optional<ExpiringProfileKeyCredential> expiringProfileKeyCredential = Optional.ofNullable(recipient.getExpiringProfileKeyCredential());
GroupCandidate candidate = new GroupCandidate(serviceId.getRawUuid(), expiringProfileKeyCredential);
GroupCandidate candidate = new GroupCandidate(serviceId, expiringProfileKeyCredential);
if (!candidate.hasValidProfileKeyCredential()) {
recipientTable.clearProfileKeyCredential(recipient.getId());

View File

@@ -380,9 +380,7 @@ public class GroupsV2StateProcessor {
boolean addedAsPendingMember = signedGroupChange.getNewPendingMembersList()
.stream()
.map(DecryptedPendingMember::getUuid)
.map(UuidUtil::fromByteStringOrNull)
.filter(Objects::nonNull)
.map(DecryptedPendingMember::getServiceIdBinary)
.anyMatch(serviceIds::matches);
boolean addedAsRequestingMember = signedGroupChange.getNewRequestingMembersList()
@@ -398,9 +396,7 @@ public class GroupsV2StateProcessor {
private boolean notHavingInviteRevoked(@NonNull DecryptedGroupChange signedGroupChange) {
boolean havingInviteRevoked = signedGroupChange.getDeletePendingMembersList()
.stream()
.map(DecryptedPendingMemberRemoval::getUuid)
.map(UuidUtil::fromByteStringOrNull)
.filter(Objects::nonNull)
.map(DecryptedPendingMemberRemoval::getServiceIdBinary)
.anyMatch(serviceIds::matches);
return !havingInviteRevoked;
@@ -434,7 +430,7 @@ public class GroupsV2StateProcessor {
info("Latest revision or not a member, use latest only");
inputGroupState = new GlobalGroupState(localState, Collections.singletonList(new ServerGroupLogEntry(latestServerGroup.getFullyDecryptedGroup(), null)));
} else {
int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, serviceIds.getAci().getRawUuid());
int revisionWeWereAdded = GroupProtoUtil.findRevisionWeWereAdded(latestServerGroup, serviceIds.getAci());
int logsNeededFrom = localState != null ? Math.max(localState.getRevision(), revisionWeWereAdded) : revisionWeWereAdded;
boolean includeFirstState = forceIncludeFirst ||
@@ -694,7 +690,7 @@ public class GroupsV2StateProcessor {
}
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), aci.getRawUuid());
Optional<DecryptedPendingMember> selfAsPendingOptional = DecryptedGroupUtil.findPendingByUuid(newLocalState.getPendingMembersList(), aci.getRawUuid());
Optional<DecryptedPendingMember> selfAsPendingOptional = DecryptedGroupUtil.findPendingByServiceId(newLocalState.getPendingMembersList(), aci);
if (selfAsMemberOptional.isPresent()) {
DecryptedMember selfAsMember = selfAsMemberOptional.get();
@@ -835,7 +831,7 @@ public class GroupsV2StateProcessor {
if (changeEditor.isPresent()) {
return changeEditor;
} else {
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci.getRawUuid());
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByServiceId(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci);
if (pendingByUuid.isPresent()) {
return Optional.ofNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid()));
}