Convert all group code to be based on ServiceIds.

This commit is contained in:
Greyson Parrelli 2023-08-03 15:28:17 -04:00 committed by Alex Hart
parent d247e2c111
commit c5d9346370
50 changed files with 836 additions and 792 deletions

View file

@ -294,12 +294,12 @@ class GroupTableTest {
private fun insertPushGroup( private fun insertPushGroup(
members: List<DecryptedMember> = listOf( members: List<DecryptedMember> = listOf(
DecryptedMember.newBuilder() DecryptedMember.newBuilder()
.setUuid(harness.self.requireServiceId().toByteString()) .setAciBytes(harness.self.requireAci().toByteString())
.setJoinedAtRevision(0) .setJoinedAtRevision(0)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build(), .build(),
DecryptedMember.newBuilder() DecryptedMember.newBuilder()
.setUuid(Recipient.resolved(harness.others[0]).requireServiceId().toByteString()) .setAciBytes(Recipient.resolved(harness.others[0]).requireAci().toByteString())
.setJoinedAtRevision(0) .setJoinedAtRevision(0)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build() .build()
@ -318,14 +318,14 @@ class GroupTableTest {
val groupMasterKey = GroupMasterKey(Random.nextBytes(GroupMasterKey.SIZE)) val groupMasterKey = GroupMasterKey(Random.nextBytes(GroupMasterKey.SIZE))
val selfMember: DecryptedMember = DecryptedMember.newBuilder() val selfMember: DecryptedMember = DecryptedMember.newBuilder()
.setUuid(harness.self.requireServiceId().toByteString()) .setAciBytes(harness.self.requireAci().toByteString())
.setJoinedAtRevision(0) .setJoinedAtRevision(0)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build() .build()
val otherMembers: List<DecryptedMember> = others.map { id -> val otherMembers: List<DecryptedMember> = others.map { id ->
DecryptedMember.newBuilder() DecryptedMember.newBuilder()
.setUuid(Recipient.resolved(id).requireServiceId().toByteString()) .setAciBytes(Recipient.resolved(id).requireAci().toByteString())
.setJoinedAtRevision(0) .setJoinedAtRevision(0)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build() .build()

View file

@ -92,12 +92,12 @@ class MessageContentProcessor__handleStoryMessageTest : MessageContentProcessorT
.addAllMembers( .addAllMembers(
listOf( listOf(
DecryptedMember.newBuilder() DecryptedMember.newBuilder()
.setUuid(harness.self.requireServiceId().toByteString()) .setAciBytes(harness.self.requireAci().toByteString())
.setJoinedAtRevision(0) .setJoinedAtRevision(0)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build(), .build(),
DecryptedMember.newBuilder() DecryptedMember.newBuilder()
.setUuid(sender.requireServiceId().toByteString()) .setAciBytes(sender.requireAci().toByteString())
.setJoinedAtRevision(0) .setJoinedAtRevision(0)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build() .build()

View file

@ -44,7 +44,6 @@ class ContactRecordProcessorTest {
} }
val remote2 = buildRecord(STORAGE_ID_C) { val remote2 = buildRecord(STORAGE_ID_C) {
setAci(PNI_A.toString())
setPni(PNI_A.toString()) setPni(PNI_A.toString())
setE164(E164_A) setE164(E164_A)
} }

View file

@ -8,16 +8,16 @@ 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
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId.ACI
import kotlin.random.Random import kotlin.random.Random
/** /**
* Helper methods for creating groups for message processing tests et al. * Helper methods for creating groups for message processing tests et al.
*/ */
object GroupTestingUtils { object GroupTestingUtils {
fun member(serviceId: ServiceId, revision: Int = 0, role: Member.Role = Member.Role.ADMINISTRATOR): DecryptedMember { fun member(aci: ACI, revision: Int = 0, role: Member.Role = Member.Role.ADMINISTRATOR): DecryptedMember {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(serviceId.toByteString()) .setAciBytes(aci.toByteString())
.setJoinedAtRevision(revision) .setJoinedAtRevision(revision)
.setRole(role) .setRole(role)
.build() .build()
@ -43,7 +43,7 @@ object GroupTestingUtils {
} }
fun Recipient.asMember(): DecryptedMember { fun Recipient.asMember(): DecryptedMember {
return member(serviceId = requireServiceId()) return member(aci = requireAci())
} }
data class TestGroupInfo(val groupId: GroupId.V2, val masterKey: GroupMasterKey, val recipientId: RecipientId) data class TestGroupInfo(val groupId: GroupId.V2, val masterKey: GroupMasterKey, val recipientId: RecipientId)

View file

@ -153,7 +153,7 @@ class ConversationSettingsRepository(
if (groupRecord.isV2Group) { if (groupRecord.isV2Group) {
val decryptedGroup: DecryptedGroup = groupRecord.requireV2GroupProperties().decryptedGroup val decryptedGroup: DecryptedGroup = groupRecord.requireV2GroupProperties().decryptedGroup
val pendingMembers: List<RecipientId> = decryptedGroup.pendingMembersList val pendingMembers: List<RecipientId> = decryptedGroup.pendingMembersList
.map(DecryptedPendingMember::getServiceIdBinary) .map(DecryptedPendingMember::getServiceIdBytes)
.map(GroupProtoUtil::serviceIdBinaryToRecipientId) .map(GroupProtoUtil::serviceIdBinaryToRecipientId)
val members = mutableListOf<RecipientId>() val members = mutableListOf<RecipientId>()

View file

@ -52,11 +52,15 @@ import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
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
import org.whispersystems.signalservice.api.groupsv2.findMemberByAci
import org.whispersystems.signalservice.api.groupsv2.findPendingByServiceId
import org.whispersystems.signalservice.api.groupsv2.findRequestingByAci
import org.whispersystems.signalservice.api.groupsv2.toAciList
import org.whispersystems.signalservice.api.groupsv2.toAciListWithUnknowns
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
import org.whispersystems.signalservice.api.push.DistributionId import org.whispersystems.signalservice.api.push.DistributionId
import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.ACI import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.util.UuidUtil
import java.io.Closeable import java.io.Closeable
import java.security.SecureRandom import java.security.SecureRandom
import java.util.Optional import java.util.Optional
@ -860,7 +864,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
writableDatabase.withinTransaction { db -> writableDatabase.withinTransaction { db ->
val record = getGroup(groupIdV1).get() val record = getGroup(groupIdV1).get()
val newMembers: MutableList<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(decryptedGroup.membersList).toRecipientIds() val newMembers: MutableList<RecipientId> = decryptedGroup.membersList.toAciList().toRecipientIds()
val pendingMembers: List<RecipientId> = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.pendingMembersList).toRecipientIds() val pendingMembers: List<RecipientId> = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.pendingMembersList).toRecipientIds()
newMembers.addAll(pendingMembers) newMembers.addAll(pendingMembers)
@ -914,11 +918,11 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
val change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().decryptedGroup, decryptedGroup) val change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().decryptedGroup, decryptedGroup)
val addedMembers: Set<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(change.newMembersList).toRecipientIds().toSet() val addedMembers: Set<RecipientId> = change.newMembersList.toAciList().toRecipientIds().toSet()
val removedMembers: Set<RecipientId> = DecryptedGroupUtil.removedMembersServiceIdList(change).toRecipientIds().toSet() val removedMembers: Set<RecipientId> = DecryptedGroupUtil.removedMembersServiceIdList(change).toRecipientIds().toSet()
val addedInvites: Set<RecipientId> = DecryptedGroupUtil.pendingToServiceIdList(change.newPendingMembersList).toRecipientIds().toSet() val addedInvites: Set<RecipientId> = DecryptedGroupUtil.pendingToServiceIdList(change.newPendingMembersList).toRecipientIds().toSet()
val removedInvites: Set<RecipientId> = DecryptedGroupUtil.removedPendingMembersServiceIdList(change).toRecipientIds().toSet() val removedInvites: Set<RecipientId> = DecryptedGroupUtil.removedPendingMembersServiceIdList(change).toRecipientIds().toSet()
val acceptedInvites: Set<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(change.promotePendingMembersList).toRecipientIds().toSet() val acceptedInvites: Set<RecipientId> = change.promotePendingMembersList.toAciList().toRecipientIds().toSet()
unmigratedV1Members -= addedMembers unmigratedV1Members -= addedMembers
unmigratedV1Members -= removedMembers unmigratedV1Members -= removedMembers
@ -1212,10 +1216,10 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
} }
fun isAdmin(recipient: Recipient): Boolean { fun isAdmin(recipient: Recipient): Boolean {
val serviceId = recipient.serviceId val aci = recipient.aci
return if (serviceId.isPresent) { return if (aci.isPresent) {
DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, serviceId.get().rawUuid) decryptedGroup.membersList.findMemberByAci(aci.get())
.map { it.role == Member.Role.ADMINISTRATOR } .map { it.role == Member.Role.ADMINISTRATOR }
.orElse(false) .orElse(false)
} else { } else {
@ -1227,12 +1231,16 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
return members.stream().filter { recipient: Recipient -> isAdmin(recipient) }.collect(Collectors.toList()) return members.stream().filter { recipient: Recipient -> isAdmin(recipient) }.collect(Collectors.toList())
} }
fun memberLevel(serviceId: Optional<ServiceId>): MemberLevel { fun memberLevel(serviceIdOptional: Optional<ServiceId>): MemberLevel {
if (!serviceId.isPresent) { if (serviceIdOptional.isEmpty) {
return MemberLevel.NOT_A_MEMBER return MemberLevel.NOT_A_MEMBER
} }
var memberLevel: Optional<MemberLevel> = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, serviceId.get().rawUuid) val serviceId: ServiceId = serviceIdOptional.get()
var memberLevel: Optional<MemberLevel> = Optional.empty()
if (serviceId is ACI) {
memberLevel = decryptedGroup.membersList.findMemberByAci(serviceId)
.map { member -> .map { member ->
if (member.role == Member.Role.ADMINISTRATOR) { if (member.role == Member.Role.ADMINISTRATOR) {
MemberLevel.ADMINISTRATOR MemberLevel.ADMINISTRATOR
@ -1240,14 +1248,15 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
MemberLevel.FULL_MEMBER MemberLevel.FULL_MEMBER
} }
} }
if (memberLevel.isAbsent()) {
memberLevel = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, serviceId.get())
.map { MemberLevel.PENDING_MEMBER }
} }
if (memberLevel.isAbsent()) { if (memberLevel.isAbsent()) {
memberLevel = DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.requestingMembersList, serviceId.get().rawUuid) memberLevel = decryptedGroup.pendingMembersList.findPendingByServiceId(serviceId)
.map { MemberLevel.PENDING_MEMBER }
}
if (memberLevel.isAbsent() && serviceId is ACI) {
memberLevel = decryptedGroup.requestingMembersList.findRequestingByAci(serviceId)
.map { _ -> MemberLevel.REQUESTING_MEMBER } .map { _ -> MemberLevel.REQUESTING_MEMBER }
} }
@ -1265,17 +1274,16 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
fun getMemberRecipientIds(memberSet: MemberSet): List<RecipientId> { fun getMemberRecipientIds(memberSet: MemberSet): List<RecipientId> {
val includeSelf = memberSet.includeSelf val includeSelf = memberSet.includeSelf
val selfAci = SignalStore.account().requireAci() val selfAci = SignalStore.account().requireAci()
val selfAciUuid = selfAci.rawUuid
val recipients: MutableList<RecipientId> = ArrayList(decryptedGroup.membersCount + decryptedGroup.pendingMembersCount) val recipients: MutableList<RecipientId> = ArrayList(decryptedGroup.membersCount + decryptedGroup.pendingMembersCount)
var unknownMembers = 0 var unknownMembers = 0
var unknownPending = 0 var unknownPending = 0
for (uuid in DecryptedGroupUtil.toUuidList(decryptedGroup.membersList)) { for (aci in decryptedGroup.membersList.toAciListWithUnknowns()) {
if (UuidUtil.UNKNOWN_UUID == uuid) { if (aci.isUnknown) {
unknownMembers++ unknownMembers++
} else if (includeSelf || selfAciUuid != uuid) { } else if (includeSelf || selfAci != aci) {
recipients += RecipientId.from(ACI.from(uuid)) recipients += RecipientId.from(aci)
} }
} }
@ -1300,9 +1308,8 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
return decryptedGroup return decryptedGroup
.membersList .membersList
.asSequence() .asSequence()
.map { UuidUtil.fromByteStringOrNull(it.uuid) } .map { ACI.parseOrNull(it.aciBytes) }
.filterNotNull() .filterNotNull()
.map { ACI.from(it) }
.sortedBy { it.toString() } .sortedBy { it.toString() }
.toList() .toList()
} }
@ -1377,7 +1384,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
private fun gv2GroupActive(decryptedGroup: DecryptedGroup): Boolean { private fun gv2GroupActive(decryptedGroup: DecryptedGroup): Boolean {
val aci = SignalStore.account().requireAci() val aci = SignalStore.account().requireAci()
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.membersList, aci.rawUuid).isPresent || return decryptedGroup.membersList.findMemberByAci(aci).isPresent ||
DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, aci).isPresent DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.pendingMembersList, aci).isPresent
} }
@ -1421,7 +1428,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
} }
private fun getV2GroupMembers(decryptedGroup: DecryptedGroup, shouldRetry: Boolean): List<RecipientId> { private fun getV2GroupMembers(decryptedGroup: DecryptedGroup, shouldRetry: Boolean): List<RecipientId> {
val ids: List<RecipientId> = DecryptedGroupUtil.membersToServiceIdList(decryptedGroup.membersList).toRecipientIds() val ids: List<RecipientId> = decryptedGroup.membersList.toAciList().toRecipientIds()
return if (RemappedRecords.getInstance().areAnyRemapped(ids)) { return if (RemappedRecords.getInstance().areAnyRemapped(ids)) {
if (shouldRetry) { if (shouldRetry) {

View file

@ -3668,7 +3668,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
val latestMessage = reader.getNext() val latestMessage = reader.getNext()
if (latestMessage != null && latestMessage.isGroupV2) { if (latestMessage != null && latestMessage.isGroupV2) {
val changeEditor = message.changeEditor val changeEditor: Optional<ServiceId> = message.changeEditor
if (changeEditor.isPresent && latestMessage.isGroupV2JoinRequest(changeEditor.get())) { if (changeEditor.isPresent && latestMessage.isGroupV2JoinRequest(changeEditor.get())) {
val secondLatestMessage = reader.getNext() val secondLatestMessage = reader.getNext()
@ -3678,11 +3678,11 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
if (secondLatestMessage != null && secondLatestMessage.isGroupV2JoinRequest(changeEditor.get())) { if (secondLatestMessage != null && secondLatestMessage.isGroupV2JoinRequest(changeEditor.get())) {
id = secondLatestMessage.id id = secondLatestMessage.id
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, message.changeRevision, changeEditor.get()) encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, message.changeRevision, changeEditor.get().toByteString())
deleteMessage(latestMessage.id) deleteMessage(latestMessage.id)
} else { } else {
id = latestMessage.id id = latestMessage.id
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, message.changeRevision, changeEditor.get()) encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, message.changeRevision, changeEditor.get().toByteString())
} }
db.update(TABLE_NAME) db.update(TABLE_NAME)

View file

@ -79,10 +79,10 @@ final class GroupsV2UpdateMessageProducer {
} }
if (selfPending.isPresent()) { if (selfPending.isPresent()) {
return updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, selfPending.get().getAddedByUuid(), R.drawable.ic_update_group_add_16); return updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, selfPending.get().getAddedByAci(), R.drawable.ic_update_group_add_16);
} }
ByteString foundingMemberUuid = decryptedGroupChange.getEditor(); ByteString foundingMemberUuid = decryptedGroupChange.getEditorServiceIdBytes();
if (!foundingMemberUuid.isEmpty()) { if (!foundingMemberUuid.isEmpty()) {
if (selfIds.matches(foundingMemberUuid)) { if (selfIds.matches(foundingMemberUuid)) {
return updateDescription(context.getString(R.string.MessageRecord_you_created_the_group), R.drawable.ic_update_group_16); return updateDescription(context.getString(R.string.MessageRecord_you_created_the_group), R.drawable.ic_update_group_16);
@ -91,9 +91,7 @@ final class GroupsV2UpdateMessageProducer {
} }
} }
if (DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getAci().getRawUuid()).isPresent() || if (DecryptedGroupUtil.findMemberByAci(group.getMembersList(), selfIds.getAci()).isPresent()) {
(selfIds.getPni() != null && DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getPni().getRawUuid()).isPresent()))
{
return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16); return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16);
} else { } else {
return updateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16); return updateDescription(context.getString(R.string.MessageRecord_group_updated), R.drawable.ic_update_group_16);
@ -107,7 +105,14 @@ final class GroupsV2UpdateMessageProducer {
List<UpdateDescription> updates = new LinkedList<>(); List<UpdateDescription> updates = new LinkedList<>();
if (change.getEditor().isEmpty() || UuidUtil.UNKNOWN_UUID.equals(UuidUtil.fromByteString(change.getEditor()))) { boolean editorUnknown = change.getEditorServiceIdBytes().isEmpty();
ServiceId editorServiceId = editorUnknown ? null : ServiceId.parseOrNull(change.getEditorServiceIdBytes());
if (editorServiceId == null || editorServiceId.isUnknown()) {
editorUnknown = true;
}
if (editorUnknown) {
describeUnknownEditorMemberAdditions(change, updates); describeUnknownEditorMemberAdditions(change, updates);
describeUnknownEditorModifyMemberRoles(change, updates); describeUnknownEditorModifyMemberRoles(change, updates);
@ -167,12 +172,12 @@ final class GroupsV2UpdateMessageProducer {
* Handles case of future protocol versions where we don't know what has changed. * Handles case of future protocol versions where we don't know what has changed.
*/ */
private void describeUnknownChange(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeUnknownChange(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_updated_group, change.getEditor(), R.drawable.ic_update_group_16)); updates.add(updateDescription(R.string.MessageRecord_s_updated_group, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_16));
} }
} }
@ -181,25 +186,25 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeMemberAdditions(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeMemberAdditions(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedMember member : change.getNewMembersList()) { for (DecryptedMember member : change.getNewMembersList()) {
boolean newMemberIsYou = selfIds.matches(member.getUuid()); boolean newMemberIsYou = selfIds.matches(member.getAciBytes());
if (editorIsYou) { if (editorIsYou) {
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group_via_the_group_link), R.drawable.ic_update_group_accept_16)); updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group_via_the_group_link), R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_you_added_s, member.getUuid(), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_you_added_s, member.getAciBytes(), R.drawable.ic_update_group_add_16));
} }
} else { } else {
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(0, updateDescription(R.string.MessageRecord_s_added_you, change.getEditor(), R.drawable.ic_update_group_add_16)); updates.add(0, updateDescription(R.string.MessageRecord_s_added_you, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_add_16));
} else { } else {
if (member.getUuid().equals(change.getEditor())) { if (member.getAciBytes().equals(change.getEditorServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group_via_the_group_link, member.getUuid(), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group_via_the_group_link, member.getAciBytes(), R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_added_s, change.getEditor(), member.getUuid(), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_added_s, change.getEditorServiceIdBytes(), member.getAciBytes(), R.drawable.ic_update_group_add_16));
} }
} }
} }
@ -208,18 +213,18 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorMemberAdditions(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeUnknownEditorMemberAdditions(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
for (DecryptedMember member : change.getNewMembersList()) { for (DecryptedMember member : change.getNewMembersList()) {
boolean newMemberIsYou = selfIds.matches(member.getUuid()); boolean newMemberIsYou = selfIds.matches(member.getAciBytes());
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16)); updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, member.getUuid(), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, member.getAciBytes(), R.drawable.ic_update_group_add_16));
} }
} }
} }
private void describeMemberRemovals(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeMemberRemovals(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (ByteString member : change.getDeleteMembersList()) { for (ByteString member : change.getDeleteMembersList()) {
boolean removedMemberIsYou = selfIds.matches(member); boolean removedMemberIsYou = selfIds.matches(member);
@ -232,12 +237,12 @@ final class GroupsV2UpdateMessageProducer {
} }
} else { } else {
if (removedMemberIsYou) { if (removedMemberIsYou) {
updates.add(updateDescription(R.string.MessageRecord_s_removed_you_from_the_group, change.getEditor(), R.drawable.ic_update_group_remove_16)); updates.add(updateDescription(R.string.MessageRecord_s_removed_you_from_the_group, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_remove_16));
} else { } else {
if (member.equals(change.getEditor())) { if (member.equals(change.getEditorServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_left_the_group, member, R.drawable.ic_update_group_leave_16)); updates.add(updateDescription(R.string.MessageRecord_s_left_the_group, member, R.drawable.ic_update_group_leave_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_removed_s, change.getEditor(), member, R.drawable.ic_update_group_remove_16)); updates.add(updateDescription(R.string.MessageRecord_s_removed_s, change.getEditorServiceIdBytes(), member, R.drawable.ic_update_group_remove_16));
} }
} }
} }
@ -257,29 +262,29 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeModifyMemberRoles(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeModifyMemberRoles(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedModifyMemberRole roleChange : change.getModifyMemberRolesList()) { for (DecryptedModifyMemberRole roleChange : change.getModifyMemberRolesList()) {
boolean changedMemberIsYou = selfIds.matches(roleChange.getUuid()); boolean changedMemberIsYou = selfIds.matches(roleChange.getAciBytes());
if (roleChange.getRole() == Member.Role.ADMINISTRATOR) { if (roleChange.getRole() == Member.Role.ADMINISTRATOR) {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(R.string.MessageRecord_you_made_s_an_admin, roleChange.getUuid(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_you_made_s_an_admin, roleChange.getAciBytes(), R.drawable.ic_update_group_role_16));
} else { } else {
if (changedMemberIsYou) { if (changedMemberIsYou) {
updates.add(updateDescription(R.string.MessageRecord_s_made_you_an_admin, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_made_you_an_admin, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_made_s_an_admin, change.getEditor(), roleChange.getUuid(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_made_s_an_admin, change.getEditorServiceIdBytes(), roleChange.getAciBytes(), R.drawable.ic_update_group_role_16));
} }
} }
} else { } else {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(R.string.MessageRecord_you_revoked_admin_privileges_from_s, roleChange.getUuid(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_you_revoked_admin_privileges_from_s, roleChange.getAciBytes(), R.drawable.ic_update_group_role_16));
} else { } else {
if (changedMemberIsYou) { if (changedMemberIsYou) {
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_admin_privileges, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_admin_privileges, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_revoked_admin_privileges_from_s, change.getEditor(), roleChange.getUuid(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_revoked_admin_privileges_from_s, change.getEditorServiceIdBytes(), roleChange.getAciBytes(), R.drawable.ic_update_group_role_16));
} }
} }
} }
@ -288,36 +293,36 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorModifyMemberRoles(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeUnknownEditorModifyMemberRoles(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
for (DecryptedModifyMemberRole roleChange : change.getModifyMemberRolesList()) { for (DecryptedModifyMemberRole roleChange : change.getModifyMemberRolesList()) {
boolean changedMemberIsYou = selfIds.matches(roleChange.getUuid()); boolean changedMemberIsYou = selfIds.matches(roleChange.getAciBytes());
if (roleChange.getRole() == Member.Role.ADMINISTRATOR) { if (roleChange.getRole() == Member.Role.ADMINISTRATOR) {
if (changedMemberIsYou) { if (changedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_now_an_admin), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_now_an_admin), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_is_now_an_admin, roleChange.getUuid(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_is_now_an_admin, roleChange.getAciBytes(), R.drawable.ic_update_group_role_16));
} }
} else { } else {
if (changedMemberIsYou) { if (changedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_an_admin), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_an_admin), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_is_no_longer_an_admin, roleChange.getUuid(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_is_no_longer_an_admin, roleChange.getAciBytes(), R.drawable.ic_update_group_role_16));
} }
} }
} }
} }
private void describeInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
int notYouInviteCount = 0; int notYouInviteCount = 0;
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) { for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary()); boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBytes());
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, change.getEditor(), R.drawable.ic_update_group_add_16)); updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_add_16));
} else { } else {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, invitee.getServiceIdBinary(), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_you_invited_s_to_the_group, invitee.getServiceIdBytes(), R.drawable.ic_update_group_add_16));
} else { } else {
notYouInviteCount++; notYouInviteCount++;
} }
@ -325,7 +330,7 @@ final class GroupsV2UpdateMessageProducer {
} }
if (notYouInviteCount > 0) { if (notYouInviteCount > 0) {
updates.add(updateDescription(R.plurals.MessageRecord_s_invited_members, notYouInviteCount, change.getEditor(), notYouInviteCount, R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.plurals.MessageRecord_s_invited_members, notYouInviteCount, change.getEditorServiceIdBytes(), notYouInviteCount, R.drawable.ic_update_group_add_16));
} }
} }
@ -333,15 +338,15 @@ final class GroupsV2UpdateMessageProducer {
int notYouInviteCount = 0; int notYouInviteCount = 0;
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) { for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary()); boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBytes());
if (newMemberIsYou) { if (newMemberIsYou) {
UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByUuid()); UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByAci());
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) { if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_were_invited_to_the_group), R.drawable.ic_update_group_add_16)); updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_were_invited_to_the_group), R.drawable.ic_update_group_add_16));
} else { } else {
updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, invitee.getAddedByUuid(), R.drawable.ic_update_group_add_16)); updates.add(0, updateDescription(R.string.MessageRecord_s_invited_you_to_the_group, invitee.getAddedByAci(), R.drawable.ic_update_group_add_16));
} }
} else { } else {
notYouInviteCount++; notYouInviteCount++;
@ -354,19 +359,19 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeRevokedInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeRevokedInvitations(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
int notDeclineCount = 0; int notDeclineCount = 0;
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) { for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
boolean decline = invitee.getServiceIdBinary().equals(change.getEditor()); boolean decline = invitee.getServiceIdBytes().equals(change.getEditorServiceIdBytes());
if (decline) { if (decline) {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
} else { } else {
updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group), R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_someone_declined_an_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
} }
} else if (selfIds.matches(invitee.getServiceIdBinary())) { } else if (selfIds.matches(invitee.getServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, change.getEditor(), R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_decline_16));
} else { } else {
notDeclineCount++; notDeclineCount++;
} }
@ -376,7 +381,7 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_you_revoked_invites, notDeclineCount, notDeclineCount), R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_you_revoked_invites, notDeclineCount, notDeclineCount), R.drawable.ic_update_group_decline_16));
} else { } else {
updates.add(updateDescription(R.plurals.MessageRecord_s_revoked_invites, notDeclineCount, change.getEditor(), notDeclineCount, R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(R.plurals.MessageRecord_s_revoked_invites, notDeclineCount, change.getEditorServiceIdBytes(), notDeclineCount, R.drawable.ic_update_group_decline_16));
} }
} }
} }
@ -385,7 +390,7 @@ final class GroupsV2UpdateMessageProducer {
int notDeclineCount = 0; int notDeclineCount = 0;
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) { for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
boolean inviteeWasYou = selfIds.matches(invitee.getServiceIdBinary()); boolean inviteeWasYou = selfIds.matches(invitee.getServiceIdBytes());
if (inviteeWasYou) { if (inviteeWasYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group), R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_an_admin_revoked_your_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
@ -400,26 +405,26 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describePromotePending(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describePromotePending(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedMember newMember : change.getPromotePendingMembersList()) { for (DecryptedMember newMember : change.getPromotePendingMembersList()) {
ByteString uuid = newMember.getUuid(); ByteString aci = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(uuid); boolean newMemberIsYou = selfIds.matches(aci);
if (editorIsYou) { if (editorIsYou) {
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_accepted_invite), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_accepted_invite), R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_you_added_invited_member_s, uuid, R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_you_added_invited_member_s, aci, R.drawable.ic_update_group_add_16));
} }
} else { } else {
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(updateDescription(R.string.MessageRecord_s_added_you, change.getEditor(), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_added_you, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_add_16));
} else { } else {
if (uuid.equals(change.getEditor())) { if (aci.equals(change.getEditorServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, uuid, R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, aci, R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_added_invited_member_s, change.getEditor(), uuid, R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_added_invited_member_s, change.getEditorServiceIdBytes(), aci, R.drawable.ic_update_group_add_16));
} }
} }
} }
@ -428,38 +433,38 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorPromotePending(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeUnknownEditorPromotePending(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
for (DecryptedMember newMember : change.getPromotePendingMembersList()) { for (DecryptedMember newMember : change.getPromotePendingMembersList()) {
ByteString uuid = newMember.getUuid(); ByteString aci = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(uuid); boolean newMemberIsYou = selfIds.matches(aci);
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, uuid, R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, aci, R.drawable.ic_update_group_add_16));
} }
} }
} }
private void describeNewTitle(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeNewTitle(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewTitle()) { if (change.hasNewTitle()) {
String newTitle = StringUtil.isolateBidi(change.getNewTitle().getValue()); String newTitle = StringUtil.isolateBidi(change.getNewTitle().getValue());
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_name_to_s, newTitle), R.drawable.ic_update_group_name_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_name_to_s, newTitle), R.drawable.ic_update_group_name_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_name_to_s, change.getEditor(), newTitle, R.drawable.ic_update_group_name_16)); updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_name_to_s, change.getEditorServiceIdBytes(), newTitle, R.drawable.ic_update_group_name_16));
} }
} }
} }
private void describeNewDescription(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeNewDescription(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewDescription()) { if (change.hasNewDescription()) {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_description), R.drawable.ic_update_group_name_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_description), R.drawable.ic_update_group_name_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_description, change.getEditor(), R.drawable.ic_update_group_name_16)); updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_description, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_name_16));
} }
} }
} }
@ -477,13 +482,13 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeNewAvatar(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeNewAvatar(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewAvatar()) { if (change.hasNewAvatar()) {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_avatar), R.drawable.ic_update_group_avatar_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_avatar), R.drawable.ic_update_group_avatar_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_avatar, change.getEditor(), R.drawable.ic_update_group_avatar_16)); updates.add(updateDescription(R.string.MessageRecord_s_changed_the_group_avatar, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_avatar_16));
} }
} }
} }
@ -495,14 +500,14 @@ final class GroupsV2UpdateMessageProducer {
} }
void describeNewTimer(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { void describeNewTimer(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewTimer()) { if (change.hasNewTimer()) {
String time = ExpirationUtil.getExpirationDisplayValue(context, change.getNewTimer().getDuration()); String time = ExpirationUtil.getExpirationDisplayValue(context, change.getNewTimer().getDuration());
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_set_disappearing_message_time_to_s, change.getEditor(), time, R.drawable.ic_update_timer_16)); updates.add(updateDescription(R.string.MessageRecord_s_set_disappearing_message_time_to_s, change.getEditorServiceIdBytes(), time, R.drawable.ic_update_timer_16));
} }
} }
} }
@ -515,14 +520,14 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeNewAttributeAccess(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeNewAttributeAccess(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.getNewAttributeAccess() != AccessControl.AccessRequired.UNKNOWN) { if (change.getNewAttributeAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewAttributeAccess()); String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewAttributeAccess());
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_info_to_s, accessLevel), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_info_to_s, accessLevel), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_changed_who_can_edit_group_info_to_s, change.getEditor(), accessLevel, R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_changed_who_can_edit_group_info_to_s, change.getEditorServiceIdBytes(), accessLevel, R.drawable.ic_update_group_role_16));
} }
} }
} }
@ -535,14 +540,14 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeNewMembershipAccess(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeNewMembershipAccess(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.getNewMemberAccess() != AccessControl.AccessRequired.UNKNOWN) { if (change.getNewMemberAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewMemberAccess()); String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewMemberAccess());
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_membership_to_s, accessLevel), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_who_can_edit_group_membership_to_s, accessLevel), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_changed_who_can_edit_group_membership_to_s, change.getEditor(), accessLevel, R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_changed_who_can_edit_group_membership_to_s, change.getEditorServiceIdBytes(), accessLevel, R.drawable.ic_update_group_role_16));
} }
} }
} }
@ -564,7 +569,7 @@ final class GroupsV2UpdateMessageProducer {
previousAccessControl = previousGroupState.getAccessControl().getAddFromInviteLink(); previousAccessControl = previousGroupState.getAccessControl().getAddFromInviteLink();
} }
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
boolean groupLinkEnabled = false; boolean groupLinkEnabled = false;
switch (change.getNewInviteLinkAccess()) { switch (change.getNewInviteLinkAccess()) {
@ -578,9 +583,9 @@ final class GroupsV2UpdateMessageProducer {
} }
} else { } else {
if (previousAccessControl == AccessControl.AccessRequired.ADMINISTRATOR) { if (previousAccessControl == AccessControl.AccessRequired.ADMINISTRATOR) {
updates.add(updateDescription(R.string.MessageRecord_s_turned_off_admin_approval_for_the_group_link, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_turned_off_admin_approval_for_the_group_link, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_off, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_off, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} }
} }
break; break;
@ -594,9 +599,9 @@ final class GroupsV2UpdateMessageProducer {
} }
} else { } else {
if (previousAccessControl == AccessControl.AccessRequired.ANY) { if (previousAccessControl == AccessControl.AccessRequired.ANY) {
updates.add(updateDescription(R.string.MessageRecord_s_turned_on_admin_approval_for_the_group_link, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_turned_on_admin_approval_for_the_group_link, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_on, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_turned_on_the_group_link_with_admin_approval_on, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} }
} }
break; break;
@ -604,7 +609,7 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_the_group_link), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_the_group_link), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_turned_off_the_group_link, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_turned_off_the_group_link, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} }
break; break;
} }
@ -613,7 +618,7 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_reset_the_group_link), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_reset_the_group_link), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_reset_the_group_link, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_reset_the_group_link, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} }
} }
} }
@ -657,19 +662,19 @@ final class GroupsV2UpdateMessageProducer {
Set<ByteString> deleteRequestingUuids = new HashSet<>(change.getDeleteRequestingMembersList()); Set<ByteString> deleteRequestingUuids = new HashSet<>(change.getDeleteRequestingMembersList());
for (DecryptedRequestingMember member : change.getNewRequestingMembersList()) { for (DecryptedRequestingMember member : change.getNewRequestingMembersList()) {
boolean requestingMemberIsYou = selfIds.matches(member.getUuid()); boolean requestingMemberIsYou = selfIds.matches(member.getAciBytes());
if (requestingMemberIsYou) { if (requestingMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_sent_a_request_to_join_the_group), R.drawable.ic_update_group_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_sent_a_request_to_join_the_group), R.drawable.ic_update_group_16));
} else { } else {
if (deleteRequestingUuids.contains(member.getUuid())) { if (deleteRequestingUuids.contains(member.getAciBytes())) {
updates.add(updateDescription(R.plurals.MessageRecord_s_requested_and_cancelled_their_request_to_join_via_the_group_link, updates.add(updateDescription(R.plurals.MessageRecord_s_requested_and_cancelled_their_request_to_join_via_the_group_link,
change.getDeleteRequestingMembersCount(), change.getDeleteRequestingMembersCount(),
member.getUuid(), member.getAciBytes(),
change.getDeleteRequestingMembersCount(), change.getDeleteRequestingMembersCount(),
R.drawable.ic_update_group_16)); R.drawable.ic_update_group_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_requested_to_join_via_the_group_link, member.getUuid(), R.drawable.ic_update_group_16)); updates.add(updateDescription(R.string.MessageRecord_s_requested_to_join_via_the_group_link, member.getAciBytes(), R.drawable.ic_update_group_16));
} }
} }
} }
@ -677,17 +682,17 @@ final class GroupsV2UpdateMessageProducer {
private void describeRequestingMembersApprovals(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeRequestingMembersApprovals(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
for (DecryptedApproveMember requestingMember : change.getPromoteRequestingMembersList()) { for (DecryptedApproveMember requestingMember : change.getPromoteRequestingMembersList()) {
boolean requestingMemberIsYou = selfIds.matches(requestingMember.getUuid()); boolean requestingMemberIsYou = selfIds.matches(requestingMember.getAciBytes());
if (requestingMemberIsYou) { if (requestingMemberIsYou) {
updates.add(updateDescription(R.string.MessageRecord_s_approved_your_request_to_join_the_group, change.getEditor(), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_s_approved_your_request_to_join_the_group, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_accept_16));
} else { } else {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(R.string.MessageRecord_you_approved_a_request_to_join_the_group_from_s, requestingMember.getUuid(), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_you_approved_a_request_to_join_the_group_from_s, requestingMember.getAciBytes(), R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_approved_a_request_to_join_the_group_from_s, change.getEditor(), requestingMember.getUuid(), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_s_approved_a_request_to_join_the_group_from_s, change.getEditorServiceIdBytes(), requestingMember.getAciBytes(), R.drawable.ic_update_group_accept_16));
} }
} }
} }
@ -695,20 +700,20 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorRequestingMembersApprovals(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeUnknownEditorRequestingMembersApprovals(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
for (DecryptedApproveMember requestingMember : change.getPromoteRequestingMembersList()) { for (DecryptedApproveMember requestingMember : change.getPromoteRequestingMembersList()) {
boolean requestingMemberIsYou = selfIds.matches(requestingMember.getUuid()); boolean requestingMemberIsYou = selfIds.matches(requestingMember.getAciBytes());
if (requestingMemberIsYou) { if (requestingMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_approved), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_approved), R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_approved, requestingMember.getUuid(), R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_a_request_to_join_the_group_from_s_has_been_approved, requestingMember.getAciBytes(), R.drawable.ic_update_group_accept_16));
} }
} }
} }
private void describeRequestingMembersDeletes(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeRequestingMembersDeletes(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
Set<ByteString> newRequestingUuids = change.getNewRequestingMembersList().stream().map(DecryptedRequestingMember::getUuid).collect(Collectors.toSet()); Set<ByteString> newRequestingUuids = change.getNewRequestingMembersList().stream().map(DecryptedRequestingMember::getAciBytes).collect(Collectors.toSet());
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (ByteString requestingMember : change.getDeleteRequestingMembersList()) { for (ByteString requestingMember : change.getDeleteRequestingMembersList()) {
if (newRequestingUuids.contains(requestingMember)) { if (newRequestingUuids.contains(requestingMember)) {
@ -724,12 +729,12 @@ final class GroupsV2UpdateMessageProducer {
updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin), R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_your_request_to_join_the_group_has_been_denied_by_an_admin), R.drawable.ic_update_group_decline_16));
} }
} else { } else {
boolean editorIsCanceledMember = change.getEditor().equals(requestingMember); boolean editorIsCanceledMember = change.getEditorServiceIdBytes().equals(requestingMember);
if (editorIsCanceledMember) { if (editorIsCanceledMember) {
updates.add(updateDescription(R.string.MessageRecord_s_canceled_their_request_to_join_the_group, requestingMember, R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(R.string.MessageRecord_s_canceled_their_request_to_join_the_group, requestingMember, R.drawable.ic_update_group_decline_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_denied_a_request_to_join_the_group_from_s, change.getEditor(), requestingMember, R.drawable.ic_update_group_decline_16)); updates.add(updateDescription(R.string.MessageRecord_s_denied_a_request_to_join_the_group_from_s, change.getEditorServiceIdBytes(), requestingMember, R.drawable.ic_update_group_decline_16));
} }
} }
} }
@ -748,19 +753,19 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describeAnnouncementGroupChange(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeAnnouncementGroupChange(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.getNewIsAnnouncementGroup() == EnabledState.ENABLED) { if (change.getNewIsAnnouncementGroup() == EnabledState.ENABLED) {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_only_admins_to_send), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_only_admins_to_send), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_allow_only_admins_to_send, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_allow_only_admins_to_send, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} }
} else if (change.getNewIsAnnouncementGroup() == EnabledState.DISABLED) { } else if (change.getNewIsAnnouncementGroup() == EnabledState.DISABLED) {
if (editorIsYou) { if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_all_members_to_send), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_all_members_to_send), R.drawable.ic_update_group_role_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_allow_all_members_to_send, change.getEditor(), R.drawable.ic_update_group_role_16)); updates.add(updateDescription(R.string.MessageRecord_s_allow_all_members_to_send, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_role_16));
} }
} }
} }
@ -774,10 +779,10 @@ final class GroupsV2UpdateMessageProducer {
} }
private void describePromotePendingPniAci(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describePromotePendingPniAci(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor()); boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) { for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) {
ByteString uuid = newMember.getUuid(); ByteString uuid = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(uuid); boolean newMemberIsYou = selfIds.matches(uuid);
if (editorIsYou) { if (editorIsYou) {
@ -788,12 +793,12 @@ final class GroupsV2UpdateMessageProducer {
} }
} else { } else {
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(updateDescription(R.string.MessageRecord_s_added_you, change.getEditor(), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_added_you, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_add_16));
} else { } else {
if (uuid.equals(change.getEditor())) { if (uuid.equals(change.getEditorServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, uuid, R.drawable.ic_update_group_accept_16)); updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, uuid, R.drawable.ic_update_group_accept_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_added_invited_member_s, change.getEditor(), uuid, R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_added_invited_member_s, change.getEditorServiceIdBytes(), uuid, R.drawable.ic_update_group_add_16));
} }
} }
} }
@ -802,13 +807,13 @@ final class GroupsV2UpdateMessageProducer {
private void describeUnknownEditorPromotePendingPniAci(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) { private void describeUnknownEditorPromotePendingPniAci(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) { for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) {
ByteString uuid = newMember.getUuid(); ByteString aci = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(uuid); boolean newMemberIsYou = selfIds.matches(aci);
if (newMemberIsYou) { if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16)); updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
} else { } else {
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, uuid, R.drawable.ic_update_group_add_16)); updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group, aci, R.drawable.ic_update_group_add_16));
} }
} }
} }

View file

@ -308,7 +308,7 @@ public abstract class MessageRecord extends DisplayRecord {
private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) { private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) {
return change.getRevision() == 0 && return change.getRevision() == 0 &&
change.getEditor().equals(UuidUtil.toByteString(SignalStore.account().requireAci().getRawUuid())); change.getEditorServiceIdBytes().equals(SignalStore.account().requireAci().toByteString());
} }
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body, @Nullable Consumer<RecipientId> recipientClickHandler) { public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body, @Nullable Consumer<RecipientId> recipientClickHandler) {
@ -349,10 +349,15 @@ public abstract class MessageRecord extends DisplayRecord {
boolean invited = DecryptedGroupUtil.findPendingByServiceId(groupState.getPendingMembersList(), SignalStore.account().requireAci()).isPresent(); boolean invited = DecryptedGroupUtil.findPendingByServiceId(groupState.getPendingMembersList(), SignalStore.account().requireAci()).isPresent();
if (decryptedGroupV2Context.hasChange()) { if (decryptedGroupV2Context.hasChange()) {
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor()); ServiceId changeEditor = ServiceId.parseOrNull(decryptedGroupV2Context.getChange().getEditorServiceIdBytes());
if (changeEditor != null) { if (changeEditor != null) {
return new InviteAddState(invited, ACI.from(changeEditor)); if (changeEditor instanceof ACI) {
return new InviteAddState(invited, (ACI) changeEditor);
} else {
Log.w(TAG, "Adder was a PNI! This should not happen.");
return null;
}
} }
} }
@ -468,14 +473,13 @@ public abstract class MessageRecord extends DisplayRecord {
return false; return false;
} }
return isGroupV2JoinRequest(UuidUtil.toByteString(serviceId.getRawUuid()));
}
public boolean isGroupV2JoinRequest(@NonNull ByteString uuid) {
DecryptedGroupV2Context decryptedGroupV2Context = getDecryptedGroupV2Context(); DecryptedGroupV2Context decryptedGroupV2Context = getDecryptedGroupV2Context();
if (decryptedGroupV2Context != null && decryptedGroupV2Context.hasChange()) { if (decryptedGroupV2Context != null && decryptedGroupV2Context.hasChange()) {
DecryptedGroupChange change = decryptedGroupV2Context.getChange(); DecryptedGroupChange change = decryptedGroupV2Context.getChange();
return change.getEditor().equals(uuid) && change.getNewRequestingMembersList().stream().anyMatch(r -> r.getUuid().equals(uuid)); ByteString serviceIdByteString = serviceId.toByteString();
return change.getEditorServiceIdBytes().equals(serviceIdByteString) && change.getNewRequestingMembersList().stream().anyMatch(r -> r.getAciBytes().equals(serviceIdByteString));
} }
return false; return false;
} }
@ -490,7 +494,7 @@ public abstract class MessageRecord extends DisplayRecord {
DecryptedGroupChange change = decryptedGroupV2Context.getChange(); DecryptedGroupChange change = decryptedGroupV2Context.getChange();
return change.getNewRequestingMembersCount() > 0 && return change.getNewRequestingMembersCount() > 0 &&
change.getDeleteRequestingMembersCount() > 0 && change.getDeleteRequestingMembersCount() > 0 &&
(serviceId == null || change.getEditor().equals(UuidUtil.toByteString(serviceId.getRawUuid()))); (serviceId == null || change.getEditorServiceIdBytes().equals(serviceId.toByteString()));
} }
return false; return false;
} }

View file

@ -169,7 +169,7 @@ public final class GroupManager {
throws GroupChangeBusyException, GroupChangeFailedException, GroupInsufficientRightsException, GroupNotAMemberException, IOException throws GroupChangeBusyException, GroupChangeFailedException, GroupInsufficientRightsException, GroupNotAMemberException, IOException
{ {
try (GroupManagerV2.GroupEditor edit = new GroupManagerV2(context).edit(groupId.requireV2())) { try (GroupManagerV2.GroupEditor edit = new GroupManagerV2(context).edit(groupId.requireV2())) {
edit.ejectMember(recipient.requireServiceId(), false, true, true); edit.ejectMember(recipient.requireAci(), false, true, true);
Log.i(TAG, "Member removed from group " + groupId); Log.i(TAG, "Member removed from group " + groupId);
} }
} }
@ -319,13 +319,13 @@ public final class GroupManager {
GroupTable.V2GroupProperties groupProperties = SignalDatabase.groups().requireGroup(groupId).requireV2GroupProperties(); GroupTable.V2GroupProperties groupProperties = SignalDatabase.groups().requireGroup(groupId).requireV2GroupProperties();
Recipient recipient = Recipient.resolved(recipientId); Recipient recipient = Recipient.resolved(recipientId);
if (groupProperties.getBannedMembers().contains(recipient.requireServiceId().getRawUuid())) { if (groupProperties.getBannedMembers().contains(recipient.requireServiceId())) {
Log.i(TAG, "Attempt to ban already banned recipient: " + recipientId); Log.i(TAG, "Attempt to ban already banned recipient: " + recipientId);
return; return;
} }
try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) { try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) {
editor.ban(recipient.requireServiceId().getRawUuid()); editor.ban(recipient.requireServiceId());
} }
} }

View file

@ -231,7 +231,7 @@ final class GroupManagerV2 {
return latest; return latest;
} }
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), selfAci.getRawUuid()); Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByAci(latest.getMembersList(), selfAci);
if (!selfInFullMemberList.isPresent()) { if (!selfInFullMemberList.isPresent()) {
return latest; return latest;
@ -309,7 +309,7 @@ final class GroupManagerV2 {
SignalDatabase.recipients().setProfileSharing(groupRecipient.getId(), true); SignalDatabase.recipients().setProfileSharing(groupRecipient.getId(), true);
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder(GroupChangeReconstruct.reconstructGroupChange(DecryptedGroup.newBuilder().build(), decryptedGroup)) DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder(GroupChangeReconstruct.reconstructGroupChange(DecryptedGroup.newBuilder().build(), decryptedGroup))
.setEditor(selfAci.toByteString()) .setEditorServiceIdBytes(selfAci.toByteString())
.build(); .build();
RecipientAndThread recipientAndThread = sendGroupUpdateHelper.sendGroupUpdate(masterKey, new GroupMutation(null, groupChange, decryptedGroup), null); RecipientAndThread recipientAndThread = sendGroupUpdateHelper.sendGroupUpdate(masterKey, new GroupMutation(null, groupChange, decryptedGroup), null);
@ -441,8 +441,8 @@ final class GroupManagerV2 {
@NonNull GroupManager.GroupActionResult denyRequests(@NonNull Collection<RecipientId> recipientIds) @NonNull GroupManager.GroupActionResult denyRequests(@NonNull Collection<RecipientId> recipientIds)
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{ {
Set<UUID> uuids = Stream.of(recipientIds) Set<ACI> uuids = Stream.of(recipientIds)
.map(r -> Recipient.resolved(r).requireServiceId().getRawUuid()) .map(r -> Recipient.resolved(r).requireAci())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
return commitChangeWithConflictResolution(selfAci, groupOperations.createRefuseGroupJoinRequest(uuids, true, v2GroupProperties.getDecryptedGroup().getBannedMembersList())); return commitChangeWithConflictResolution(selfAci, groupOperations.createRefuseGroupJoinRequest(uuids, true, v2GroupProperties.getDecryptedGroup().getBannedMembersList()));
@ -463,7 +463,7 @@ final class GroupManagerV2 {
{ {
GroupRecord groupRecord = groupDatabase.requireGroup(groupId); GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup(); DecryptedGroup decryptedGroup = groupRecord.requireV2GroupProperties().getDecryptedGroup();
Optional<DecryptedMember> selfMember = DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), selfAci.getRawUuid()); Optional<DecryptedMember> selfMember = DecryptedGroupUtil.findMemberByAci(decryptedGroup.getMembersList(), selfAci);
Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfAci); Optional<DecryptedPendingMember> aciPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfAci);
Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfPni); Optional<DecryptedPendingMember> pniPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfPni);
Optional<DecryptedPendingMember> selfPendingMember = Optional.empty(); Optional<DecryptedPendingMember> selfPendingMember = Optional.empty();
@ -478,23 +478,23 @@ final class GroupManagerV2 {
if (selfPendingMember.isPresent()) { if (selfPendingMember.isPresent()) {
try { try {
revokeInvites(serviceId, Collections.singleton(new UuidCiphertext(selfPendingMember.get().getUuidCipherText().toByteArray())), false); revokeInvites(serviceId, Collections.singleton(new UuidCiphertext(selfPendingMember.get().getServiceIdCipherText().toByteArray())), false);
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} else if (selfMember.isPresent()) { } else if (selfMember.isPresent()) {
ejectMember(serviceId, true, false, sendToMembers); ejectMember(selfAci, true, false, sendToMembers);
} else { } else {
Log.i(TAG, "Unable to leave group we are not pending or in"); Log.i(TAG, "Unable to leave group we are not pending or in");
} }
} }
@WorkerThread @WorkerThread
@NonNull GroupManager.GroupActionResult ejectMember(@NonNull ServiceId serviceId, boolean allowWhenBlocked, boolean ban, boolean sendToMembers) @NonNull GroupManager.GroupActionResult ejectMember(@NonNull ACI aci, boolean allowWhenBlocked, boolean ban, boolean sendToMembers)
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{ {
return commitChangeWithConflictResolution(selfAci, return commitChangeWithConflictResolution(selfAci,
groupOperations.createRemoveMembersChange(Collections.singleton(serviceId.getRawUuid()), groupOperations.createRemoveMembersChange(Collections.singleton(aci),
ban, ban,
ban ? v2GroupProperties.getDecryptedGroup().getBannedMembersList() ban ? v2GroupProperties.getDecryptedGroup().getBannedMembersList()
: Collections.emptyList()), : Collections.emptyList()),
@ -508,7 +508,7 @@ final class GroupManagerV2 {
{ {
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireServiceId().getRawUuid()).toList(); List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireServiceId().getRawUuid()).toList();
return commitChangeWithConflictResolution(selfAci, groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.getRawUuid(), return commitChangeWithConflictResolution(selfAci, groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci,
newAdminRecipients)); newAdminRecipients));
} }
@ -518,7 +518,7 @@ final class GroupManagerV2 {
{ {
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey(); ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup(); DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup();
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.getRawUuid()); Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByAci(group.getMembersList(), selfAci);
if (!selfInGroup.isPresent()) { if (!selfInGroup.isPresent()) {
Log.w(TAG, "Self not in group " + groupId); Log.w(TAG, "Self not in group " + groupId);
@ -548,7 +548,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{ {
DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup(); DecryptedGroup group = groupDatabase.requireGroup(groupId).requireV2GroupProperties().getDecryptedGroup();
Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfAci.getRawUuid()); Optional<DecryptedMember> selfInGroup = DecryptedGroupUtil.findMemberByAci(group.getMembersList(), selfAci);
if (selfInGroup.isPresent()) { if (selfInGroup.isPresent()) {
Log.w(TAG, "Self already in group"); Log.w(TAG, "Self already in group");
@ -575,13 +575,13 @@ final class GroupManagerV2 {
throw new GroupChangeFailedException("Unable to accept invite when not in pending list"); throw new GroupChangeFailedException("Unable to accept invite when not in pending list");
} }
public GroupManager.GroupActionResult ban(UUID uuid) public GroupManager.GroupActionResult ban(ServiceId serviceId)
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{ {
ByteString uuidByteString = UuidUtil.toByteString(uuid); ByteString serviceIdByteString = serviceId.toByteString();
boolean rejectJoinRequest = v2GroupProperties.getDecryptedGroup().getRequestingMembersList().stream().anyMatch(m -> m.getUuid().equals(uuidByteString)); boolean rejectJoinRequest = v2GroupProperties.getDecryptedGroup().getRequestingMembersList().stream().anyMatch(m -> m.getAciBytes().equals(serviceIdByteString));
return commitChangeWithConflictResolution(selfAci, groupOperations.createBanUuidsChange(Collections.singleton(uuid), rejectJoinRequest, v2GroupProperties.getDecryptedGroup().getBannedMembersList())); return commitChangeWithConflictResolution(selfAci, groupOperations.createBanServiceIdsChange(Collections.singleton(serviceId), rejectJoinRequest, v2GroupProperties.getDecryptedGroup().getBannedMembersList()));
} }
public GroupManager.GroupActionResult unban(Set<ServiceId> serviceIds) public GroupManager.GroupActionResult unban(Set<ServiceId> serviceIds)
@ -650,7 +650,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{ {
boolean refetchedAddMemberCredentials = false; boolean refetchedAddMemberCredentials = false;
change.setSourceUuid(UuidUtil.toByteString(authServiceId.getRawUuid())); change.setSourceServiceId(UuidUtil.toByteString(authServiceId.getRawUuid()));
for (int attempt = 0; attempt < 5; attempt++) { for (int attempt = 0; attempt < 5; attempt++) {
try { try {
@ -1070,16 +1070,16 @@ final class GroupManagerV2 {
.setRevision(GroupsV2StateProcessor.PLACEHOLDER_REVISION); .setRevision(GroupsV2StateProcessor.PLACEHOLDER_REVISION);
Recipient self = Recipient.self(); Recipient self = Recipient.self();
ByteString selfUuid = selfAci.toByteString(); ByteString selfAciBytes = selfAci.toByteString();
ByteString profileKey = ByteString.copyFrom(Objects.requireNonNull(self.getProfileKey())); ByteString profileKey = ByteString.copyFrom(Objects.requireNonNull(self.getProfileKey()));
if (requestToJoin) { if (requestToJoin) {
group.addRequestingMembers(DecryptedRequestingMember.newBuilder() group.addRequestingMembers(DecryptedRequestingMember.newBuilder()
.setUuid(selfUuid) .setAciBytes(selfAciBytes)
.setProfileKey(profileKey)); .setProfileKey(profileKey));
} else { } else {
group.addMembers(DecryptedMember.newBuilder() group.addMembers(DecryptedMember.newBuilder()
.setUuid(selfUuid) .setAciBytes(selfAciBytes)
.setProfileKey(profileKey)); .setProfileKey(profileKey));
} }
@ -1104,7 +1104,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.setSourceUuid(selfAci.toByteString()); change.setSourceServiceId(selfAci.toByteString());
return commitJoinChangeWithConflictResolution(currentRevision, change); return commitJoinChangeWithConflictResolution(currentRevision, change);
} }
@ -1203,7 +1203,7 @@ final class GroupManagerV2 {
void cancelJoinRequest() void cancelJoinRequest()
throws GroupChangeFailedException, IOException throws GroupChangeFailedException, IOException
{ {
Set<UUID> uuids = Collections.singleton(selfAci.getRawUuid()); Set<ACI> uuids = Collections.singleton(selfAci);
GroupChange signedGroupChange; GroupChange signedGroupChange;
try { try {

View file

@ -36,12 +36,12 @@ public final class GroupProtoUtil {
{ {
ByteString bytes = self.toByteString(); ByteString bytes = self.toByteString();
for (DecryptedMember decryptedMember : partialDecryptedGroup.getMembersList()) { for (DecryptedMember decryptedMember : partialDecryptedGroup.getMembersList()) {
if (decryptedMember.getUuid().equals(bytes)) { if (decryptedMember.getAciBytes().equals(bytes)) {
return decryptedMember.getJoinedAtRevision(); return decryptedMember.getJoinedAtRevision();
} }
} }
for (DecryptedPendingMember decryptedMember : partialDecryptedGroup.getPendingMembersList()) { for (DecryptedPendingMember decryptedMember : partialDecryptedGroup.getPendingMembersList()) {
if (decryptedMember.getServiceIdBinary().equals(bytes)) { if (decryptedMember.getServiceIdBytes().equals(bytes)) {
// Assume latest, we don't have any information about when pending members were invited // Assume latest, we don't have any information about when pending members were invited
return partialDecryptedGroup.getRevision(); return partialDecryptedGroup.getRevision();
} }
@ -80,12 +80,12 @@ public final class GroupProtoUtil {
} }
@WorkerThread @WorkerThread
public static Recipient pendingMemberToRecipient(@NonNull Context context, @NonNull DecryptedPendingMember pendingMember) { public static Recipient pendingMemberToRecipient(@NonNull DecryptedPendingMember pendingMember) {
return pendingMemberServiceIdToRecipient(context, pendingMember.getServiceIdBinary()); return pendingMemberServiceIdToRecipient(pendingMember.getServiceIdBytes());
} }
@WorkerThread @WorkerThread
public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString serviceIdBinary) { public static Recipient pendingMemberServiceIdToRecipient(@NonNull ByteString serviceIdBinary) {
ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary); ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary);
if (serviceId.isUnknown()) { if (serviceId.isUnknown()) {
@ -106,11 +106,11 @@ public final class GroupProtoUtil {
return RecipientId.from(serviceId); return RecipientId.from(serviceId);
} }
public static boolean isMember(@NonNull UUID uuid, @NonNull List<DecryptedMember> membersList) { public static boolean isMember(@NonNull ACI aci, @NonNull List<DecryptedMember> membersList) {
ByteString uuidBytes = UuidUtil.toByteString(uuid); ByteString aciBytes = aci.toByteString();
for (DecryptedMember member : membersList) { for (DecryptedMember member : membersList) {
if (uuidBytes.equals(member.getUuid())) { if (aciBytes.equals(member.getAciBytes())) {
return true; return true;
} }
} }

View file

@ -111,7 +111,7 @@ public final class LiveGroup {
return Stream.of(requestingMembersList) return Stream.of(requestingMembersList)
.map(requestingMember -> { .map(requestingMember -> {
Recipient recipient = Recipient.externalPush(ServiceId.parseOrThrow(requestingMember.getUuid())); Recipient recipient = Recipient.externalPush(ServiceId.parseOrThrow(requestingMember.getAciBytes()));
return new GroupMemberEntry.RequestingMember(recipient, selfAdmin); return new GroupMemberEntry.RequestingMember(recipient, selfAdmin);
}) })
.toList(); .toList();

View file

@ -59,17 +59,17 @@ final class PendingMemberInvitesRepository {
boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self()); boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self());
Stream.of(pendingMembersList) Stream.of(pendingMembersList)
.groupBy(DecryptedPendingMember::getAddedByUuid) .groupBy(DecryptedPendingMember::getAddedByAci)
.forEach(g -> .forEach(g ->
{ {
ByteString inviterUuid = g.getKey(); ByteString inviterAci = g.getKey();
List<DecryptedPendingMember> invitedMembers = g.getValue(); List<DecryptedPendingMember> invitedMembers = g.getValue();
if (self.equals(inviterUuid)) { if (self.equals(inviterAci)) {
for (DecryptedPendingMember pendingMember : invitedMembers) { for (DecryptedPendingMember pendingMember : invitedMembers) {
try { try {
Recipient invitee = GroupProtoUtil.pendingMemberToRecipient(context, pendingMember); Recipient invitee = GroupProtoUtil.pendingMemberToRecipient(pendingMember);
UuidCiphertext uuidCipherText = new UuidCiphertext(pendingMember.getUuidCipherText().toByteArray()); UuidCiphertext uuidCipherText = new UuidCiphertext(pendingMember.getServiceIdCipherText().toByteArray());
byMe.add(new SinglePendingMemberInvitedByYou(invitee, uuidCipherText)); byMe.add(new SinglePendingMemberInvitedByYou(invitee, uuidCipherText));
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
@ -77,12 +77,12 @@ final class PendingMemberInvitesRepository {
} }
} }
} else { } else {
Recipient inviter = GroupProtoUtil.pendingMemberServiceIdToRecipient(context, inviterUuid); Recipient inviter = GroupProtoUtil.pendingMemberServiceIdToRecipient(inviterAci);
ArrayList<UuidCiphertext> uuidCipherTexts = new ArrayList<>(invitedMembers.size()); ArrayList<UuidCiphertext> uuidCipherTexts = new ArrayList<>(invitedMembers.size());
for (DecryptedPendingMember pendingMember : invitedMembers) { for (DecryptedPendingMember pendingMember : invitedMembers) {
try { try {
uuidCipherTexts.add(new UuidCiphertext(pendingMember.getUuidCipherText().toByteArray())); uuidCipherTexts.add(new UuidCiphertext(pendingMember.getServiceIdCipherText().toByteArray()));
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
Log.w(TAG, e); Log.w(TAG, e);
} }

View file

@ -42,7 +42,7 @@ public final class ProfileKeySet {
* authoritative. * authoritative.
*/ */
public void addKeysFromGroupChange(@NonNull DecryptedGroupChange change) { public void addKeysFromGroupChange(@NonNull DecryptedGroupChange change) {
UUID editor = UuidUtil.fromByteStringOrNull(change.getEditor()); ServiceId editor = ServiceId.parseOrNull(change.getEditorServiceIdBytes());
for (DecryptedMember member : change.getNewMembersList()) { for (DecryptedMember member : change.getNewMembersList()) {
addMemberKey(member, editor); addMemberKey(member, editor);
@ -57,7 +57,7 @@ public final class ProfileKeySet {
} }
for (DecryptedRequestingMember member : change.getNewRequestingMembersList()) { for (DecryptedRequestingMember member : change.getNewRequestingMembersList()) {
addMemberKey(editor, member.getUuid(), member.getProfileKey()); addMemberKey(editor, member.getAciBytes(), member.getProfileKey());
} }
} }
@ -74,17 +74,17 @@ public final class ProfileKeySet {
} }
} }
private void addMemberKey(@NonNull DecryptedMember member, @Nullable UUID changeSource) { private void addMemberKey(@NonNull DecryptedMember member, @Nullable ServiceId changeSource) {
addMemberKey(changeSource, member.getUuid(), member.getProfileKey()); addMemberKey(changeSource, member.getAciBytes(), member.getProfileKey());
} }
private void addMemberKey(@Nullable UUID changeSource, private void addMemberKey(@Nullable ServiceId changeSource,
@NonNull ByteString memberUuidBytes, @NonNull ByteString memberAciBytes,
@NonNull ByteString profileKeyBytes) @NonNull ByteString profileKeyBytes)
{ {
UUID memberUuid = UuidUtil.fromByteString(memberUuidBytes); ACI memberUuid = ACI.parseOrThrow(memberAciBytes);
if (UuidUtil.UNKNOWN_UUID.equals(memberUuid)) { if (memberUuid.isUnknown()) {
Log.w(TAG, "Seen unknown member UUID"); Log.w(TAG, "Seen unknown member UUID");
return; return;
} }
@ -98,11 +98,11 @@ public final class ProfileKeySet {
} }
if (memberUuid.equals(changeSource)) { if (memberUuid.equals(changeSource)) {
authoritativeProfileKeys.put(ACI.from(memberUuid), profileKey); authoritativeProfileKeys.put(memberUuid, profileKey);
profileKeys.remove(ACI.from(memberUuid)); profileKeys.remove(memberUuid);
} else { } else {
if (!authoritativeProfileKeys.containsKey(ACI.from(memberUuid))) { if (!authoritativeProfileKeys.containsKey(memberUuid)) {
profileKeys.put(ACI.from(memberUuid), profileKey); profileKeys.put(memberUuid, profileKey);
} }
} }
} }

View file

@ -55,6 +55,7 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException; import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException; import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup; 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.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceIds; import org.whispersystems.signalservice.api.push.ServiceIds;
import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.api.util.UuidUtil;
@ -69,7 +70,6 @@ import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID;
/** /**
* Advances a groups state to a specified revision. * Advances a groups state to a specified revision.
@ -373,20 +373,20 @@ public class GroupsV2StateProcessor {
boolean addedAsMember = signedGroupChange.getNewMembersList() boolean addedAsMember = signedGroupChange.getNewMembersList()
.stream() .stream()
.map(DecryptedMember::getUuid) .map(DecryptedMember::getAciBytes)
.map(UuidUtil::fromByteStringOrNull) .map(ACI::parseOrNull)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.anyMatch(serviceIds::matches); .anyMatch(serviceIds::matches);
boolean addedAsPendingMember = signedGroupChange.getNewPendingMembersList() boolean addedAsPendingMember = signedGroupChange.getNewPendingMembersList()
.stream() .stream()
.map(DecryptedPendingMember::getServiceIdBinary) .map(DecryptedPendingMember::getServiceIdBytes)
.anyMatch(serviceIds::matches); .anyMatch(serviceIds::matches);
boolean addedAsRequestingMember = signedGroupChange.getNewRequestingMembersList() boolean addedAsRequestingMember = signedGroupChange.getNewRequestingMembersList()
.stream() .stream()
.map(DecryptedRequestingMember::getUuid) .map(DecryptedRequestingMember::getAciBytes)
.map(UuidUtil::fromByteStringOrNull) .map(ACI::parseOrNull)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.anyMatch(serviceIds::matches); .anyMatch(serviceIds::matches);
@ -396,7 +396,7 @@ public class GroupsV2StateProcessor {
private boolean notHavingInviteRevoked(@NonNull DecryptedGroupChange signedGroupChange) { private boolean notHavingInviteRevoked(@NonNull DecryptedGroupChange signedGroupChange) {
boolean havingInviteRevoked = signedGroupChange.getDeletePendingMembersList() boolean havingInviteRevoked = signedGroupChange.getDeletePendingMembersList()
.stream() .stream()
.map(DecryptedPendingMemberRemoval::getServiceIdBinary) .map(DecryptedPendingMemberRemoval::getServiceIdBytes)
.anyMatch(serviceIds::matches); .anyMatch(serviceIds::matches);
return !havingInviteRevoked; return !havingInviteRevoked;
@ -421,12 +421,12 @@ public class GroupsV2StateProcessor {
throw new IOException(e); throw new IOException(e);
} }
if (localState != null && localState.getRevision() >= latestServerGroup.getRevision() && GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), localState.getMembersList())) { if (localState != null && localState.getRevision() >= latestServerGroup.getRevision() && GroupProtoUtil.isMember(serviceIds.getAci(), localState.getMembersList())) {
info("Local state is at or later than server"); info("Local state is at or later than server");
return new GroupUpdateResult(GroupState.GROUP_CONSISTENT_OR_AHEAD, null); return new GroupUpdateResult(GroupState.GROUP_CONSISTENT_OR_AHEAD, null);
} }
if (latestRevisionOnly || !GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), latestServerGroup.getMembersList())) { if (latestRevisionOnly || !GroupProtoUtil.isMember(serviceIds.getAci(), latestServerGroup.getMembersList())) {
info("Latest revision or not a member, use latest only"); info("Latest revision or not a member, use latest only");
inputGroupState = new GlobalGroupState(localState, Collections.singletonList(new ServerGroupLogEntry(latestServerGroup.getFullyDecryptedGroup(), null))); inputGroupState = new GlobalGroupState(localState, Collections.singletonList(new ServerGroupLogEntry(latestServerGroup.getFullyDecryptedGroup(), null)));
} else { } else {
@ -437,7 +437,7 @@ public class GroupsV2StateProcessor {
localState == null || localState == null ||
localState.getRevision() < 0 || localState.getRevision() < 0 ||
localState.getRevision() == revisionWeWereAdded || localState.getRevision() == revisionWeWereAdded ||
!GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), localState.getMembersList()) || !GroupProtoUtil.isMember(serviceIds.getAci(), localState.getMembersList()) ||
(revision == LATEST && localState.getRevision() + 1 < latestServerGroup.getRevision()); (revision == LATEST && localState.getRevision() + 1 < latestServerGroup.getRevision());
info("Requesting from server currentRevision: " + (localState != null ? localState.getRevision() : "null") + info("Requesting from server currentRevision: " + (localState != null ? localState.getRevision() : "null") +
@ -552,18 +552,17 @@ public class GroupsV2StateProcessor {
} }
Recipient groupRecipient = Recipient.externalGroupExact(groupId); Recipient groupRecipient = Recipient.externalGroupExact(groupId);
UUID selfUuid = serviceIds.getAci().getRawUuid();
DecryptedGroup decryptedGroup = groupDatabase.requireGroup(groupId) DecryptedGroup decryptedGroup = groupDatabase.requireGroup(groupId)
.requireV2GroupProperties() .requireV2GroupProperties()
.getDecryptedGroup(); .getDecryptedGroup();
DecryptedGroup simulatedGroupState = DecryptedGroupUtil.removeMember(decryptedGroup, selfUuid, decryptedGroup.getRevision() + 1); DecryptedGroup simulatedGroupState = DecryptedGroupUtil.removeMember(decryptedGroup, serviceIds.getAci(), decryptedGroup.getRevision() + 1);
DecryptedGroupChange simulatedGroupChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange simulatedGroupChange = DecryptedGroupChange.newBuilder()
.setEditor(UuidUtil.toByteString(UuidUtil.UNKNOWN_UUID)) .setEditorServiceIdBytes(ACI.UNKNOWN.toByteString())
.setRevision(simulatedGroupState.getRevision()) .setRevision(simulatedGroupState.getRevision())
.addDeleteMembers(UuidUtil.toByteString(selfUuid)) .addDeleteMembers(serviceIds.getAci().toByteString())
.build(); .build();
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null); DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null);
@ -682,14 +681,14 @@ public class GroupsV2StateProcessor {
void determineProfileSharing(@NonNull GlobalGroupState inputGroupState, @NonNull DecryptedGroup newLocalState) { void determineProfileSharing(@NonNull GlobalGroupState inputGroupState, @NonNull DecryptedGroup newLocalState) {
if (inputGroupState.getLocalState() != null) { if (inputGroupState.getLocalState() != null) {
boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), aci.getRawUuid()).isPresent(); boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByAci(inputGroupState.getLocalState().getMembersList(), aci).isPresent();
if (wasAMemberAlready) { if (wasAMemberAlready) {
return; return;
} }
} }
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), aci.getRawUuid()); Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByAci(newLocalState.getMembersList(), aci);
Optional<DecryptedPendingMember> selfAsPendingOptional = DecryptedGroupUtil.findPendingByServiceId(newLocalState.getPendingMembersList(), aci); Optional<DecryptedPendingMember> selfAsPendingOptional = DecryptedGroupUtil.findPendingByServiceId(newLocalState.getPendingMembersList(), aci);
if (selfAsMemberOptional.isPresent()) { if (selfAsMemberOptional.isPresent()) {
@ -700,8 +699,8 @@ public class GroupsV2StateProcessor {
.map(ServerGroupLogEntry::getChange) .map(ServerGroupLogEntry::getChange)
.filter(c -> c != null && c.getRevision() == revisionJoinedAt) .filter(c -> c != null && c.getRevision() == revisionJoinedAt)
.findFirst() .findFirst()
.map(c -> Optional.ofNullable(UuidUtil.fromByteStringOrNull(c.getEditor())) .map(c -> Optional.ofNullable(ServiceId.parseOrNull(c.getEditorServiceIdBytes()))
.map(uuid -> Recipient.externalPush(ACI.from(uuid)))) .map(Recipient::externalPush))
.orElse(Optional.empty()); .orElse(Optional.empty());
if (addedByOptional.isPresent()) { if (addedByOptional.isPresent()) {
@ -709,7 +708,7 @@ public class GroupsV2StateProcessor {
Log.i(TAG, String.format("Added as a full member of %s by %s", groupId, addedBy.getId())); Log.i(TAG, String.format("Added as a full member of %s by %s", groupId, addedBy.getId()));
if (addedBy.isBlocked() && (inputGroupState.getLocalState() == null || !DecryptedGroupUtil.isRequesting(inputGroupState.getLocalState(), aci.getRawUuid()))) { if (addedBy.isBlocked() && (inputGroupState.getLocalState() == null || !DecryptedGroupUtil.isRequesting(inputGroupState.getLocalState(), aci))) {
Log.i(TAG, "Added by a blocked user. Leaving group."); Log.i(TAG, "Added by a blocked user. Leaving group.");
ApplicationDependencies.getJobManager().add(new LeaveGroupV2Job(groupId)); ApplicationDependencies.getJobManager().add(new LeaveGroupV2Job(groupId));
//noinspection UnnecessaryReturnStatement //noinspection UnnecessaryReturnStatement
@ -725,7 +724,7 @@ public class GroupsV2StateProcessor {
Log.w(TAG, "Could not find founding member during gv2 create. Not enabling profile sharing."); Log.w(TAG, "Could not find founding member during gv2 create. Not enabling profile sharing.");
} }
} else if (selfAsPendingOptional.isPresent()) { } else if (selfAsPendingOptional.isPresent()) {
Optional<Recipient> addedBy = selfAsPendingOptional.flatMap(adder -> Optional.ofNullable(UuidUtil.fromByteStringOrNull(adder.getAddedByUuid())) Optional<Recipient> addedBy = selfAsPendingOptional.flatMap(adder -> Optional.ofNullable(UuidUtil.fromByteStringOrNull(adder.getAddedByAci()))
.map(uuid -> Recipient.externalPush(ACI.from(uuid)))); .map(uuid -> Recipient.externalPush(ACI.from(uuid))));
if (addedBy.isPresent() && addedBy.get().isBlocked()) { if (addedBy.isPresent() && addedBy.get().isBlocked()) {
@ -791,7 +790,7 @@ public class GroupsV2StateProcessor {
} }
void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) { void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) {
Optional<ACI> editor = getEditor(decryptedGroupV2Context).map(ACI::from); Optional<ServiceId> editor = getEditor(decryptedGroupV2Context);
boolean outgoing = !editor.isPresent() || aci.equals(editor.get()); boolean outgoing = !editor.isPresent() || aci.equals(editor.get());
@ -825,15 +824,15 @@ public class GroupsV2StateProcessor {
} }
} }
private Optional<UUID> getEditor(@NonNull DecryptedGroupV2Context decryptedGroupV2Context) { private Optional<ServiceId> getEditor(@NonNull DecryptedGroupV2Context decryptedGroupV2Context) {
DecryptedGroupChange change = decryptedGroupV2Context.getChange(); DecryptedGroupChange change = decryptedGroupV2Context.getChange();
Optional<UUID> changeEditor = DecryptedGroupUtil.editorUuid(change); Optional<ServiceId> changeEditor = DecryptedGroupUtil.editorServiceId(change);
if (changeEditor.isPresent()) { if (changeEditor.isPresent()) {
return changeEditor; return changeEditor;
} else { } else {
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByServiceId(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci); Optional<DecryptedPendingMember> pending = DecryptedGroupUtil.findPendingByServiceId(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci);
if (pendingByUuid.isPresent()) { if (pending.isPresent()) {
return Optional.ofNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid())); return Optional.ofNullable(ACI.parseOrNull(pending.get().getAddedByAci()));
} }
} }
return Optional.empty(); return Optional.empty();

View file

@ -119,10 +119,10 @@ public final class GroupV2UpdateSelfProfileKeyJob extends BaseJob {
continue; continue;
} }
ByteString selfUuidBytes = UuidUtil.toByteString(Recipient.self().requireAci().getRawUuid()); ByteString selfUuidBytes = Recipient.self().requireAci().toByteString();
DecryptedMember selfMember = group.get().requireV2GroupProperties().getDecryptedGroup().getMembersList() DecryptedMember selfMember = group.get().requireV2GroupProperties().getDecryptedGroup().getMembersList()
.stream() .stream()
.filter(m -> m.getUuid().equals(selfUuidBytes)) .filter(m -> m.getAciBytes().equals(selfUuidBytes))
.findFirst() .findFirst()
.orElse(null); .orElse(null);

View file

@ -36,14 +36,12 @@ import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos; import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -73,13 +71,12 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
@NonNull DecryptedGroup decryptedGroup, @NonNull DecryptedGroup decryptedGroup,
@NonNull OutgoingMessage groupMessage) @NonNull OutgoingMessage groupMessage)
{ {
List<UUID> memberUuids = DecryptedGroupUtil.toUuidList(decryptedGroup.getMembersList()); List<ACI> memberAcis = DecryptedGroupUtil.toAciList(decryptedGroup.getMembersList());
List<ServiceId> pendingServiceIds = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.getPendingMembersList()); List<ServiceId> pendingServiceIds = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.getPendingMembersList());
Stream<ServiceId> memberServiceIds = Stream.of(memberUuids) Stream<ACI> memberServiceIds = Stream.of(memberAcis)
.filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid)) .filter(ACI::isValid)
.filter(uuid -> !SignalStore.account().requireAci().getRawUuid().equals(uuid)) .filter(aci -> !SignalStore.account().requireAci().equals(aci));
.map(ACI::from);
Stream<ServiceId> filteredPendingServiceIds = Stream.of(pendingServiceIds) Stream<ServiceId> filteredPendingServiceIds = Stream.of(pendingServiceIds)
.filterNot(ServiceId::isUnknown); .filterNot(ServiceId::isUnknown);

View file

@ -16,15 +16,13 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Base64;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* Represents either a GroupV1 or GroupV2 encoded context. * Represents either a GroupV1 or GroupV2 encoded context.
@ -166,11 +164,11 @@ public final class MessageGroupContext {
return decryptedGroupV2Context.getChange(); return decryptedGroupV2Context.getChange();
} }
public @NonNull List<ServiceId> getAllActivePendingAndRemovedMembers() { public @NonNull List<? extends ServiceId> getAllActivePendingAndRemovedMembers() {
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState(); DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
DecryptedGroupChange groupChange = decryptedGroupV2Context.getChange(); DecryptedGroupChange groupChange = decryptedGroupV2Context.getChange();
return Stream.of(DecryptedGroupUtil.membersToServiceIdList(groupState.getMembersList()), return Stream.of(DecryptedGroupUtil.toAciList(groupState.getMembersList()),
DecryptedGroupUtil.pendingToServiceIdList(groupState.getPendingMembersList()), DecryptedGroupUtil.pendingToServiceIdList(groupState.getPendingMembersList()),
DecryptedGroupUtil.removedMembersServiceIdList(groupChange), DecryptedGroupUtil.removedMembersServiceIdList(groupChange),
DecryptedGroupUtil.removedPendingMembersServiceIdList(groupChange), DecryptedGroupUtil.removedPendingMembersServiceIdList(groupChange),
@ -190,7 +188,7 @@ public final class MessageGroupContext {
List<RecipientId> members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount()); List<RecipientId> members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount());
for (DecryptedMember member : decryptedGroupV2Context.getGroupState().getMembersList()) { for (DecryptedMember member : decryptedGroupV2Context.getGroupState().getMembersList()) {
RecipientId recipient = RecipientId.from(ServiceId.parseOrThrow(member.getUuid())); RecipientId recipient = RecipientId.from(ACI.parseOrThrow(member.getAciBytes()));
if (!Recipient.self().getId().equals(recipient)) { if (!Recipient.self().getId().equals(recipient)) {
members.add(recipient); members.add(recipient);
} }

View file

@ -7,6 +7,8 @@ import com.google.protobuf.ByteString;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.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.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import java.util.Optional; import java.util.Optional;
@ -37,7 +39,7 @@ public final class GroupV2UpdateMessageUtil {
private static boolean changeEditorOnlyWasRemoved(@NonNull DecryptedGroupChange decryptedGroupChange) { private static boolean changeEditorOnlyWasRemoved(@NonNull DecryptedGroupChange decryptedGroupChange) {
return decryptedGroupChange.getDeleteMembersCount() == 1 && return decryptedGroupChange.getDeleteMembersCount() == 1 &&
decryptedGroupChange.getDeleteMembers(0).equals(decryptedGroupChange.getEditor()); decryptedGroupChange.getDeleteMembers(0).equals(decryptedGroupChange.getEditorServiceIdBytes());
} }
private static boolean noChangesOtherThanDeletes(@NonNull DecryptedGroupChange decryptedGroupChange) { private static boolean noChangesOtherThanDeletes(@NonNull DecryptedGroupChange decryptedGroupChange) {
@ -65,9 +67,9 @@ public final class GroupV2UpdateMessageUtil {
return -1; return -1;
} }
public static Optional<ByteString> getChangeEditor(MessageGroupContext groupContext) { public static Optional<ServiceId> getChangeEditor(MessageGroupContext groupContext) {
if (isGroupV2(groupContext) && isUpdate(groupContext)) { if (isGroupV2(groupContext) && isUpdate(groupContext)) {
return Optional.ofNullable(groupContext.requireGroupV2Properties().getChange().getEditor()); return Optional.ofNullable(groupContext.requireGroupV2Properties().getChange().getEditorServiceIdBytes()).map(ServiceId::parseOrNull);
} }
return Optional.empty(); return Optional.empty();
} }

View file

@ -4,6 +4,8 @@ import com.google.protobuf.ByteString;
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context; import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
import org.thoughtcrime.securesms.mms.MessageGroupContext; import org.thoughtcrime.securesms.mms.MessageGroupContext;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import java.util.Optional; import java.util.Optional;
@ -52,7 +54,7 @@ public final class IncomingGroupUpdateMessage extends IncomingTextMessage {
return GroupV2UpdateMessageUtil.getChangeRevision(groupContext); return GroupV2UpdateMessageUtil.getChangeRevision(groupContext);
} }
public Optional<ByteString> getChangeEditor() { public Optional<ServiceId> getChangeEditor() {
return GroupV2UpdateMessageUtil.getChangeEditor(groupContext); return GroupV2UpdateMessageUtil.getChangeEditor(groupContext);
} }
} }

View file

@ -28,10 +28,10 @@ object GV2Transformer : ColumnTransformer {
} }
private fun DecryptedGroup.formatAsHtml(): String { private fun DecryptedGroup.formatAsHtml(): String {
val members: String = describeList(membersList, DecryptedMember::getUuid) val members: String = describeList(membersList, DecryptedMember::getAciBytes)
val pending: String = describeList(pendingMembersList, DecryptedPendingMember::getServiceIdBinary) val pending: String = describeList(pendingMembersList, DecryptedPendingMember::getServiceIdBytes)
val requesting: String = describeList(requestingMembersList, DecryptedRequestingMember::getUuid) val requesting: String = describeList(requestingMembersList, DecryptedRequestingMember::getAciBytes)
val banned: String = describeList(bannedMembersList, DecryptedBannedMember::getServiceIdBinary) val banned: String = describeList(bannedMembersList, DecryptedBannedMember::getServiceIdBytes)
return """ return """
Revision: $revision Revision: $revision

View file

@ -85,7 +85,7 @@ class GroupChangeData(private val revision: Int, private val groupOperations: Gr
} }
fun source(serviceId: ServiceId) { fun source(serviceId: ServiceId) {
actionsBuilder.sourceUuid = groupOperations.encryptServiceId(serviceId) actionsBuilder.sourceServiceId = groupOperations.encryptServiceId(serviceId)
} }
fun deleteMember(serviceId: ServiceId) { fun deleteMember(serviceId: ServiceId) {

View file

@ -57,9 +57,9 @@ import static java.util.Collections.singletonList;
@Config(manifest = Config.NONE, application = Application.class) @Config(manifest = Config.NONE, application = Application.class)
public final class GroupsV2UpdateMessageProducerTest { public final class GroupsV2UpdateMessageProducerTest {
private UUID you; private ACI you;
private UUID alice; private ACI alice;
private UUID bob; private ACI bob;
private GroupsV2UpdateMessageProducer producer; private GroupsV2UpdateMessageProducer producer;
@ -74,9 +74,9 @@ public final class GroupsV2UpdateMessageProducerTest {
@Before @Before
public void setup() { public void setup() {
you = UUID.randomUUID(); you = ACI.from(UUID.randomUUID());
alice = UUID.randomUUID(); alice = ACI.from(UUID.randomUUID());
bob = UUID.randomUUID(); bob = ACI.from(UUID.randomUUID());
recipientIdMockedStatic.when(() -> RecipientId.from(anyLong())).thenCallRealMethod(); recipientIdMockedStatic.when(() -> RecipientId.from(anyLong())).thenCallRealMethod();
@ -86,10 +86,10 @@ public final class GroupsV2UpdateMessageProducerTest {
Recipient aliceRecipient = recipientWithName(aliceId, "Alice"); Recipient aliceRecipient = recipientWithName(aliceId, "Alice");
Recipient bobRecipient = recipientWithName(bobId, "Bob"); Recipient bobRecipient = recipientWithName(bobId, "Bob");
producer = new GroupsV2UpdateMessageProducer(ApplicationProvider.getApplicationContext(), new ServiceIds(ACI.from(you), PNI.from(UUID.randomUUID())), null); producer = new GroupsV2UpdateMessageProducer(ApplicationProvider.getApplicationContext(), new ServiceIds(you, PNI.from(UUID.randomUUID())), null);
recipientIdMockedStatic.when(() -> RecipientId.from(ACI.from(alice))).thenReturn(aliceId); recipientIdMockedStatic.when(() -> RecipientId.from(alice)).thenReturn(aliceId);
recipientIdMockedStatic.when(() -> RecipientId.from(ACI.from(bob))).thenReturn(bobId); recipientIdMockedStatic.when(() -> RecipientId.from(bob)).thenReturn(bobId);
recipientMockedStatic.when(() -> Recipient.resolved(aliceId)).thenReturn(aliceRecipient); recipientMockedStatic.when(() -> Recipient.resolved(aliceId)).thenReturn(aliceRecipient);
recipientMockedStatic.when(() -> Recipient.resolved(bobId)).thenReturn(bobRecipient); recipientMockedStatic.when(() -> Recipient.resolved(bobId)).thenReturn(bobRecipient);
} }
@ -436,7 +436,7 @@ public final class GroupsV2UpdateMessageProducerTest {
public void member_invited_2_persons() { public void member_invited_2_persons() {
DecryptedGroupChange change = changeBy(alice) DecryptedGroupChange change = changeBy(alice)
.invite(bob) .invite(bob)
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(singletonList("Alice invited 2 people to the group."))); assertThat(describeChange(change), is(singletonList("Alice invited 2 people to the group.")));
@ -447,8 +447,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeBy(bob) DecryptedGroupChange change = changeBy(bob)
.invite(alice) .invite(alice)
.invite(you) .invite(you)
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(Arrays.asList("Bob invited you to the group.", "Bob invited 3 people to the group."))); assertThat(describeChange(change), is(Arrays.asList("Bob invited you to the group.", "Bob invited 3 people to the group.")));
@ -496,8 +496,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeByUnknown() DecryptedGroupChange change = changeByUnknown()
.invite(alice) .invite(alice)
.invite(you) .invite(you)
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(Arrays.asList("You were invited to the group.", "3 people were invited to the group."))); assertThat(describeChange(change), is(Arrays.asList("You were invited to the group.", "3 people were invited to the group.")));
@ -508,8 +508,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeByUnknown() DecryptedGroupChange change = changeByUnknown()
.invite(alice) .invite(alice)
.inviteBy(you, bob) .inviteBy(you, bob)
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(Arrays.asList("Bob invited you to the group.", "3 people were invited to the group."))); assertThat(describeChange(change), is(Arrays.asList("Bob invited you to the group.", "3 people were invited to the group.")));
@ -520,8 +520,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeBy(bob) DecryptedGroupChange change = changeBy(bob)
.addMember(alice) .addMember(alice)
.invite(you) .invite(you)
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.invite(UUID.randomUUID()) .invite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(Arrays.asList("Bob invited you to the group.", "Bob added Alice.", "Bob invited 2 people to the group."))); assertThat(describeChange(change), is(Arrays.asList("Bob invited you to the group.", "Bob added Alice.", "Bob invited 2 people to the group.")));
@ -562,7 +562,7 @@ public final class GroupsV2UpdateMessageProducerTest {
public void member_uninvited_2_people() { public void member_uninvited_2_people() {
DecryptedGroupChange change = changeBy(alice) DecryptedGroupChange change = changeBy(alice)
.uninvite(bob) .uninvite(bob)
.uninvite(UUID.randomUUID()) .uninvite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(singletonList("Alice revoked 2 invitations to the group."))); assertThat(describeChange(change), is(singletonList("Alice revoked 2 invitations to the group.")));
@ -581,7 +581,7 @@ public final class GroupsV2UpdateMessageProducerTest {
public void you_uninvited_2_people() { public void you_uninvited_2_people() {
DecryptedGroupChange change = changeBy(you) DecryptedGroupChange change = changeBy(you)
.uninvite(bob) .uninvite(bob)
.uninvite(UUID.randomUUID()) .uninvite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(singletonList("You revoked 2 invitations to the group."))); assertThat(describeChange(change), is(singletonList("You revoked 2 invitations to the group.")));
@ -627,7 +627,7 @@ public final class GroupsV2UpdateMessageProducerTest {
public void unknown_revokes_2_invites() { public void unknown_revokes_2_invites() {
DecryptedGroupChange change = changeByUnknown() DecryptedGroupChange change = changeByUnknown()
.uninvite(bob) .uninvite(bob)
.uninvite(UUID.randomUUID()) .uninvite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(singletonList("2 invitations to the group were revoked."))); assertThat(describeChange(change), is(singletonList("2 invitations to the group were revoked.")));
@ -638,8 +638,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeByUnknown() DecryptedGroupChange change = changeByUnknown()
.uninvite(bob) .uninvite(bob)
.uninvite(you) .uninvite(you)
.uninvite(UUID.randomUUID()) .uninvite(ACI.from(UUID.randomUUID()))
.uninvite(UUID.randomUUID()) .uninvite(ACI.from(UUID.randomUUID()))
.build(); .build();
assertThat(describeChange(change), is(Arrays.asList("An admin revoked your invitation to the group.", "3 invitations to the group were revoked."))); assertThat(describeChange(change), is(Arrays.asList("An admin revoked your invitation to the group.", "3 invitations to the group were revoked.")));
@ -993,7 +993,7 @@ public final class GroupsV2UpdateMessageProducerTest {
assertEquals("The admin approval for the group link has been turned on.", describeGroupLinkChange(null, AccessControl.AccessRequired.ANY, AccessControl.AccessRequired.ADMINISTRATOR)); assertEquals("The admin approval for the group link has been turned on.", describeGroupLinkChange(null, AccessControl.AccessRequired.ANY, AccessControl.AccessRequired.ADMINISTRATOR));
} }
private String describeGroupLinkChange(@Nullable UUID editor, @NonNull AccessControl.AccessRequired fromAccess, AccessControl.AccessRequired toAccess){ private String describeGroupLinkChange(@Nullable ACI editor, @NonNull AccessControl.AccessRequired fromAccess, AccessControl.AccessRequired toAccess){
DecryptedGroup previousGroupState = DecryptedGroup.newBuilder() DecryptedGroup previousGroupState = DecryptedGroup.newBuilder()
.setAccessControl(AccessControl.newBuilder() .setAccessControl(AccessControl.newBuilder()
.setAddFromInviteLink(fromAccess)) .setAddFromInviteLink(fromAccess))
@ -1441,12 +1441,12 @@ public final class GroupsV2UpdateMessageProducerTest {
return producer.describeNewGroup(group, groupChange).getSpannable().toString(); return producer.describeNewGroup(group, groupChange).getSpannable().toString();
} }
private static GroupStateBuilder newGroupBy(UUID foundingMember, int revision) { private static GroupStateBuilder newGroupBy(ACI foundingMember, int revision) {
return new GroupStateBuilder(foundingMember, revision); return new GroupStateBuilder(foundingMember, revision);
} }
private void assertSingleChangeMentioning(DecryptedGroupChange change, List<UUID> expectedMentions) { private void assertSingleChangeMentioning(DecryptedGroupChange change, List<ACI> expectedMentions) {
List<ServiceId> expectedMentionSids = expectedMentions.stream().map(ACI::from).collect(Collectors.toList()); List<ServiceId> expectedMentionSids = expectedMentions.stream().collect(Collectors.toList());
List<UpdateDescription> changes = producer.describeChanges(null, change); List<UpdateDescription> changes = producer.describeChanges(null, change);
@ -1466,23 +1466,23 @@ public final class GroupsV2UpdateMessageProducerTest {
private final DecryptedGroup.Builder builder; private final DecryptedGroup.Builder builder;
GroupStateBuilder(@NonNull UUID foundingMember, int revision) { GroupStateBuilder(@NonNull ACI foundingMember, int revision) {
builder = DecryptedGroup.newBuilder() builder = DecryptedGroup.newBuilder()
.setRevision(revision) .setRevision(revision)
.addMembers(DecryptedMember.newBuilder() .addMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(foundingMember))); .setAciBytes(foundingMember.toByteString()));
} }
GroupStateBuilder invite(@NonNull UUID inviter, @NonNull UUID invitee) { GroupStateBuilder invite(@NonNull ACI inviter, @NonNull ServiceId invitee) {
builder.addPendingMembers(DecryptedPendingMember.newBuilder() builder.addPendingMembers(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(invitee)) .setServiceIdBytes(invitee.toByteString())
.setAddedByUuid(UuidUtil.toByteString(inviter))); .setAddedByAci(inviter.toByteString()));
return this; return this;
} }
GroupStateBuilder member(@NonNull UUID member) { GroupStateBuilder member(@NonNull ACI member) {
builder.addMembers(DecryptedMember.newBuilder() builder.addMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(member))); .setAciBytes(member.toByteString()));
return this; return this;
} }

View file

@ -9,7 +9,7 @@ import org.mockito.kotlin.mock
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.util.Base64 import org.thoughtcrime.securesms.util.Base64
import org.whispersystems.signalservice.api.util.UuidUtil import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.internal.push.SignalServiceProtos import org.whispersystems.signalservice.internal.push.SignalServiceProtos
import java.util.Random import java.util.Random
import java.util.UUID import java.util.UUID
@ -48,8 +48,8 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
*/ */
@Test @Test
fun appendDeleteToExistingContext() { fun appendDeleteToExistingContext() {
val alice = UUID.randomUUID() val alice = ACI.from(UUID.randomUUID())
val aliceByteString = UuidUtil.toByteString(alice) val aliceByteString = alice.toByteString()
val change = ChangeBuilder.changeBy(alice) val change = ChangeBuilder.changeBy(alice)
.requestJoin(alice) .requestJoin(alice)
.build() .build()
@ -71,7 +71,7 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
val newContext = DecryptedGroupV2Context.parseFrom(Base64.decode(newEncodedBody)) val newContext = DecryptedGroupV2Context.parseFrom(Base64.decode(newEncodedBody))
assertThat("revision updated to 10", newContext.change.revision, `is`(10)) assertThat("revision updated to 10", newContext.change.revision, `is`(10))
assertThat("change should retain join request", newContext.change.newRequestingMembersList[0].uuid, `is`(aliceByteString)) assertThat("change should retain join request", newContext.change.newRequestingMembersList[0].aciBytes, `is`(aliceByteString))
assertThat("change should add delete request", newContext.change.deleteRequestingMembersList[0], `is`(aliceByteString)) assertThat("change should add delete request", newContext.change.deleteRequestingMembersList[0], `is`(aliceByteString))
} }

View file

@ -151,8 +151,8 @@ class GroupManagerV2Test_edit {
then { patchedGroup -> then { patchedGroup ->
assertThat("Revision updated by one", patchedGroup.revision, `is`(6)) assertThat("Revision updated by one", patchedGroup.revision, `is`(6))
assertThat("Self is no longer in the group", patchedGroup.membersList.find { it.uuid == selfAci.toByteString() }, Matchers.nullValue()) assertThat("Self is no longer in the group", patchedGroup.membersList.find { it.aciBytes == selfAci.toByteString() }, Matchers.nullValue())
assertThat("Other is now an admin in the group", patchedGroup.membersList.find { it.uuid == otherAci.toByteString() }?.role, `is`(Member.Role.ADMINISTRATOR)) assertThat("Other is now an admin in the group", patchedGroup.membersList.find { it.aciBytes == otherAci.toByteString() }?.role, `is`(Member.Role.ADMINISTRATOR))
} }
} }
} }

View file

@ -19,16 +19,14 @@ import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.protos.groups.local.DecryptedString;
import org.signal.storageservice.protos.groups.local.DecryptedTimer; import org.signal.storageservice.protos.groups.local.DecryptedTimer;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import java.util.UUID;
public final class ChangeBuilder { public final class ChangeBuilder {
private final DecryptedGroupChange.Builder builder; private final DecryptedGroupChange.Builder builder;
@Nullable private final UUID editor; @Nullable private final ACI editor;
public static ChangeBuilder changeBy(@NonNull UUID editor) { public static ChangeBuilder changeBy(@NonNull ACI editor) {
return new ChangeBuilder(editor); return new ChangeBuilder(editor);
} }
@ -36,10 +34,10 @@ public final class ChangeBuilder {
return new ChangeBuilder(); return new ChangeBuilder();
} }
ChangeBuilder(@NonNull UUID editor) { ChangeBuilder(@NonNull ACI editor) {
this.editor = editor; this.editor = editor;
this.builder = DecryptedGroupChange.newBuilder() this.builder = DecryptedGroupChange.newBuilder()
.setEditor(UuidUtil.toByteString(editor)); .setEditorServiceIdBytes(editor.toByteString());
} }
ChangeBuilder() { ChangeBuilder() {
@ -47,74 +45,74 @@ public final class ChangeBuilder {
this.builder = DecryptedGroupChange.newBuilder(); this.builder = DecryptedGroupChange.newBuilder();
} }
public ChangeBuilder addMember(@NonNull UUID newMember) { public ChangeBuilder addMember(@NonNull ACI newMember) {
builder.addNewMembers(DecryptedMember.newBuilder() builder.addNewMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMember))); .setAciBytes(newMember.toByteString()));
return this; return this;
} }
public ChangeBuilder addMember(@NonNull UUID newMember, @NonNull ProfileKey profileKey) { public ChangeBuilder addMember(@NonNull ACI newMember, @NonNull ProfileKey profileKey) {
builder.addNewMembers(DecryptedMember.newBuilder() builder.addNewMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMember)) .setAciBytes(newMember.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))); .setProfileKey(ByteString.copyFrom(profileKey.serialize())));
return this; return this;
} }
public ChangeBuilder deleteMember(@NonNull UUID removedMember) { public ChangeBuilder deleteMember(@NonNull ACI removedMember) {
builder.addDeleteMembers(UuidUtil.toByteString(removedMember)); builder.addDeleteMembers(removedMember.toByteString());
return this; return this;
} }
public ChangeBuilder promoteToAdmin(@NonNull UUID member) { public ChangeBuilder promoteToAdmin(@NonNull ACI member) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.setUuid(UuidUtil.toByteString(member))); .setAciBytes(member.toByteString()));
return this; return this;
} }
public ChangeBuilder demoteToMember(@NonNull UUID member) { public ChangeBuilder demoteToMember(@NonNull ACI member) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setUuid(UuidUtil.toByteString(member))); .setAciBytes(member.toByteString()));
return this; return this;
} }
public ChangeBuilder invite(@NonNull UUID potentialMember) { public ChangeBuilder invite(@NonNull ACI potentialMember) {
return inviteBy(potentialMember, UuidUtil.UNKNOWN_UUID); return inviteBy(potentialMember, ACI.UNKNOWN);
} }
public ChangeBuilder inviteBy(@NonNull UUID potentialMember, @NonNull UUID inviter) { public ChangeBuilder inviteBy(@NonNull ACI potentialMember, @NonNull ACI inviter) {
builder.addNewPendingMembers(DecryptedPendingMember.newBuilder() builder.addNewPendingMembers(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(potentialMember)) .setServiceIdBytes(potentialMember.toByteString())
.setAddedByUuid(UuidUtil.toByteString(inviter))); .setAddedByAci(inviter.toByteString()));
return this; return this;
} }
public ChangeBuilder uninvite(@NonNull UUID pendingMember) { public ChangeBuilder uninvite(@NonNull ACI pendingMember) {
builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(pendingMember))); .setServiceIdBytes(pendingMember.toByteString()));
return this; return this;
} }
public ChangeBuilder promote(@NonNull UUID pendingMember) { public ChangeBuilder promote(@NonNull ACI pendingMember) {
builder.addPromotePendingMembers(DecryptedMember.newBuilder().setUuid(UuidUtil.toByteString(pendingMember))); builder.addPromotePendingMembers(DecryptedMember.newBuilder().setAciBytes(pendingMember.toByteString()));
return this; return this;
} }
public ChangeBuilder profileKeyUpdate(@NonNull UUID member, @NonNull ProfileKey profileKey) { public ChangeBuilder profileKeyUpdate(@NonNull ACI member, @NonNull ProfileKey profileKey) {
return profileKeyUpdate(member, profileKey.serialize()); return profileKeyUpdate(member, profileKey.serialize());
} }
public ChangeBuilder profileKeyUpdate(@NonNull UUID member, @NonNull byte[] profileKey) { public ChangeBuilder profileKeyUpdate(@NonNull ACI member, @NonNull byte[] profileKey) {
builder.addModifiedProfileKeys(DecryptedMember.newBuilder() builder.addModifiedProfileKeys(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(member)) .setAciBytes(member.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey))); .setProfileKey(ByteString.copyFrom(profileKey)));
return this; return this;
} }
public ChangeBuilder promote(@NonNull UUID pendingMember, @NonNull ProfileKey profileKey) { public ChangeBuilder promote(@NonNull ACI pendingMember, @NonNull ProfileKey profileKey) {
builder.addPromotePendingMembers(DecryptedMember.newBuilder() builder.addPromotePendingMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(pendingMember)) .setAciBytes(pendingMember.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))); .setProfileKey(ByteString.copyFrom(profileKey.serialize())));
return this; return this;
} }
@ -162,7 +160,7 @@ public final class ChangeBuilder {
return requestJoin(editor, newProfileKey()); return requestJoin(editor, newProfileKey());
} }
public ChangeBuilder requestJoin(@NonNull UUID requester) { public ChangeBuilder requestJoin(@NonNull ACI requester) {
return requestJoin(requester, newProfileKey()); return requestJoin(requester, newProfileKey());
} }
@ -171,22 +169,22 @@ public final class ChangeBuilder {
return requestJoin(editor, profileKey); return requestJoin(editor, profileKey);
} }
public ChangeBuilder requestJoin(@NonNull UUID requester, @NonNull ProfileKey profileKey) { public ChangeBuilder requestJoin(@NonNull ACI requester, @NonNull ProfileKey profileKey) {
builder.addNewRequestingMembers(DecryptedRequestingMember.newBuilder() builder.addNewRequestingMembers(DecryptedRequestingMember.newBuilder()
.setUuid(UuidUtil.toByteString(requester)) .setAciBytes(requester.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))); .setProfileKey(ByteString.copyFrom(profileKey.serialize())));
return this; return this;
} }
public ChangeBuilder approveRequest(@NonNull UUID approvedMember) { public ChangeBuilder approveRequest(@NonNull ACI approvedMember) {
builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setUuid(UuidUtil.toByteString(approvedMember))); .setAciBytes(approvedMember.toByteString()));
return this; return this;
} }
public ChangeBuilder denyRequest(@NonNull UUID approvedMember) { public ChangeBuilder denyRequest(@NonNull ACI approvedMember) {
builder.addDeleteRequestingMembers(UuidUtil.toByteString(approvedMember)); builder.addDeleteRequestingMembers(approvedMember.toByteString());
return this; return this;
} }

View file

@ -22,7 +22,7 @@ public final class ProfileKeySetTest {
@Test @Test
public void empty_change() { public void empty_change() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).build());
@ -33,95 +33,95 @@ public final class ProfileKeySetTest {
@Test @Test
public void new_member_is_not_authoritative() { public void new_member_is_not_authoritative() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID newMember = UUID.randomUUID(); ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).addMember(newMember, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).addMember(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty()); assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey))); assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
} }
@Test @Test
public void new_member_by_self_is_authoritative() { public void new_member_by_self_is_authoritative() {
UUID newMember = UUID.randomUUID(); ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(newMember).addMember(newMember, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(newMember).addMember(newMember, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty()); assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey))); assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
} }
@Test @Test
public void new_member_by_self_promote_is_authoritative() { public void new_member_by_self_promote_is_authoritative() {
UUID newMember = UUID.randomUUID(); ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(newMember).promote(newMember, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(newMember).promote(newMember, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty()); assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey))); assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
} }
@Test @Test
public void new_member_by_promote_by_other_editor_is_not_authoritative() { public void new_member_by_promote_by_other_editor_is_not_authoritative() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID newMember = UUID.randomUUID(); ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).promote(newMember, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).promote(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty()); assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey))); assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
} }
@Test @Test
public void new_member_by_promote_by_unknown_editor_is_not_authoritative() { public void new_member_by_promote_by_unknown_editor_is_not_authoritative() {
UUID newMember = UUID.randomUUID(); ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeByUnknown().promote(newMember, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeByUnknown().promote(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty()); assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey))); assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
} }
@Test @Test
public void profile_key_update_by_self_is_authoritative() { public void profile_key_update_by_self_is_authoritative() {
UUID member = UUID.randomUUID(); ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty()); assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey))); assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey)));
} }
@Test @Test
public void profile_key_update_by_another_is_not_authoritative() { public void profile_key_update_by_another_is_not_authoritative() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID member = UUID.randomUUID(); ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty()); assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey))); assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(member, profileKey)));
} }
@Test @Test
public void multiple_updates_overwrite() { public void multiple_updates_overwrite() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID member = UUID.randomUUID(); ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey1 = ProfileKeyUtil.createNew(); ProfileKey profileKey1 = ProfileKeyUtil.createNew();
ProfileKey profileKey2 = ProfileKeyUtil.createNew(); ProfileKey profileKey2 = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
@ -130,13 +130,13 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty()); assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey2))); assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(member, profileKey2)));
} }
@Test @Test
public void authoritative_takes_priority_when_seen_first() { public void authoritative_takes_priority_when_seen_first() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID member = UUID.randomUUID(); ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey1 = ProfileKeyUtil.createNew(); ProfileKey profileKey1 = ProfileKeyUtil.createNew();
ProfileKey profileKey2 = ProfileKeyUtil.createNew(); ProfileKey profileKey2 = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
@ -145,13 +145,13 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty()); assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey1))); assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey1)));
} }
@Test @Test
public void authoritative_takes_priority_when_seen_second() { public void authoritative_takes_priority_when_seen_second() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID member = UUID.randomUUID(); ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey1 = ProfileKeyUtil.createNew(); ProfileKey profileKey1 = ProfileKeyUtil.createNew();
ProfileKey profileKey2 = ProfileKeyUtil.createNew(); ProfileKey profileKey2 = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
@ -160,14 +160,14 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey2).build()); profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty()); assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey2))); assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey2)));
} }
@Test @Test
public void bad_profile_key() { public void bad_profile_key() {
LogRecorder logRecorder = new LogRecorder(); LogRecorder logRecorder = new LogRecorder();
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID member = UUID.randomUUID(); ACI member = ACI.from(UUID.randomUUID());
byte[] badProfileKey = new byte[10]; byte[] badProfileKey = new byte[10];
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
@ -181,26 +181,26 @@ public final class ProfileKeySetTest {
@Test @Test
public void new_requesting_member_if_editor_is_authoritative() { public void new_requesting_member_if_editor_is_authoritative() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(profileKey).build());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(editor), profileKey))); assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(editor, profileKey)));
assertTrue(profileKeySet.getProfileKeys().isEmpty()); assertTrue(profileKeySet.getProfileKeys().isEmpty());
} }
@Test @Test
public void new_requesting_member_if_not_editor_is_not_authoritative() { public void new_requesting_member_if_not_editor_is_not_authoritative() {
UUID editor = UUID.randomUUID(); ACI editor = ACI.from(UUID.randomUUID());
UUID requesting = UUID.randomUUID(); ACI requesting = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew(); ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet(); ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(requesting, profileKey).build()); profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(requesting, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty()); assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(requesting), profileKey))); assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(requesting, profileKey)));
} }
} }

View file

@ -8,6 +8,8 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedString; import org.signal.storageservice.protos.groups.local.DecryptedString;
import org.thoughtcrime.securesms.testutil.LogRecorder; import org.thoughtcrime.securesms.testutil.LogRecorder;
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.api.util.UuidUtil;
import java.util.UUID; import java.util.UUID;
@ -261,7 +263,7 @@ public final class GroupStateMapperTest {
DecryptedGroup currentState = state(6); DecryptedGroup currentState = state(6);
ServerGroupLogEntry log7 = serverLogEntry(7); ServerGroupLogEntry log7 = serverLogEntry(7);
DecryptedMember newMember = DecryptedMember.newBuilder() DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID())) .setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build(); .build();
DecryptedGroup state7b = DecryptedGroup.newBuilder() DecryptedGroup state7b = DecryptedGroup.newBuilder()
.setRevision(8) .setRevision(8)
@ -323,12 +325,12 @@ public final class GroupStateMapperTest {
@Test @Test
public void clears_changes_duplicated_in_the_placeholder() { public void clears_changes_duplicated_in_the_placeholder() {
UUID newMemberUuid = UUID.randomUUID(); ACI newMemberAci = ACI.from(UUID.randomUUID());
DecryptedMember newMember = DecryptedMember.newBuilder() DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMemberUuid)) .setAciBytes(newMemberAci.toByteString())
.build(); .build();
DecryptedMember existingMember = DecryptedMember.newBuilder() DecryptedMember existingMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID())) .setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build(); .build();
DecryptedGroup currentState = DecryptedGroup.newBuilder() DecryptedGroup currentState = DecryptedGroup.newBuilder()
.setRevision(GroupStateMapper.PLACEHOLDER_REVISION) .setRevision(GroupStateMapper.PLACEHOLDER_REVISION)
@ -343,7 +345,7 @@ public final class GroupStateMapperTest {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(8) .setRevision(8)
.setEditor(UuidUtil.toByteString(newMemberUuid)) .setEditorServiceIdBytes(newMemberAci.toByteString())
.addNewMembers(newMember) .addNewMembers(newMember)
.build()); .build());
@ -357,13 +359,13 @@ public final class GroupStateMapperTest {
@Test @Test
public void clears_changes_duplicated_in_a_non_placeholder() { public void clears_changes_duplicated_in_a_non_placeholder() {
UUID editorUuid = UUID.randomUUID(); ACI editorAci = ACI.from(UUID.randomUUID());
UUID newMemberUuid = UUID.randomUUID(); ACI newMemberAci = ACI.from(UUID.randomUUID());
DecryptedMember newMember = DecryptedMember.newBuilder() DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMemberUuid)) .setAciBytes(newMemberAci.toByteString())
.build(); .build();
DecryptedMember existingMember = DecryptedMember.newBuilder() DecryptedMember existingMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID())) .setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build(); .build();
DecryptedGroup currentState = DecryptedGroup.newBuilder() DecryptedGroup currentState = DecryptedGroup.newBuilder()
.setRevision(8) .setRevision(8)
@ -378,14 +380,14 @@ public final class GroupStateMapperTest {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(8) .setRevision(8)
.setEditor(UuidUtil.toByteString(editorUuid)) .setEditorServiceIdBytes(editorAci.toByteString())
.addNewMembers(existingMember) .addNewMembers(existingMember)
.addNewMembers(newMember) .addNewMembers(newMember)
.build()); .build());
DecryptedGroupChange expectedChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange expectedChange = DecryptedGroupChange.newBuilder()
.setRevision(8) .setRevision(8)
.setEditor(UuidUtil.toByteString(editorUuid)) .setEditorServiceIdBytes(editorAci.toByteString())
.addNewMembers(newMember) .addNewMembers(newMember)
.build(); .build();
@ -399,12 +401,12 @@ public final class GroupStateMapperTest {
@Test @Test
public void notices_changes_in_avatar_and_title_but_not_members_in_placeholder() { public void notices_changes_in_avatar_and_title_but_not_members_in_placeholder() {
UUID newMemberUuid = UUID.randomUUID(); ACI newMemberAci = ACI.from(UUID.randomUUID());
DecryptedMember newMember = DecryptedMember.newBuilder() DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMemberUuid)) .setAciBytes(newMemberAci.toByteString())
.build(); .build();
DecryptedMember existingMember = DecryptedMember.newBuilder() DecryptedMember existingMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID())) .setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build(); .build();
DecryptedGroup currentState = DecryptedGroup.newBuilder() DecryptedGroup currentState = DecryptedGroup.newBuilder()
.setRevision(GroupStateMapper.PLACEHOLDER_REVISION) .setRevision(GroupStateMapper.PLACEHOLDER_REVISION)
@ -421,7 +423,7 @@ public final class GroupStateMapperTest {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(8) .setRevision(8)
.setEditor(UuidUtil.toByteString(newMemberUuid)) .setEditorServiceIdBytes(newMemberAci.toByteString())
.addNewMembers(newMember) .addNewMembers(newMember)
.build()); .build());
@ -448,7 +450,7 @@ public final class GroupStateMapperTest {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(2) .setRevision(2)
.setEditor(UuidUtil.toByteString(KNOWN_EDITOR)) .setEditorServiceIdBytes(UuidUtil.toByteString(KNOWN_EDITOR))
.setNewTitle(DecryptedString.newBuilder().setValue(log1.getGroup().getTitle())) .setNewTitle(DecryptedString.newBuilder().setValue(log1.getGroup().getTitle()))
.build()); .build());
@ -457,7 +459,7 @@ public final class GroupStateMapperTest {
assertThat(advanceGroupStateResult.getProcessedLogEntries(), is(asList(asLocal(log1), assertThat(advanceGroupStateResult.getProcessedLogEntries(), is(asList(asLocal(log1),
new LocalGroupLogEntry(log2.getGroup(), DecryptedGroupChange.newBuilder() new LocalGroupLogEntry(log2.getGroup(), DecryptedGroupChange.newBuilder()
.setRevision(2) .setRevision(2)
.setEditor(UuidUtil.toByteString(KNOWN_EDITOR)) .setEditorServiceIdBytes(UuidUtil.toByteString(KNOWN_EDITOR))
.build())))); .build()))));
assertTrue(advanceGroupStateResult.getNewGlobalGroupState().getServerHistory().isEmpty()); assertTrue(advanceGroupStateResult.getNewGlobalGroupState().getServerHistory().isEmpty());
assertEquals(log2.getGroup(), advanceGroupStateResult.getNewGlobalGroupState().getLocalState()); assertEquals(log2.getGroup(), advanceGroupStateResult.getNewGlobalGroupState().getLocalState());
@ -494,7 +496,7 @@ public final class GroupStateMapperTest {
private static DecryptedGroupChange change(int revision) { private static DecryptedGroupChange change(int revision) {
return DecryptedGroupChange.newBuilder() return DecryptedGroupChange.newBuilder()
.setRevision(revision) .setRevision(revision)
.setEditor(UuidUtil.toByteString(KNOWN_EDITOR)) .setEditorServiceIdBytes(UuidUtil.toByteString(KNOWN_EDITOR))
.setNewTitle(DecryptedString.newBuilder().setValue("Group Revision " + revision)) .setNewTitle(DecryptedString.newBuilder().setValue("Group Revision " + revision))
.build(); .build();
} }

View file

@ -428,7 +428,7 @@ class GroupsV2StateProcessorTest {
} }
changeLog(101) { changeLog(101) {
change { change {
addDeleteMembers(randomMembers[1].uuid) addDeleteMembers(randomMembers[1].aciBytes)
addModifiedProfileKeys(randomMembers[0]) addModifiedProfileKeys(randomMembers[0])
} }
} }
@ -449,7 +449,7 @@ class GroupsV2StateProcessorTest {
} }
changeLog(101) { changeLog(101) {
change { change {
addDeleteMembers(randomMembers[1].uuid) addDeleteMembers(randomMembers[1].aciBytes)
addModifiedProfileKeys(randomMembers[0]) addModifiedProfileKeys(randomMembers[0])
} }
} }

View file

@ -9,6 +9,8 @@ import org.signal.storageservice.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;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos; import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import java.util.Random; import java.util.Random;
@ -22,7 +24,7 @@ public class GroupV2UpdateMessageUtilTest {
@Test @Test
public void isJustAGroupLeave_whenEditorIsRemoved_shouldReturnTrue() { public void isJustAGroupLeave_whenEditorIsRemoved_shouldReturnTrue() {
// GIVEN // GIVEN
UUID alice = UUID.randomUUID(); ACI alice = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice) DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(alice) .deleteMember(alice)
.build(); .build();
@ -45,8 +47,8 @@ public class GroupV2UpdateMessageUtilTest {
@Test @Test
public void isJustAGroupLeave_whenOtherIsRemoved_shouldReturnFalse() { public void isJustAGroupLeave_whenOtherIsRemoved_shouldReturnFalse() {
// GIVEN // GIVEN
UUID alice = UUID.randomUUID(); ACI alice = ACI.from(UUID.randomUUID());
UUID bob = UUID.randomUUID(); ACI bob = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice) DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(bob) .deleteMember(bob)
.build(); .build();
@ -69,8 +71,8 @@ public class GroupV2UpdateMessageUtilTest {
@Test @Test
public void isJustAGroupLeave_whenEditorIsRemovedAndOtherChanges_shouldReturnFalse() { public void isJustAGroupLeave_whenEditorIsRemovedAndOtherChanges_shouldReturnFalse() {
// GIVEN // GIVEN
UUID alice = UUID.randomUUID(); ACI alice = ACI.from(UUID.randomUUID());
UUID bob = UUID.randomUUID(); ACI bob = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice) DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(alice) .deleteMember(alice)
.addMember(bob) .addMember(bob)
@ -94,7 +96,7 @@ public class GroupV2UpdateMessageUtilTest {
@Test @Test
public void isJoinRequestCancel_whenChangeRemovesRequestingMembers_shouldReturnTrue() { public void isJoinRequestCancel_whenChangeRemovesRequestingMembers_shouldReturnTrue() {
// GIVEN // GIVEN
UUID alice = UUID.randomUUID(); ACI alice = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice) DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.denyRequest(alice) .denyRequest(alice)
.build(); .build();
@ -117,8 +119,8 @@ public class GroupV2UpdateMessageUtilTest {
@Test @Test
public void isJoinRequestCancel_whenChangeContainsNoRemoveRequestingMembers_shouldReturnFalse() { public void isJoinRequestCancel_whenChangeContainsNoRemoveRequestingMembers_shouldReturnFalse() {
// GIVEN // GIVEN
UUID alice = UUID.randomUUID(); ACI alice = ACI.from(UUID.randomUUID());
UUID bob = UUID.randomUUID(); ACI bob = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice) DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(alice) .deleteMember(alice)
.addMember(bob) .addMember(bob)

View file

@ -21,7 +21,7 @@ fun groupContext(masterKey: GroupMasterKey, init: DecryptedGroupV2Context.Builde
fun groupChange(editor: ServiceId, init: DecryptedGroupChange.Builder.() -> Unit): DecryptedGroupChange { fun groupChange(editor: ServiceId, init: DecryptedGroupChange.Builder.() -> Unit): DecryptedGroupChange {
val builder = DecryptedGroupChange.newBuilder() val builder = DecryptedGroupChange.newBuilder()
builder.editor = editor.toByteString() builder.editorServiceIdBytes = editor.toByteString()
builder.init() builder.init()
return builder.build() return builder.build()
} }
@ -49,19 +49,19 @@ fun member(serviceId: UUID, role: Member.Role = Member.Role.DEFAULT, joinedAt: I
fun member(aci: ACI, role: Member.Role = Member.Role.DEFAULT, joinedAt: Int = 0): DecryptedMember { fun member(aci: ACI, role: Member.Role = Member.Role.DEFAULT, joinedAt: Int = 0): DecryptedMember {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setRole(role) .setRole(role)
.setUuid(aci.toByteString()) .setAciBytes(aci.toByteString())
.setJoinedAtRevision(joinedAt) .setJoinedAtRevision(joinedAt)
.build() .build()
} }
fun requestingMember(serviceId: ServiceId): DecryptedRequestingMember { fun requestingMember(serviceId: ServiceId): DecryptedRequestingMember {
return DecryptedRequestingMember.newBuilder() return DecryptedRequestingMember.newBuilder()
.setUuid(serviceId.toByteString()) .setAciBytes(serviceId.toByteString())
.build() .build()
} }
fun pendingMember(serviceId: ServiceId): DecryptedPendingMember { fun pendingMember(serviceId: ServiceId): DecryptedPendingMember {
return DecryptedPendingMember.newBuilder() return DecryptedPendingMember.newBuilder()
.setServiceIdBinary(serviceId.toByteString()) .setServiceIdBytes(serviceId.toByteString())
.build() .build()
} }

View file

@ -103,7 +103,7 @@ final class DecryptedGroupChangeActionsBuilderChangeSetModifier implements Chang
result.removeNewRequestingMembers(i); result.removeNewRequestingMembers(i);
DecryptedMember build = DecryptedMember.newBuilder() DecryptedMember build = DecryptedMember.newBuilder()
.setUuid(addMemberAction.getUuid()) .setAciBytes(addMemberAction.getAciBytes())
.setProfileKey(addMemberAction.getProfileKey()) .setProfileKey(addMemberAction.getProfileKey())
.setRole(Member.Role.DEFAULT).build(); .setRole(Member.Role.DEFAULT).build();

View file

@ -0,0 +1,33 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.api.groupsv2
import org.signal.storageservice.protos.groups.local.DecryptedMember
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import java.util.Optional
fun Collection<DecryptedMember>.toAciListWithUnknowns(): List<ACI> {
return DecryptedGroupUtil.toAciListWithUnknowns(this)
}
fun Collection<DecryptedMember>.toAciList(): List<ACI> {
return DecryptedGroupUtil.toAciList(this)
}
fun Collection<DecryptedMember>.findMemberByAci(aci: ACI): Optional<DecryptedMember> {
return DecryptedGroupUtil.findMemberByAci(this, aci)
}
fun Collection<DecryptedRequestingMember>.findRequestingByAci(aci: ACI): Optional<DecryptedRequestingMember> {
return DecryptedGroupUtil.findRequestingByAci(this, aci)
}
fun Collection<DecryptedPendingMember>.findPendingByServiceId(serviceId: ServiceId): Optional<DecryptedPendingMember> {
return DecryptedGroupUtil.findPendingByServiceId(this, serviceId)
}

View file

@ -16,8 +16,8 @@ import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemov
import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember; import org.signal.storageservice.protos.groups.local.DecryptedRequestingMember;
import org.signal.storageservice.protos.groups.local.EnabledState; import org.signal.storageservice.protos.groups.local.EnabledState;
import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceIds; import org.whispersystems.signalservice.api.push.ServiceIds;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -27,60 +27,58 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
public final class DecryptedGroupUtil { public final class DecryptedGroupUtil {
private static final String TAG = DecryptedGroupUtil.class.getSimpleName(); private static final String TAG = DecryptedGroupUtil.class.getSimpleName();
public static ArrayList<UUID> toUuidList(Collection<DecryptedMember> membersList) { public static ArrayList<ACI> toAciListWithUnknowns(Collection<DecryptedMember> membersList) {
ArrayList<UUID> uuidList = new ArrayList<>(membersList.size()); ArrayList<ACI> serviceIdList = new ArrayList<>(membersList.size());
for (DecryptedMember member : membersList) { for (DecryptedMember member : membersList) {
uuidList.add(toUuid(member)); serviceIdList.add(ACI.parseOrUnknown(member.getAciBytes()));
} }
return uuidList; return serviceIdList;
} }
public static ArrayList<ServiceId> membersToServiceIdList(Collection<DecryptedMember> membersList) { /** Converts the list of members to ACI's, filtering out unknown ACI's. */
ArrayList<ServiceId> serviceIdList = new ArrayList<>(membersList.size()); public static ArrayList<ACI> toAciList(Collection<DecryptedMember> membersList) {
ArrayList<ACI> serviceIdList = new ArrayList<>(membersList.size());
for (DecryptedMember member : membersList) { for (DecryptedMember member : membersList) {
ServiceId serviceId = ServiceId.parseOrNull(member.getUuid()); ACI aci = ACI.parseOrNull(member.getAciBytes());
if (serviceId != null) { if (aci != null) {
serviceIdList.add(serviceId); serviceIdList.add(aci);
} }
} }
return serviceIdList; return serviceIdList;
} }
public static Set<ByteString> membersToUuidByteStringSet(Collection<DecryptedMember> membersList) { public static Set<ByteString> membersToAciByteStringSet(Collection<DecryptedMember> membersList) {
Set<ByteString> uuidList = new HashSet<>(membersList.size()); Set<ByteString> aciList = new HashSet<>(membersList.size());
for (DecryptedMember member : membersList) { for (DecryptedMember member : membersList) {
uuidList.add(member.getUuid()); aciList.add(member.getAciBytes());
} }
return uuidList; return aciList;
} }
/** /**
* Can return non-decryptable member UUIDs as unknown ACIs. * Can return non-decryptable member ACIs as unknown ACIs.
*/ */
public static ArrayList<ServiceId> pendingToServiceIdList(Collection<DecryptedPendingMember> membersList) { public static ArrayList<ServiceId> pendingToServiceIdList(Collection<DecryptedPendingMember> membersList) {
ArrayList<ServiceId> serviceIdList = new ArrayList<>(membersList.size()); ArrayList<ServiceId> serviceIdList = new ArrayList<>(membersList.size());
for (DecryptedPendingMember member : membersList) { for (DecryptedPendingMember member : membersList) {
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary()); ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBytes());
if (serviceId != null) { if (serviceId != null) {
serviceIdList.add(serviceId); serviceIdList.add(serviceId);
} else { } else {
serviceIdList.add(ServiceId.ACI.UNKNOWN); serviceIdList.add(ACI.UNKNOWN);
} }
} }
@ -88,7 +86,7 @@ public final class DecryptedGroupUtil {
} }
/** /**
* Will not return any non-decryptable member UUIDs. * Will not return any non-decryptable member ACIs.
*/ */
public static ArrayList<ServiceId> removedMembersServiceIdList(DecryptedGroupChange groupChange) { public static ArrayList<ServiceId> removedMembersServiceIdList(DecryptedGroupChange groupChange) {
List<ByteString> deletedMembers = groupChange.getDeleteMembersList(); List<ByteString> deletedMembers = groupChange.getDeleteMembersList();
@ -106,14 +104,14 @@ public final class DecryptedGroupUtil {
} }
/** /**
* Will not return any non-decryptable member UUIDs. * Will not return any non-decryptable member ACIs.
*/ */
public static ArrayList<ServiceId> removedPendingMembersServiceIdList(DecryptedGroupChange groupChange) { public static ArrayList<ServiceId> removedPendingMembersServiceIdList(DecryptedGroupChange groupChange) {
List<DecryptedPendingMemberRemoval> deletedPendingMembers = groupChange.getDeletePendingMembersList(); List<DecryptedPendingMemberRemoval> deletedPendingMembers = groupChange.getDeletePendingMembersList();
ArrayList<ServiceId> serviceIdList = new ArrayList<>(deletedPendingMembers.size()); ArrayList<ServiceId> serviceIdList = new ArrayList<>(deletedPendingMembers.size());
for (DecryptedPendingMemberRemoval member : deletedPendingMembers) { for (DecryptedPendingMemberRemoval member : deletedPendingMembers) {
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary()); ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBytes());
if(serviceId != null) { if(serviceId != null) {
serviceIdList.add(serviceId); serviceIdList.add(serviceId);
@ -124,7 +122,7 @@ public final class DecryptedGroupUtil {
} }
/** /**
* Will not return any non-decryptable member UUIDs. * Will not return any non-decryptable member ACIs.
*/ */
public static ArrayList<ServiceId> removedRequestingMembersServiceIdList(DecryptedGroupChange groupChange) { public static ArrayList<ServiceId> removedRequestingMembersServiceIdList(DecryptedGroupChange groupChange) {
List<ByteString> deleteRequestingMembers = groupChange.getDeleteRequestingMembersList(); List<ByteString> deleteRequestingMembers = groupChange.getDeleteRequestingMembersList();
@ -145,7 +143,7 @@ public final class DecryptedGroupUtil {
Set<ServiceId> serviceIdSet = new HashSet<>(membersList.size()); Set<ServiceId> serviceIdSet = new HashSet<>(membersList.size());
for (DecryptedBannedMember member : membersList) { for (DecryptedBannedMember member : membersList) {
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary()); ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBytes());
if (serviceId != null) { if (serviceId != null) {
serviceIdSet.add(serviceId); serviceIdSet.add(serviceId);
} }
@ -154,26 +152,18 @@ public final class DecryptedGroupUtil {
return serviceIdSet; return serviceIdSet;
} }
public static UUID toUuid(DecryptedMember member) {
return toUuid(member.getUuid());
}
private static UUID toUuid(ByteString memberUuid) {
return UuidUtil.fromByteStringOrUnknown(memberUuid);
}
/** /**
* The UUID of the member that made the change. * The ACI of the member that made the change.
*/ */
public static Optional<UUID> editorUuid(DecryptedGroupChange change) { public static Optional<ServiceId> editorServiceId(DecryptedGroupChange change) {
return Optional.ofNullable(change != null ? UuidUtil.fromByteStringOrNull(change.getEditor()) : null); return Optional.ofNullable(change != null ? ServiceId.parseOrNull(change.getEditorServiceIdBytes()) : null);
} }
public static Optional<DecryptedMember> findMemberByUuid(Collection<DecryptedMember> members, UUID uuid) { public static Optional<DecryptedMember> findMemberByAci(Collection<DecryptedMember> members, ACI aci) {
ByteString uuidBytes = UuidUtil.toByteString(uuid); ByteString aciBytes = aci.toByteString();
for (DecryptedMember member : members) { for (DecryptedMember member : members) {
if (uuidBytes.equals(member.getUuid())) { if (aciBytes.equals(member.getAciBytes())) {
return Optional.of(member); return Optional.of(member);
} }
} }
@ -185,7 +175,7 @@ public final class DecryptedGroupUtil {
ByteString serviceIdBinary = serviceId.toByteString(); ByteString serviceIdBinary = serviceId.toByteString();
for (DecryptedPendingMember member : members) { for (DecryptedPendingMember member : members) {
if (serviceIdBinary.equals(member.getServiceIdBinary())) { if (serviceIdBinary.equals(member.getServiceIdBytes())) {
return Optional.of(member); return Optional.of(member);
} }
} }
@ -195,7 +185,7 @@ public final class DecryptedGroupUtil {
public static Optional<DecryptedPendingMember> findPendingByServiceIds(Collection<DecryptedPendingMember> members, ServiceIds serviceIds) { public static Optional<DecryptedPendingMember> findPendingByServiceIds(Collection<DecryptedPendingMember> members, ServiceIds serviceIds) {
for (DecryptedPendingMember member : members) { for (DecryptedPendingMember member : members) {
if (serviceIds.matches(member.getServiceIdBinary())) { if (serviceIds.matches(member.getServiceIdBytes())) {
return Optional.of(member); return Optional.of(member);
} }
} }
@ -203,10 +193,10 @@ public final class DecryptedGroupUtil {
return Optional.empty(); return Optional.empty();
} }
private static int findPendingIndexByUuidCipherText(List<DecryptedPendingMember> members, ByteString cipherText) { private static int findPendingIndexByServiceIdCipherText(List<DecryptedPendingMember> members, ByteString cipherText) {
for (int i = 0; i < members.size(); i++) { for (int i = 0; i < members.size(); i++) {
DecryptedPendingMember member = members.get(i); DecryptedPendingMember member = members.get(i);
if (cipherText.equals(member.getUuidCipherText())) { if (cipherText.equals(member.getServiceIdCipherText())) {
return i; return i;
} }
} }
@ -217,7 +207,7 @@ public final class DecryptedGroupUtil {
private static int findPendingIndexByServiceId(List<DecryptedPendingMember> members, ByteString serviceIdBinary) { private static int findPendingIndexByServiceId(List<DecryptedPendingMember> members, ByteString serviceIdBinary) {
for (int i = 0; i < members.size(); i++) { for (int i = 0; i < members.size(); i++) {
DecryptedPendingMember member = members.get(i); DecryptedPendingMember member = members.get(i);
if (serviceIdBinary.equals(member.getServiceIdBinary())) { if (serviceIdBinary.equals(member.getServiceIdBytes())) {
return i; return i;
} }
} }
@ -225,11 +215,11 @@ public final class DecryptedGroupUtil {
return -1; return -1;
} }
public static Optional<DecryptedRequestingMember> findRequestingByUuid(Collection<DecryptedRequestingMember> members, UUID uuid) { public static Optional<DecryptedRequestingMember> findRequestingByAci(Collection<DecryptedRequestingMember> members, ACI aci) {
ByteString uuidBytes = UuidUtil.toByteString(uuid); ByteString aciBytes = aci.toByteString();
for (DecryptedRequestingMember member : members) { for (DecryptedRequestingMember member : members) {
if (uuidBytes.equals(member.getUuid())) { if (aciBytes.equals(member.getAciBytes())) {
return Optional.of(member); return Optional.of(member);
} }
} }
@ -239,7 +229,7 @@ public final class DecryptedGroupUtil {
public static Optional<DecryptedRequestingMember> findRequestingByServiceIds(Collection<DecryptedRequestingMember> members, ServiceIds serviceIds) { public static Optional<DecryptedRequestingMember> findRequestingByServiceIds(Collection<DecryptedRequestingMember> members, ServiceIds serviceIds) {
for (DecryptedRequestingMember member : members) { for (DecryptedRequestingMember member : members) {
if (serviceIds.matches(member.getUuid())) { if (serviceIds.matches(member.getAciBytes())) {
return Optional.of(member); return Optional.of(member);
} }
} }
@ -252,25 +242,25 @@ public final class DecryptedGroupUtil {
findRequestingByServiceIds(group.getRequestingMembersList(), serviceIds).isPresent(); findRequestingByServiceIds(group.getRequestingMembersList(), serviceIds).isPresent();
} }
public static boolean isRequesting(DecryptedGroup group, UUID uuid) { public static boolean isRequesting(DecryptedGroup group, ACI aci) {
return findRequestingByUuid(group.getRequestingMembersList(), uuid).isPresent(); return findRequestingByAci(group.getRequestingMembersList(), aci).isPresent();
} }
/** /**
* Removes the uuid from the full members of a group. * Removes the aci from the full members of a group.
* <p> * <p>
* Generally not expected to have to do this, just in the case of leaving a group where you cannot * Generally not expected to have to do this, just in the case of leaving a group where you cannot
* get the new group state as you are not in the group any longer. * get the new group state as you are not in the group any longer.
*/ */
public static DecryptedGroup removeMember(DecryptedGroup group, UUID uuid, int revision) { public static DecryptedGroup removeMember(DecryptedGroup group, ACI aci, int revision) {
DecryptedGroup.Builder builder = DecryptedGroup.newBuilder(group); DecryptedGroup.Builder builder = DecryptedGroup.newBuilder(group);
ByteString uuidString = UuidUtil.toByteString(uuid); ByteString aciByteString = aci.toByteString();
boolean removed = false; boolean removed = false;
ArrayList<DecryptedMember> decryptedMembers = new ArrayList<>(builder.getMembersList()); ArrayList<DecryptedMember> decryptedMembers = new ArrayList<>(builder.getMembersList());
Iterator<DecryptedMember> membersList = decryptedMembers.iterator(); Iterator<DecryptedMember> membersList = decryptedMembers.iterator();
while (membersList.hasNext()) { while (membersList.hasNext()) {
if (uuidString.equals(membersList.next().getUuid())) { if (aciByteString.equals(membersList.next().getAciBytes())) {
membersList.remove(); membersList.remove();
removed = true; removed = true;
} }
@ -355,11 +345,11 @@ public final class DecryptedGroupUtil {
LinkedHashMap<ByteString, DecryptedMember> members = new LinkedHashMap<>(); LinkedHashMap<ByteString, DecryptedMember> members = new LinkedHashMap<>();
for (DecryptedMember member : builder.getMembersList()) { for (DecryptedMember member : builder.getMembersList()) {
members.put(member.getUuid(), member); members.put(member.getAciBytes(), member);
} }
for (DecryptedMember member : newMembersList) { for (DecryptedMember member : newMembersList) {
members.put(member.getUuid(), member); members.put(member.getAciBytes(), member);
} }
builder.clearMembers(); builder.clearMembers();
@ -370,7 +360,7 @@ public final class DecryptedGroupUtil {
protected static void applyDeleteMemberActions(DecryptedGroup.Builder builder, List<ByteString> deleteMembersList) { protected static void applyDeleteMemberActions(DecryptedGroup.Builder builder, List<ByteString> deleteMembersList) {
for (ByteString removedMember : deleteMembersList) { for (ByteString removedMember : deleteMembersList) {
int index = indexOfUuid(builder.getMembersList(), removedMember); int index = indexOfAci(builder.getMembersList(), removedMember);
if (index == -1) { if (index == -1) {
Log.w(TAG, "Deleted member on change not found in group"); Log.w(TAG, "Deleted member on change not found in group");
@ -383,7 +373,7 @@ public final class DecryptedGroupUtil {
private static void applyModifyMemberRoleActions(DecryptedGroup.Builder builder, List<DecryptedModifyMemberRole> modifyMemberRolesList) throws NotAbleToApplyGroupV2ChangeException { private static void applyModifyMemberRoleActions(DecryptedGroup.Builder builder, List<DecryptedModifyMemberRole> modifyMemberRolesList) throws NotAbleToApplyGroupV2ChangeException {
for (DecryptedModifyMemberRole modifyMemberRole : modifyMemberRolesList) { for (DecryptedModifyMemberRole modifyMemberRole : modifyMemberRolesList) {
int index = indexOfUuid(builder.getMembersList(), modifyMemberRole.getUuid()); int index = indexOfAci(builder.getMembersList(), modifyMemberRole.getAciBytes());
if (index == -1) { if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException(); throw new NotAbleToApplyGroupV2ChangeException();
@ -400,7 +390,7 @@ public final class DecryptedGroupUtil {
private static void applyModifyMemberProfileKeyActions(DecryptedGroup.Builder builder, List<DecryptedMember> modifiedProfileKeysList) throws NotAbleToApplyGroupV2ChangeException { private static void applyModifyMemberProfileKeyActions(DecryptedGroup.Builder builder, List<DecryptedMember> modifiedProfileKeysList) throws NotAbleToApplyGroupV2ChangeException {
for (DecryptedMember modifyProfileKey : modifiedProfileKeysList) { for (DecryptedMember modifyProfileKey : modifiedProfileKeysList) {
int index = indexOfUuid(builder.getMembersList(), modifyProfileKey.getUuid()); int index = indexOfAci(builder.getMembersList(), modifyProfileKey.getAciBytes());
if (index == -1) { if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException(); throw new NotAbleToApplyGroupV2ChangeException();
@ -411,15 +401,15 @@ public final class DecryptedGroupUtil {
} }
private static void applyAddPendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMember> newPendingMembersList) throws NotAbleToApplyGroupV2ChangeException { private static void applyAddPendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMember> newPendingMembersList) throws NotAbleToApplyGroupV2ChangeException {
Set<ByteString> fullMemberSet = getMemberUuidSet(builder.getMembersList()); Set<ByteString> fullMemberSet = getMemberAciSet(builder.getMembersList());
Set<ByteString> pendingMemberCipherTexts = getPendingMemberCipherTextSet(builder.getPendingMembersList()); Set<ByteString> pendingMemberCipherTexts = getPendingMemberCipherTextSet(builder.getPendingMembersList());
for (DecryptedPendingMember pendingMember : newPendingMembersList) { for (DecryptedPendingMember pendingMember : newPendingMembersList) {
if (fullMemberSet.contains(pendingMember.getServiceIdBinary())) { if (fullMemberSet.contains(pendingMember.getServiceIdBytes())) {
throw new NotAbleToApplyGroupV2ChangeException(); throw new NotAbleToApplyGroupV2ChangeException();
} }
if (!pendingMemberCipherTexts.contains(pendingMember.getUuidCipherText())) { if (!pendingMemberCipherTexts.contains(pendingMember.getServiceIdCipherText())) {
builder.addPendingMembers(pendingMember); builder.addPendingMembers(pendingMember);
} }
} }
@ -427,7 +417,7 @@ public final class DecryptedGroupUtil {
protected static void applyDeletePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMemberRemoval> deletePendingMembersList) { protected static void applyDeletePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMemberRemoval> deletePendingMembersList) {
for (DecryptedPendingMemberRemoval removedMember : deletePendingMembersList) { for (DecryptedPendingMemberRemoval removedMember : deletePendingMembersList) {
int index = findPendingIndexByUuidCipherText(builder.getPendingMembersList(), removedMember.getUuidCipherText()); int index = findPendingIndexByServiceIdCipherText(builder.getPendingMembersList(), removedMember.getServiceIdCipherText());
if (index == -1) { if (index == -1) {
Log.w(TAG, "Deleted pending member on change not found in group"); Log.w(TAG, "Deleted pending member on change not found in group");
@ -440,7 +430,7 @@ public final class DecryptedGroupUtil {
protected static void applyPromotePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedMember> promotePendingMembersList) throws NotAbleToApplyGroupV2ChangeException { protected static void applyPromotePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedMember> promotePendingMembersList) throws NotAbleToApplyGroupV2ChangeException {
for (DecryptedMember newMember : promotePendingMembersList) { for (DecryptedMember newMember : promotePendingMembersList) {
int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getUuid()); int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getAciBytes());
if (index == -1) { if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException(); throw new NotAbleToApplyGroupV2ChangeException();
@ -515,7 +505,7 @@ public final class DecryptedGroupUtil {
private static void applyDeleteRequestingMembers(DecryptedGroup.Builder builder, List<ByteString> deleteRequestingMembersList) { private static void applyDeleteRequestingMembers(DecryptedGroup.Builder builder, List<ByteString> deleteRequestingMembersList) {
for (ByteString removedMember : deleteRequestingMembersList) { for (ByteString removedMember : deleteRequestingMembersList) {
int index = indexOfUuidInRequestingList(builder.getRequestingMembersList(), removedMember); int index = indexOfAciInRequestingList(builder.getRequestingMembersList(), removedMember);
if (index == -1) { if (index == -1) {
Log.w(TAG, "Deleted member on change not found in group"); Log.w(TAG, "Deleted member on change not found in group");
@ -528,7 +518,7 @@ public final class DecryptedGroupUtil {
private static void applyPromoteRequestingMemberActions(DecryptedGroup.Builder builder, List<DecryptedApproveMember> promoteRequestingMembers) throws NotAbleToApplyGroupV2ChangeException { private static void applyPromoteRequestingMemberActions(DecryptedGroup.Builder builder, List<DecryptedApproveMember> promoteRequestingMembers) throws NotAbleToApplyGroupV2ChangeException {
for (DecryptedApproveMember approvedMember : promoteRequestingMembers) { for (DecryptedApproveMember approvedMember : promoteRequestingMembers) {
int index = indexOfUuidInRequestingList(builder.getRequestingMembersList(), approvedMember.getUuid()); int index = indexOfAciInRequestingList(builder.getRequestingMembersList(), approvedMember.getAciBytes());
if (index == -1) { if (index == -1) {
Log.w(TAG, "Deleted member on change not found in group"); Log.w(TAG, "Deleted member on change not found in group");
@ -542,7 +532,7 @@ public final class DecryptedGroupUtil {
builder.removeRequestingMembers(index) builder.removeRequestingMembers(index)
.addMembers(DecryptedMember.newBuilder() .addMembers(DecryptedMember.newBuilder()
.setUuid(approvedMember.getUuid()) .setAciBytes(approvedMember.getAciBytes())
.setProfileKey(requestingMember.getProfileKey()) .setProfileKey(requestingMember.getProfileKey())
.setRole(role)); .setRole(role));
} }
@ -558,7 +548,7 @@ public final class DecryptedGroupUtil {
Set<ByteString> bannedMemberServiceIdSet = getBannedMemberServiceIdSet(builder.getBannedMembersList()); Set<ByteString> bannedMemberServiceIdSet = getBannedMemberServiceIdSet(builder.getBannedMembersList());
for (DecryptedBannedMember member : newBannedMembersList) { for (DecryptedBannedMember member : newBannedMembersList) {
if (bannedMemberServiceIdSet.contains(member.getServiceIdBinary())) { if (bannedMemberServiceIdSet.contains(member.getServiceIdBytes())) {
Log.w(TAG, "Banned member already in banned list"); Log.w(TAG, "Banned member already in banned list");
} else { } else {
builder.addBannedMembers(member); builder.addBannedMembers(member);
@ -568,7 +558,7 @@ public final class DecryptedGroupUtil {
private static void applyDeleteBannedMembersActions(DecryptedGroup.Builder builder, List<DecryptedBannedMember> deleteMembersList) { private static void applyDeleteBannedMembersActions(DecryptedGroup.Builder builder, List<DecryptedBannedMember> deleteMembersList) {
for (DecryptedBannedMember removedMember : deleteMembersList) { for (DecryptedBannedMember removedMember : deleteMembersList) {
int index = indexOfServiceIdInBannedMemberList(builder.getBannedMembersList(), removedMember.getServiceIdBinary()); int index = indexOfServiceIdInBannedMemberList(builder.getBannedMembersList(), removedMember.getServiceIdBytes());
if (index == -1) { if (index == -1) {
Log.w(TAG, "Deleted banned member on change not found in banned list"); Log.w(TAG, "Deleted banned member on change not found in banned list");
@ -581,7 +571,7 @@ public final class DecryptedGroupUtil {
protected static void applyPromotePendingPniAciMemberActions(DecryptedGroup.Builder builder, List<DecryptedMember> promotePendingPniAciMembersList) throws NotAbleToApplyGroupV2ChangeException { protected static void applyPromotePendingPniAciMemberActions(DecryptedGroup.Builder builder, List<DecryptedMember> promotePendingPniAciMembersList) throws NotAbleToApplyGroupV2ChangeException {
for (DecryptedMember newMember : promotePendingPniAciMembersList) { for (DecryptedMember newMember : promotePendingPniAciMembersList) {
int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getPni()); int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getPniBytes());
if (index == -1) { if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException(); throw new NotAbleToApplyGroupV2ChangeException();
@ -598,21 +588,21 @@ public final class DecryptedGroupUtil {
.build(); .build();
} }
private static Set<ByteString> getMemberUuidSet(List<DecryptedMember> membersList) { private static Set<ByteString> getMemberAciSet(List<DecryptedMember> membersList) {
Set<ByteString> memberUuids = new HashSet<>(membersList.size()); Set<ByteString> memberAcis = new HashSet<>(membersList.size());
for (DecryptedMember members : membersList) { for (DecryptedMember members : membersList) {
memberUuids.add(members.getUuid()); memberAcis.add(members.getAciBytes());
} }
return memberUuids; return memberAcis;
} }
private static Set<ByteString> getPendingMemberCipherTextSet(List<DecryptedPendingMember> pendingMemberList) { private static Set<ByteString> getPendingMemberCipherTextSet(List<DecryptedPendingMember> pendingMemberList) {
Set<ByteString> pendingMemberCipherTexts = new HashSet<>(pendingMemberList.size()); Set<ByteString> pendingMemberCipherTexts = new HashSet<>(pendingMemberList.size());
for (DecryptedPendingMember pendingMember : pendingMemberList) { for (DecryptedPendingMember pendingMember : pendingMemberList) {
pendingMemberCipherTexts.add(pendingMember.getUuidCipherText()); pendingMemberCipherTexts.add(pendingMember.getServiceIdCipherText());
} }
return pendingMemberCipherTexts; return pendingMemberCipherTexts;
@ -622,25 +612,25 @@ public final class DecryptedGroupUtil {
Set<ByteString> memberServiceIds = new HashSet<>(bannedMemberList.size()); Set<ByteString> memberServiceIds = new HashSet<>(bannedMemberList.size());
for (DecryptedBannedMember member : bannedMemberList) { for (DecryptedBannedMember member : bannedMemberList) {
memberServiceIds.add(member.getServiceIdBinary()); memberServiceIds.add(member.getServiceIdBytes());
} }
return memberServiceIds; return memberServiceIds;
} }
private static void removePendingAndRequestingMembersNowInGroup(DecryptedGroup.Builder builder) { private static void removePendingAndRequestingMembersNowInGroup(DecryptedGroup.Builder builder) {
Set<ByteString> allMembers = membersToUuidByteStringSet(builder.getMembersList()); Set<ByteString> allMembers = membersToAciByteStringSet(builder.getMembersList());
for (int i = builder.getPendingMembersCount() - 1; i >= 0; i--) { for (int i = builder.getPendingMembersCount() - 1; i >= 0; i--) {
DecryptedPendingMember pendingMember = builder.getPendingMembers(i); DecryptedPendingMember pendingMember = builder.getPendingMembers(i);
if (allMembers.contains(pendingMember.getServiceIdBinary())) { if (allMembers.contains(pendingMember.getServiceIdBytes())) {
builder.removePendingMembers(i); builder.removePendingMembers(i);
} }
} }
for (int i = builder.getRequestingMembersCount() - 1; i >= 0; i--) { for (int i = builder.getRequestingMembersCount() - 1; i >= 0; i--) {
DecryptedRequestingMember requestingMember = builder.getRequestingMembers(i); DecryptedRequestingMember requestingMember = builder.getRequestingMembers(i);
if (allMembers.contains(requestingMember.getUuid())) { if (allMembers.contains(requestingMember.getAciBytes())) {
builder.removeRequestingMembers(i); builder.removeRequestingMembers(i);
} }
} }
@ -652,23 +642,29 @@ public final class DecryptedGroupUtil {
} }
} }
private static int indexOfUuid(List<DecryptedMember> memberList, ByteString uuid) { private static int indexOfAci(List<DecryptedMember> memberList, ByteString aci) {
for (int i = 0; i < memberList.size(); i++) { for (int i = 0; i < memberList.size(); i++) {
if (uuid.equals(memberList.get(i).getUuid())) return i; if (aci.equals(memberList.get(i).getAciBytes())) {
return i;
}
} }
return -1; return -1;
} }
private static int indexOfUuidInRequestingList(List<DecryptedRequestingMember> memberList, ByteString uuid) { private static int indexOfAciInRequestingList(List<DecryptedRequestingMember> memberList, ByteString aci) {
for (int i = 0; i < memberList.size(); i++) { for (int i = 0; i < memberList.size(); i++) {
if (uuid.equals(memberList.get(i).getUuid())) return i; if (aci.equals(memberList.get(i).getAciBytes())) {
return i;
}
} }
return -1; return -1;
} }
private static int indexOfServiceIdInBannedMemberList(List<DecryptedBannedMember> memberList, ByteString serviceIdBinary) { private static int indexOfServiceIdInBannedMemberList(List<DecryptedBannedMember> memberList, ByteString serviceIdBinary) {
for (int i = 0; i < memberList.size(); i++) { for (int i = 0; i < memberList.size(); i++) {
if (serviceIdBinary.equals(memberList.get(i).getServiceIdBinary())) return i; if (serviceIdBinary.equals(memberList.get(i).getServiceIdBytes())) {
return i;
}
} }
return -1; return -1;
} }

View file

@ -57,37 +57,37 @@ public final class GroupChangeReconstruct {
builder.setNewMemberAccess(toState.getAccessControl().getMembers()); builder.setNewMemberAccess(toState.getAccessControl().getMembers());
} }
Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set<ByteString> fromStateMemberAcis = membersToSetOfAcis(fromState.getMembersList());
Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); Set<ByteString> toStateMemberAcis = membersToSetOfAcis(toState.getMembersList());
Set<ByteString> pendingMembersListA = pendingMembersToSetOfServiceIds(fromState.getPendingMembersList()); Set<ByteString> pendingMembersListA = pendingMembersToSetOfServiceIds(fromState.getPendingMembersList());
Set<ByteString> pendingMembersListB = pendingMembersToSetOfServiceIds(toState.getPendingMembersList()); Set<ByteString> pendingMembersListB = pendingMembersToSetOfServiceIds(toState.getPendingMembersList());
Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set<ByteString> requestingMembersListA = requestingMembersToSetOfAcis(fromState.getRequestingMembersList());
Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); Set<ByteString> requestingMembersListB = requestingMembersToSetOfAcis(toState.getRequestingMembersList());
Set<ByteString> bannedMembersListA = bannedMembersToSetOfServiceIds(fromState.getBannedMembersList()); Set<ByteString> bannedMembersListA = bannedMembersToSetOfServiceIds(fromState.getBannedMembersList());
Set<ByteString> bannedMembersListB = bannedMembersToSetOfServiceIds(toState.getBannedMembersList()); Set<ByteString> bannedMembersListB = bannedMembersToSetOfServiceIds(toState.getBannedMembersList());
Set<ByteString> removedPendingMemberServiceIds = subtract(pendingMembersListA, pendingMembersListB); Set<ByteString> removedPendingMemberServiceIds = subtract(pendingMembersListA, pendingMembersListB);
Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); Set<ByteString> removedRequestingMemberAcis = subtract(requestingMembersListA, requestingMembersListB);
Set<ByteString> newPendingMemberServiceIds = subtract(pendingMembersListB, pendingMembersListA); Set<ByteString> newPendingMemberServiceIds = subtract(pendingMembersListB, pendingMembersListA);
Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); Set<ByteString> newRequestingMemberAcis = subtract(requestingMembersListB, requestingMembersListA);
Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> removedMemberAcis = subtract(fromStateMemberAcis, toStateMemberAcis);
Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); Set<ByteString> newMemberAcis = subtract(toStateMemberAcis, fromStateMemberAcis);
Set<ByteString> removedBannedMemberServiceIds = subtract(bannedMembersListA, bannedMembersListB); Set<ByteString> removedBannedMemberServiceIds = subtract(bannedMembersListA, bannedMembersListB);
Set<ByteString> newBannedMemberServiceIds = subtract(bannedMembersListB, bannedMembersListA); Set<ByteString> newBannedMemberServiceIds = subtract(bannedMembersListB, bannedMembersListA);
Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberServiceIds); Set<ByteString> addedByInvitationAcis = intersect(newMemberAcis, removedPendingMemberServiceIds);
Set<ByteString> addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set<ByteString> addedByRequestApprovalAcis = intersect(newMemberAcis, removedRequestingMemberAcis);
Set<DecryptedMember> addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set<DecryptedMember> addedMembersByInvitation = intersectByAci(toState.getMembersList(), addedByInvitationAcis);
Set<DecryptedMember> addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set<DecryptedMember> addedMembersByRequestApproval = intersectByAci(toState.getMembersList(), addedByRequestApprovalAcis);
Set<DecryptedMember> addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); Set<DecryptedMember> addedMembers = intersectByAci(toState.getMembersList(), subtract(newMemberAcis, addedByInvitationAcis, addedByRequestApprovalAcis));
Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByServiceId(fromState.getPendingMembersList(), subtract(removedPendingMemberServiceIds, addedByInvitationUuids)); Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByServiceId(fromState.getPendingMembersList(), subtract(removedPendingMemberServiceIds, addedByInvitationAcis));
Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByAci(fromState.getRequestingMembersList(), subtract(removedRequestingMemberAcis, addedByRequestApprovalAcis));
for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { for (DecryptedMember member : intersectByAci(fromState.getMembersList(), removedMemberAcis)) {
builder.addDeleteMembers(member.getUuid()); builder.addDeleteMembers(member.getAciBytes());
} }
for (DecryptedMember member : addedMembers) { for (DecryptedMember member : addedMembers) {
@ -100,24 +100,24 @@ public final class GroupChangeReconstruct {
for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { for (DecryptedPendingMember uninvitedMember : uninvitedMembers) {
builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(uninvitedMember.getServiceIdBinary()) .setServiceIdBytes(uninvitedMember.getServiceIdBytes())
.setUuidCipherText(uninvitedMember.getUuidCipherText())); .setServiceIdCipherText(uninvitedMember.getServiceIdCipherText()));
} }
for (DecryptedPendingMember invitedMember : intersectPendingByServiceId(toState.getPendingMembersList(), newPendingMemberServiceIds)) { for (DecryptedPendingMember invitedMember : intersectPendingByServiceId(toState.getPendingMembersList(), newPendingMemberServiceIds)) {
builder.addNewPendingMembers(invitedMember); builder.addNewPendingMembers(invitedMember);
} }
Set<ByteString> consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> consistentMemberAcis = intersect(fromStateMemberAcis, toStateMemberAcis);
Set<DecryptedMember> changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); Set<DecryptedMember> changedMembers = intersectByAci(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberAcis);
Map<ByteString, DecryptedMember> membersUuidMap = uuidMap(fromState.getMembersList()); Map<ByteString, DecryptedMember> membersAciMap = mapByAci(fromState.getMembersList());
Map<ByteString, DecryptedBannedMember> bannedMembersServiceIdMap = bannedServiceIdMap(toState.getBannedMembersList()); Map<ByteString, DecryptedBannedMember> bannedMembersServiceIdMap = bannedServiceIdMap(toState.getBannedMembersList());
for (DecryptedMember newState : changedMembers) { for (DecryptedMember newState : changedMembers) {
DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); DecryptedMember oldState = membersAciMap.get(newState.getAciBytes());
if (oldState.getRole() != newState.getRole()) { if (oldState.getRole() != newState.getRole()) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setUuid(newState.getUuid()) .setAciBytes(newState.getAciBytes())
.setRole(newState.getRole())); .setRole(newState.getRole()));
} }
@ -130,17 +130,17 @@ public final class GroupChangeReconstruct {
builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink()); builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink());
} }
for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) { for (DecryptedRequestingMember requestingMember : intersectRequestingByAci(toState.getRequestingMembersList(), newRequestingMemberAcis)) {
builder.addNewRequestingMembers(requestingMember); builder.addNewRequestingMembers(requestingMember);
} }
for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) { for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) {
builder.addDeleteRequestingMembers(requestingMember.getUuid()); builder.addDeleteRequestingMembers(requestingMember.getAciBytes());
} }
for (DecryptedMember member : addedMembersByRequestApproval) { for (DecryptedMember member : addedMembersByRequestApproval) {
builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setUuid(member.getUuid()) .setAciBytes(member.getAciBytes())
.setRole(member.getRole())); .setRole(member.getRole()));
} }
@ -149,11 +149,11 @@ public final class GroupChangeReconstruct {
} }
for (ByteString serviceIdBinary : removedBannedMemberServiceIds) { for (ByteString serviceIdBinary : removedBannedMemberServiceIds) {
builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(serviceIdBinary).build()); builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBytes(serviceIdBinary).build());
} }
for (ByteString serviceIdBinary : newBannedMemberServiceIds) { for (ByteString serviceIdBinary : newBannedMemberServiceIds) {
DecryptedBannedMember.Builder newBannedBuilder = DecryptedBannedMember.newBuilder().setServiceIdBinary(serviceIdBinary); DecryptedBannedMember.Builder newBannedBuilder = DecryptedBannedMember.newBuilder().setServiceIdBytes(serviceIdBinary);
DecryptedBannedMember bannedMember = bannedMembersServiceIdMap.get(serviceIdBinary); DecryptedBannedMember bannedMember = bannedMembersServiceIdMap.get(serviceIdBinary);
if (bannedMember != null) { if (bannedMember != null) {
newBannedBuilder.setTimestamp(bannedMember.getTimestamp()); newBannedBuilder.setTimestamp(bannedMember.getTimestamp());
@ -165,10 +165,10 @@ public final class GroupChangeReconstruct {
return builder.build(); return builder.build();
} }
private static Map<ByteString, DecryptedMember> uuidMap(List<DecryptedMember> membersList) { private static Map<ByteString, DecryptedMember> mapByAci(List<DecryptedMember> membersList) {
Map<ByteString, DecryptedMember> map = new LinkedHashMap<>(membersList.size()); Map<ByteString, DecryptedMember> map = new LinkedHashMap<>(membersList.size());
for (DecryptedMember member : membersList) { for (DecryptedMember member : membersList) {
map.put(member.getUuid(), member); map.put(member.getAciBytes(), member);
} }
return map; return map;
} }
@ -176,15 +176,15 @@ public final class GroupChangeReconstruct {
private static Map<ByteString, DecryptedBannedMember> bannedServiceIdMap(List<DecryptedBannedMember> membersList) { private static Map<ByteString, DecryptedBannedMember> bannedServiceIdMap(List<DecryptedBannedMember> membersList) {
Map<ByteString, DecryptedBannedMember> map = new LinkedHashMap<>(membersList.size()); Map<ByteString, DecryptedBannedMember> map = new LinkedHashMap<>(membersList.size());
for (DecryptedBannedMember member : membersList) { for (DecryptedBannedMember member : membersList) {
map.put(member.getServiceIdBinary(), member); map.put(member.getServiceIdBytes(), member);
} }
return map; return map;
} }
private static Set<DecryptedMember> intersectByUUID(Collection<DecryptedMember> members, Set<ByteString> uuids) { private static Set<DecryptedMember> intersectByAci(Collection<DecryptedMember> members, Set<ByteString> acis) {
Set<DecryptedMember> result = new LinkedHashSet<>(members.size()); Set<DecryptedMember> result = new LinkedHashSet<>(members.size());
for (DecryptedMember member : members) { for (DecryptedMember member : members) {
if (uuids.contains(member.getUuid())) if (acis.contains(member.getAciBytes()))
result.add(member); result.add(member);
} }
return result; return result;
@ -193,16 +193,16 @@ public final class GroupChangeReconstruct {
private static Set<DecryptedPendingMember> intersectPendingByServiceId(Collection<DecryptedPendingMember> members, Set<ByteString> serviceIds) { private static Set<DecryptedPendingMember> intersectPendingByServiceId(Collection<DecryptedPendingMember> members, Set<ByteString> serviceIds) {
Set<DecryptedPendingMember> result = new LinkedHashSet<>(members.size()); Set<DecryptedPendingMember> result = new LinkedHashSet<>(members.size());
for (DecryptedPendingMember member : members) { for (DecryptedPendingMember member : members) {
if (serviceIds.contains(member.getServiceIdBinary())) if (serviceIds.contains(member.getServiceIdBytes()))
result.add(member); result.add(member);
} }
return result; return result;
} }
private static Set<DecryptedRequestingMember> intersectRequestingByUUID(Collection<DecryptedRequestingMember> members, Set<ByteString> uuids) { private static Set<DecryptedRequestingMember> intersectRequestingByAci(Collection<DecryptedRequestingMember> members, Set<ByteString> acis) {
Set<DecryptedRequestingMember> result = new LinkedHashSet<>(members.size()); Set<DecryptedRequestingMember> result = new LinkedHashSet<>(members.size());
for (DecryptedRequestingMember member : members) { for (DecryptedRequestingMember member : members) {
if (uuids.contains(member.getUuid())) if (acis.contains(member.getAciBytes()))
result.add(member); result.add(member);
} }
return result; return result;
@ -211,31 +211,31 @@ public final class GroupChangeReconstruct {
private static Set<ByteString> pendingMembersToSetOfServiceIds(Collection<DecryptedPendingMember> pendingMembers) { private static Set<ByteString> pendingMembersToSetOfServiceIds(Collection<DecryptedPendingMember> pendingMembers) {
Set<ByteString> serviceIds = new LinkedHashSet<>(pendingMembers.size()); Set<ByteString> serviceIds = new LinkedHashSet<>(pendingMembers.size());
for (DecryptedPendingMember pendingMember : pendingMembers) { for (DecryptedPendingMember pendingMember : pendingMembers) {
serviceIds.add(pendingMember.getServiceIdBinary()); serviceIds.add(pendingMember.getServiceIdBytes());
} }
return serviceIds; return serviceIds;
} }
private static Set<ByteString> requestingMembersToSetOfUuids(Collection<DecryptedRequestingMember> requestingMembers) { private static Set<ByteString> requestingMembersToSetOfAcis(Collection<DecryptedRequestingMember> requestingMembers) {
Set<ByteString> uuids = new LinkedHashSet<>(requestingMembers.size()); Set<ByteString> acis = new LinkedHashSet<>(requestingMembers.size());
for (DecryptedRequestingMember requestingMember : requestingMembers) { for (DecryptedRequestingMember requestingMember : requestingMembers) {
uuids.add(requestingMember.getUuid()); acis.add(requestingMember.getAciBytes());
} }
return uuids; return acis;
} }
private static Set<ByteString> membersToSetOfUuids(Collection<DecryptedMember> members) { private static Set<ByteString> membersToSetOfAcis(Collection<DecryptedMember> members) {
Set<ByteString> uuids = new LinkedHashSet<>(members.size()); Set<ByteString> acis = new LinkedHashSet<>(members.size());
for (DecryptedMember member : members) { for (DecryptedMember member : members) {
uuids.add(member.getUuid()); acis.add(member.getAciBytes());
} }
return uuids; return acis;
} }
private static Set<ByteString> bannedMembersToSetOfServiceIds(Collection<DecryptedBannedMember> bannedMembers) { private static Set<ByteString> bannedMembersToSetOfServiceIds(Collection<DecryptedBannedMember> bannedMembers) {
Set<ByteString> serviceIds = new LinkedHashSet<>(bannedMembers.size()); Set<ByteString> serviceIds = new LinkedHashSet<>(bannedMembers.size());
for (DecryptedBannedMember bannedMember : bannedMembers) { for (DecryptedBannedMember bannedMember : bannedMembers) {
serviceIds.add(bannedMember.getServiceIdBinary()); serviceIds.add(bannedMember.getServiceIdBytes());
} }
return serviceIds; return serviceIds;
} }

View file

@ -113,19 +113,19 @@ public final class GroupChangeUtil {
HashMap<ByteString, DecryptedBannedMember> bannedMembersByServiceId = new HashMap<>(groupState.getBannedMembersCount()); HashMap<ByteString, DecryptedBannedMember> bannedMembersByServiceId = new HashMap<>(groupState.getBannedMembersCount());
for (DecryptedMember member : groupState.getMembersList()) { for (DecryptedMember member : groupState.getMembersList()) {
fullMembersByUuid.put(member.getUuid(), member); fullMembersByUuid.put(member.getAciBytes(), member);
} }
for (DecryptedPendingMember member : groupState.getPendingMembersList()) { for (DecryptedPendingMember member : groupState.getPendingMembersList()) {
pendingMembersByServiceId.put(member.getServiceIdBinary(), member); pendingMembersByServiceId.put(member.getServiceIdBytes(), member);
} }
for (DecryptedRequestingMember member : groupState.getRequestingMembersList()) { for (DecryptedRequestingMember member : groupState.getRequestingMembersList()) {
requestingMembersByUuid.put(member.getUuid(), member); requestingMembersByUuid.put(member.getAciBytes(), member);
} }
for (DecryptedBannedMember member : groupState.getBannedMembersList()) { for (DecryptedBannedMember member : groupState.getBannedMembersList()) {
bannedMembersByServiceId.put(member.getServiceIdBinary(), member); bannedMembersByServiceId.put(member.getServiceIdBytes(), member);
} }
resolveField3AddMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByServiceId); resolveField3AddMembers (conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByServiceId);
@ -157,9 +157,9 @@ public final class GroupChangeUtil {
for (int i = newMembersList.size() - 1; i >= 0; i--) { for (int i = newMembersList.size() - 1; i >= 0; i--) {
DecryptedMember member = newMembersList.get(i); DecryptedMember member = newMembersList.get(i);
if (fullMembersByUuid.containsKey(member.getUuid())) { if (fullMembersByUuid.containsKey(member.getAciBytes())) {
result.removeAddMembers(i); result.removeAddMembers(i);
} else if (pendingMembersByServiceId.containsKey(member.getUuid())) { } else if (pendingMembersByServiceId.containsKey(member.getAciBytes()) || pendingMembersByServiceId.containsKey(member.getPniBytes())) {
result.moveAddToPromote(i); result.moveAddToPromote(i);
} }
} }
@ -182,7 +182,7 @@ public final class GroupChangeUtil {
for (int i = modifyRolesList.size() - 1; i >= 0; i--) { for (int i = modifyRolesList.size() - 1; i >= 0; i--) {
DecryptedModifyMemberRole modifyRoleAction = modifyRolesList.get(i); DecryptedModifyMemberRole modifyRoleAction = modifyRolesList.get(i);
DecryptedMember memberInGroup = fullMembersByUuid.get(modifyRoleAction.getUuid()); DecryptedMember memberInGroup = fullMembersByUuid.get(modifyRoleAction.getAciBytes());
if (memberInGroup == null || memberInGroup.getRole() == modifyRoleAction.getRole()) { if (memberInGroup == null || memberInGroup.getRole() == modifyRoleAction.getRole()) {
result.removeModifyMemberRoles(i); result.removeModifyMemberRoles(i);
@ -195,7 +195,7 @@ public final class GroupChangeUtil {
for (int i = modifyProfileKeysList.size() - 1; i >= 0; i--) { for (int i = modifyProfileKeysList.size() - 1; i >= 0; i--) {
DecryptedMember member = modifyProfileKeysList.get(i); DecryptedMember member = modifyProfileKeysList.get(i);
DecryptedMember memberInGroup = fullMembersByUuid.get(member.getUuid()); DecryptedMember memberInGroup = fullMembersByUuid.get(member.getAciBytes());
if (memberInGroup == null || member.getProfileKey().equals(memberInGroup.getProfileKey())) { if (memberInGroup == null || member.getProfileKey().equals(memberInGroup.getProfileKey())) {
result.removeModifyMemberProfileKeys(i); result.removeModifyMemberProfileKeys(i);
@ -209,7 +209,7 @@ public final class GroupChangeUtil {
for (int i = newPendingMembersList.size() - 1; i >= 0; i--) { for (int i = newPendingMembersList.size() - 1; i >= 0; i--) {
DecryptedPendingMember member = newPendingMembersList.get(i); DecryptedPendingMember member = newPendingMembersList.get(i);
if (fullMembersByUuid.containsKey(member.getServiceIdBinary()) || pendingMembersByServiceId.containsKey(member.getServiceIdBinary())) { if (fullMembersByUuid.containsKey(member.getServiceIdBytes()) || pendingMembersByServiceId.containsKey(member.getServiceIdBytes())) {
result.removeAddPendingMembers(i); result.removeAddPendingMembers(i);
} }
} }
@ -221,7 +221,7 @@ public final class GroupChangeUtil {
for (int i = deletePendingMembersList.size() - 1; i >= 0; i--) { for (int i = deletePendingMembersList.size() - 1; i >= 0; i--) {
DecryptedPendingMemberRemoval member = deletePendingMembersList.get(i); DecryptedPendingMemberRemoval member = deletePendingMembersList.get(i);
if (!pendingMembersByServiceId.containsKey(member.getServiceIdBinary())) { if (!pendingMembersByServiceId.containsKey(member.getServiceIdBytes())) {
result.removeDeletePendingMembers(i); result.removeDeletePendingMembers(i);
} }
} }
@ -233,7 +233,7 @@ public final class GroupChangeUtil {
for (int i = promotePendingMembersList.size() - 1; i >= 0; i--) { for (int i = promotePendingMembersList.size() - 1; i >= 0; i--) {
DecryptedMember member = promotePendingMembersList.get(i); DecryptedMember member = promotePendingMembersList.get(i);
if (!pendingMembersByServiceId.containsKey(member.getUuid())) { if (!pendingMembersByServiceId.containsKey(member.getAciBytes()) && !pendingMembersByServiceId.containsKey(member.getPniBytes())) {
result.removePromotePendingMembers(i); result.removePromotePendingMembers(i);
} }
} }
@ -281,9 +281,9 @@ public final class GroupChangeUtil {
for (int i = newMembersList.size() - 1; i >= 0; i--) { for (int i = newMembersList.size() - 1; i >= 0; i--) {
DecryptedRequestingMember member = newMembersList.get(i); DecryptedRequestingMember member = newMembersList.get(i);
if (fullMembersByUuid.containsKey(member.getUuid())) { if (fullMembersByUuid.containsKey(member.getAciBytes())) {
result.removeAddRequestingMembers(i); result.removeAddRequestingMembers(i);
} else if (pendingMembersByServiceId.containsKey(member.getUuid())) { } else if (pendingMembersByServiceId.containsKey(member.getAciBytes())) {
result.moveAddRequestingMembersToPromote(i); result.moveAddRequestingMembersToPromote(i);
} }
} }
@ -313,7 +313,7 @@ public final class GroupChangeUtil {
for (int i = promoteRequestingMembersList.size() - 1; i >= 0; i--) { for (int i = promoteRequestingMembersList.size() - 1; i >= 0; i--) {
DecryptedApproveMember member = promoteRequestingMembersList.get(i); DecryptedApproveMember member = promoteRequestingMembersList.get(i);
if (!requestingMembersByUuid.containsKey(member.getUuid())) { if (!requestingMembersByUuid.containsKey(member.getAciBytes())) {
result.removePromoteRequestingMembers(i); result.removePromoteRequestingMembers(i);
} }
} }
@ -337,7 +337,7 @@ public final class GroupChangeUtil {
for (int i = newBannedMembersList.size() - 1; i >= 0; i--) { for (int i = newBannedMembersList.size() - 1; i >= 0; i--) {
DecryptedBannedMember member = newBannedMembersList.get(i); DecryptedBannedMember member = newBannedMembersList.get(i);
if (bannedMembersByServiceId.containsKey(member.getServiceIdBinary())) { if (bannedMembersByServiceId.containsKey(member.getServiceIdBytes())) {
result.removeAddBannedMembers(i); result.removeAddBannedMembers(i);
} }
} }
@ -349,19 +349,19 @@ public final class GroupChangeUtil {
for (int i = deleteBannedMembersList.size() - 1; i >= 0; i--) { for (int i = deleteBannedMembersList.size() - 1; i >= 0; i--) {
DecryptedBannedMember member = deleteBannedMembersList.get(i); DecryptedBannedMember member = deleteBannedMembersList.get(i);
if (!bannedMembersByServiceId.containsKey(member.getServiceIdBinary())) { if (!bannedMembersByServiceId.containsKey(member.getServiceIdBytes())) {
result.removeDeleteBannedMembers(i); result.removeDeleteBannedMembers(i);
} }
} }
} }
private static void resolveField24PromotePendingPniAciMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap<ByteString, DecryptedMember> fullMembersByUuid) { private static void resolveField24PromotePendingPniAciMembers(DecryptedGroupChange conflictingChange, ChangeSetModifier result, HashMap<ByteString, DecryptedMember> fullMembersByAci) {
List<DecryptedMember> promotePendingPniAciMembersList = conflictingChange.getPromotePendingPniAciMembersList(); List<DecryptedMember> promotePendingPniAciMembersList = conflictingChange.getPromotePendingPniAciMembersList();
for (int i = promotePendingPniAciMembersList.size() - 1; i >= 0; i--) { for (int i = promotePendingPniAciMembersList.size() - 1; i >= 0; i--) {
DecryptedMember member = promotePendingPniAciMembersList.get(i); DecryptedMember member = promotePendingPniAciMembersList.get(i);
if (fullMembersByUuid.containsKey(member.getUuid())) { if (fullMembersByAci.containsKey(member.getAciBytes())) {
result.removePromotePendingPniAciMembers(i); result.removePromotePendingPniAciMembers(i);
} }
} }

View file

@ -215,14 +215,16 @@ public final class GroupsV2Operations {
return actions; return actions;
} }
public GroupChange.Actions.Builder createRefuseGroupJoinRequest(Set<UUID> requestsToRemove, boolean alsoBan, List<DecryptedBannedMember> bannedMembers) { public GroupChange.Actions.Builder createRefuseGroupJoinRequest(Set<? extends ServiceId> requestsToRemove, boolean alsoBan, List<DecryptedBannedMember> bannedMembers) {
GroupChange.Actions.Builder actions = alsoBan ? createBanUuidsChange(requestsToRemove, false, bannedMembers) GroupChange.Actions.Builder actions = alsoBan ? createBanServiceIdsChange(requestsToRemove, false, bannedMembers)
: GroupChange.Actions.newBuilder(); : GroupChange.Actions.newBuilder();
for (UUID uuid : requestsToRemove) { for (ServiceId serviceId : requestsToRemove) {
if (serviceId instanceof ACI) {
actions.addDeleteRequestingMembers(GroupChange.Actions.DeleteRequestingMemberAction actions.addDeleteRequestingMembers(GroupChange.Actions.DeleteRequestingMemberAction
.newBuilder() .newBuilder()
.setDeletedUserId(encryptServiceId(ACI.from(uuid)))); .setDeletedUserId(encryptServiceId(serviceId)));
}
} }
return actions; return actions;
@ -241,20 +243,20 @@ public final class GroupsV2Operations {
return actions; return actions;
} }
public GroupChange.Actions.Builder createRemoveMembersChange(final Set<UUID> membersToRemove, boolean alsoBan, List<DecryptedBannedMember> bannedMembers) { public GroupChange.Actions.Builder createRemoveMembersChange(final Set<ACI> membersToRemove, boolean alsoBan, List<DecryptedBannedMember> bannedMembers) {
GroupChange.Actions.Builder actions = alsoBan ? createBanUuidsChange(membersToRemove, false, bannedMembers) GroupChange.Actions.Builder actions = alsoBan ? createBanServiceIdsChange(membersToRemove, false, bannedMembers)
: GroupChange.Actions.newBuilder(); : GroupChange.Actions.newBuilder();
for (UUID remove: membersToRemove) { for (ACI remove: membersToRemove) {
actions.addDeleteMembers(GroupChange.Actions.DeleteMemberAction actions.addDeleteMembers(GroupChange.Actions.DeleteMemberAction
.newBuilder() .newBuilder()
.setDeletedUserId(encryptServiceId(ACI.from(remove)))); .setDeletedUserId(encryptServiceId(remove)));
} }
return actions; return actions;
} }
public GroupChange.Actions.Builder createLeaveAndPromoteMembersToAdmin(UUID self, List<UUID> membersToMakeAdmin) { public GroupChange.Actions.Builder createLeaveAndPromoteMembersToAdmin(ACI self, List<UUID> membersToMakeAdmin) {
GroupChange.Actions.Builder actions = createRemoveMembersChange(Collections.singleton(self), false, Collections.emptyList()); GroupChange.Actions.Builder actions = createRemoveMembersChange(Collections.singleton(self), false, Collections.emptyList());
for (UUID member : membersToMakeAdmin) { for (UUID member : membersToMakeAdmin) {
@ -363,16 +365,16 @@ public final class GroupsV2Operations {
} }
/** Note that this can only ban ACIs. */ /** Note that this can only ban ACIs. */
public GroupChange.Actions.Builder createBanUuidsChange(Set<UUID> banUuids, boolean rejectJoinRequest, List<DecryptedBannedMember> bannedMembersList) { public GroupChange.Actions.Builder createBanServiceIdsChange(Set<? extends ServiceId> banServiceIds, boolean rejectJoinRequest, List<DecryptedBannedMember> bannedMembersList) {
GroupChange.Actions.Builder builder = rejectJoinRequest ? createRefuseGroupJoinRequest(banUuids, false, Collections.emptyList()) GroupChange.Actions.Builder builder = rejectJoinRequest ? createRefuseGroupJoinRequest(banServiceIds, false, Collections.emptyList())
: GroupChange.Actions.newBuilder(); : GroupChange.Actions.newBuilder();
int spacesToFree = bannedMembersList.size() + banUuids.size() - maxGroupSize; int spacesToFree = bannedMembersList.size() + banServiceIds.size() - maxGroupSize;
if (spacesToFree > 0) { if (spacesToFree > 0) {
List<ByteString> unban = bannedMembersList.stream() List<ByteString> unban = bannedMembersList.stream()
.sorted(Comparator.comparingLong(DecryptedBannedMember::getTimestamp)) .sorted(Comparator.comparingLong(DecryptedBannedMember::getTimestamp))
.limit(spacesToFree) .limit(spacesToFree)
.map(DecryptedBannedMember::getServiceIdBinary) .map(DecryptedBannedMember::getServiceIdBytes)
.collect(Collectors.toList()); .collect(Collectors.toList());
for (ByteString serviceIdBinary : unban) { for (ByteString serviceIdBinary : unban) {
@ -380,8 +382,8 @@ public final class GroupsV2Operations {
} }
} }
for (UUID uuid : banUuids) { for (ServiceId banServiceId : banServiceIds) {
builder.addAddBannedMembers(GroupChange.Actions.AddBannedMemberAction.newBuilder().setAdded(BannedMember.newBuilder().setUserId(encryptServiceId(ACI.from(uuid))).build())); builder.addAddBannedMembers(GroupChange.Actions.AddBannedMemberAction.newBuilder().setAdded(BannedMember.newBuilder().setUserId(encryptServiceId(banServiceId)).build()));
} }
return builder; return builder;
@ -458,7 +460,7 @@ public final class GroupsV2Operations {
for (Member member : membersList) { for (Member member : membersList) {
ACI memberAci = decryptAci(member.getUserId()); ACI memberAci = decryptAci(member.getUserId());
decryptedMembers.add(DecryptedMember.newBuilder() decryptedMembers.add(DecryptedMember.newBuilder()
.setUuid(memberAci.toByteString()) .setAciBytes(memberAci.toByteString())
.setJoinedAtRevision(member.getJoinedAtRevision()) .setJoinedAtRevision(member.getJoinedAtRevision())
.build()); .build());
} }
@ -466,7 +468,7 @@ public final class GroupsV2Operations {
for (PendingMember member : pendingMembersList) { for (PendingMember member : pendingMembersList) {
ServiceId pendingMemberServiceId = decryptServiceIdOrUnknown(member.getMember().getUserId()); ServiceId pendingMemberServiceId = decryptServiceIdOrUnknown(member.getMember().getUserId());
decryptedPendingMembers.add(DecryptedPendingMember.newBuilder() decryptedPendingMembers.add(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(pendingMemberServiceId.toByteString()) .setServiceIdBytes(pendingMemberServiceId.toByteString())
.build()); .build());
} }
@ -507,7 +509,7 @@ public final class GroupsV2Operations {
} }
for (BannedMember member : group.getBannedMembersList()) { for (BannedMember member : group.getBannedMembersList()) {
decryptedBannedMembers.add(DecryptedBannedMember.newBuilder().setServiceIdBinary(decryptServiceIdToBinary(member.getUserId())).setTimestamp(member.getTimestamp()).build()); decryptedBannedMembers.add(DecryptedBannedMember.newBuilder().setServiceIdBytes(decryptServiceIdToBinary(member.getUserId())).setTimestamp(member.getTimestamp()).build());
} }
return DecryptedGroup.newBuilder() return DecryptedGroup.newBuilder()
@ -560,9 +562,9 @@ public final class GroupsV2Operations {
// Field 1 // Field 1
if (source != null) { if (source != null) {
builder.setEditor(source.toByteString()); builder.setEditorServiceIdBytes(source.toByteString());
} else { } else {
builder.setEditor(decryptServiceIdToBinary(actions.getSourceUuid())); builder.setEditorServiceIdBytes(decryptServiceIdToBinary(actions.getSourceServiceId()));
} }
// Field 2 // Field 2
@ -579,14 +581,14 @@ public final class GroupsV2Operations {
// Field 4 // Field 4
for (GroupChange.Actions.DeleteMemberAction deleteMemberAction : actions.getDeleteMembersList()) { for (GroupChange.Actions.DeleteMemberAction deleteMemberAction : actions.getDeleteMembersList()) {
builder.addDeleteMembers(decryptServiceIdToBinary(deleteMemberAction.getDeletedUserId())); builder.addDeleteMembers(decryptAciToBinary(deleteMemberAction.getDeletedUserId()));
} }
// Field 5 // Field 5
for (GroupChange.Actions.ModifyMemberRoleAction modifyMemberRoleAction : actions.getModifyMemberRolesList()) { for (GroupChange.Actions.ModifyMemberRoleAction modifyMemberRoleAction : actions.getModifyMemberRolesList()) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setRole(modifyMemberRoleAction.getRole()) .setRole(modifyMemberRoleAction.getRole())
.setUuid(decryptServiceIdToBinary(modifyMemberRoleAction.getUserId()))); .setAciBytes(decryptAciToBinary(modifyMemberRoleAction.getUserId())));
} }
// Field 6 // Field 6
@ -607,7 +609,7 @@ public final class GroupsV2Operations {
builder.addModifiedProfileKeys(DecryptedMember.newBuilder() builder.addModifiedProfileKeys(DecryptedMember.newBuilder()
.setRole(Member.Role.UNKNOWN) .setRole(Member.Role.UNKNOWN)
.setJoinedAtRevision(-1) .setJoinedAtRevision(-1)
.setUuid(aci.toByteString()) .setAciBytes(aci.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))); .setProfileKey(ByteString.copyFrom(profileKey.serialize())));
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
throw new InvalidGroupStateException(e); throw new InvalidGroupStateException(e);
@ -618,25 +620,25 @@ public final class GroupsV2Operations {
for (GroupChange.Actions.AddPendingMemberAction addPendingMemberAction : actions.getAddPendingMembersList()) { for (GroupChange.Actions.AddPendingMemberAction addPendingMemberAction : actions.getAddPendingMembersList()) {
PendingMember added = addPendingMemberAction.getAdded(); PendingMember added = addPendingMemberAction.getAdded();
Member member = added.getMember(); Member member = added.getMember();
ByteString uuidCipherText = member.getUserId(); ByteString serviceIdCipherText = member.getUserId();
ServiceId serviceId = decryptServiceIdOrUnknown(uuidCipherText); ServiceId serviceId = decryptServiceIdOrUnknown(serviceIdCipherText);
builder.addNewPendingMembers(DecryptedPendingMember.newBuilder() builder.addNewPendingMembers(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(serviceId.toByteString()) .setServiceIdBytes(serviceId.toByteString())
.setUuidCipherText(uuidCipherText) .setServiceIdCipherText(serviceIdCipherText)
.setRole(member.getRole()) .setRole(member.getRole())
.setAddedByUuid(decryptServiceIdToBinary(added.getAddedByUserId())) .setAddedByAci(decryptAciToBinary(added.getAddedByUserId()))
.setTimestamp(added.getTimestamp())); .setTimestamp(added.getTimestamp()));
} }
// Field 8 // Field 8
for (GroupChange.Actions.DeletePendingMemberAction deletePendingMemberAction : actions.getDeletePendingMembersList()) { for (GroupChange.Actions.DeletePendingMemberAction deletePendingMemberAction : actions.getDeletePendingMembersList()) {
ByteString uuidCipherText = deletePendingMemberAction.getDeletedUserId(); ByteString serviceIdCipherText = deletePendingMemberAction.getDeletedUserId();
ServiceId serviceId = decryptServiceIdOrUnknown(uuidCipherText); ServiceId serviceId = decryptServiceIdOrUnknown(serviceIdCipherText);
builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(serviceId.toByteString()) .setServiceIdBytes(serviceId.toByteString())
.setUuidCipherText(uuidCipherText)); .setServiceIdCipherText(serviceIdCipherText));
} }
// Field 9 // Field 9
@ -657,7 +659,7 @@ public final class GroupsV2Operations {
builder.addPromotePendingMembers(DecryptedMember.newBuilder() builder.addPromotePendingMembers(DecryptedMember.newBuilder()
.setJoinedAtRevision(-1) .setJoinedAtRevision(-1)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setUuid(aci.toByteString()) .setAciBytes(aci.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))); .setProfileKey(ByteString.copyFrom(profileKey.serialize())));
} catch (InvalidInputException e) { } catch (InvalidInputException e) {
throw new InvalidGroupStateException(e); throw new InvalidGroupStateException(e);
@ -707,7 +709,7 @@ public final class GroupsV2Operations {
// Field 18 // Field 18
for (GroupChange.Actions.PromoteRequestingMemberAction promote : actions.getPromoteRequestingMembersList()) { for (GroupChange.Actions.PromoteRequestingMemberAction promote : actions.getPromoteRequestingMembersList()) {
builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder().setRole(promote.getRole()).setUuid(decryptServiceIdToBinary(promote.getUserId()))); builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder().setRole(promote.getRole()).setAciBytes(decryptAciToBinary(promote.getUserId())));
} }
// Field 19 // Field 19
@ -727,12 +729,12 @@ public final class GroupsV2Operations {
// Field 22 // Field 22
for (GroupChange.Actions.AddBannedMemberAction action : actions.getAddBannedMembersList()) { for (GroupChange.Actions.AddBannedMemberAction action : actions.getAddBannedMembersList()) {
builder.addNewBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(decryptServiceIdToBinary(action.getAdded().getUserId())).setTimestamp(action.getAdded().getTimestamp()).build()); builder.addNewBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBytes(decryptServiceIdToBinary(action.getAdded().getUserId())).setTimestamp(action.getAdded().getTimestamp()).build());
} }
// Field 23 // Field 23
for (GroupChange.Actions.DeleteBannedMemberAction action : actions.getDeleteBannedMembersList()) { for (GroupChange.Actions.DeleteBannedMemberAction action : actions.getDeleteBannedMembersList()) {
builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(decryptServiceIdToBinary(action.getDeletedUserId())).build()); builder.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBytes(decryptServiceIdToBinary(action.getDeletedUserId())).build());
} }
// Field 24 // Field 24
@ -745,13 +747,13 @@ public final class GroupsV2Operations {
throw new InvalidGroupStateException(); throw new InvalidGroupStateException();
} }
builder.setEditor(aci.toByteString()) builder.setEditorServiceIdBytes(aci.toByteString())
.addPromotePendingPniAciMembers(DecryptedMember.newBuilder() .addPromotePendingPniAciMembers(DecryptedMember.newBuilder()
.setUuid(aci.toByteString()) .setAciBytes(aci.toByteString())
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setJoinedAtRevision(actions.getRevision()) .setJoinedAtRevision(actions.getRevision())
.setPni(pni.toByteString())); .setPniBytes(pni.toByteString()));
} }
return builder.build(); return builder.build();
@ -776,7 +778,7 @@ public final class GroupsV2Operations {
ACI aci = decryptAci(member.getUserId()); ACI aci = decryptAci(member.getUserId());
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(aci.toByteString()) .setAciBytes(aci.toByteString())
.setJoinedAtRevision(member.getJoinedAtRevision()) .setJoinedAtRevision(member.getJoinedAtRevision())
.setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), aci)) .setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), aci))
.setRole(member.getRole()); .setRole(member.getRole());
@ -787,12 +789,12 @@ public final class GroupsV2Operations {
if (!(serviceId instanceof ACI)) { if (!(serviceId instanceof ACI)) {
throw new InvalidGroupStateException(); throw new InvalidGroupStateException();
} }
ACI serviceIdAsAci = (ACI)serviceId; ACI aci = (ACI) serviceId;
ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), serviceIdAsAci.getLibSignalAci()); ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), aci.getLibSignalAci());
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(serviceIdAsAci.toByteString()) .setAciBytes(aci.toByteString())
.setJoinedAtRevision(member.getJoinedAtRevision()) .setJoinedAtRevision(member.getJoinedAtRevision())
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setRole(member.getRole()); .setRole(member.getRole());
@ -813,9 +815,9 @@ public final class GroupsV2Operations {
} }
return DecryptedPendingMember.newBuilder() return DecryptedPendingMember.newBuilder()
.setServiceIdBinary(serviceId.toByteString()) .setServiceIdBytes(serviceId.toByteString())
.setUuidCipherText(userIdCipherText) .setServiceIdCipherText(userIdCipherText)
.setAddedByUuid(addedBy.toByteString()) .setAddedByAci(addedBy.toByteString())
.setRole(role) .setRole(role)
.setTimestamp(member.getTimestamp()) .setTimestamp(member.getTimestamp())
.build(); .build();
@ -828,7 +830,7 @@ public final class GroupsV2Operations {
ACI aci = decryptAci(member.getUserId()); ACI aci = decryptAci(member.getUserId());
return DecryptedRequestingMember.newBuilder() return DecryptedRequestingMember.newBuilder()
.setUuid(aci.toByteString()) .setAciBytes(aci.toByteString())
.setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), aci)) .setProfileKey(decryptProfileKeyToByteString(member.getProfileKey(), aci))
.setTimestamp(member.getTimestamp()) .setTimestamp(member.getTimestamp())
.build(); .build();
@ -844,12 +846,12 @@ public final class GroupsV2Operations {
if (!(serviceId instanceof ACI)) { if (!(serviceId instanceof ACI)) {
throw new InvalidGroupStateException(); throw new InvalidGroupStateException();
} }
ACI serviceIdAsAci = (ACI)serviceId; ACI aci = (ACI) serviceId;
ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), serviceIdAsAci.getLibSignalAci()); ProfileKey profileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCredentialPresentation.getProfileKeyCiphertext(), aci.getLibSignalAci());
return DecryptedRequestingMember.newBuilder() return DecryptedRequestingMember.newBuilder()
.setUuid(serviceIdAsAci.toByteString()) .setAciBytes(aci.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.build(); .build();
} }
@ -872,6 +874,10 @@ public final class GroupsV2Operations {
return decryptServiceId(userId).toByteString(); return decryptServiceId(userId).toByteString();
} }
private ByteString decryptAciToBinary(ByteString userId) throws InvalidGroupStateException, VerificationFailedException {
return decryptAci(userId).toByteString();
}
// Visible for Testing // Visible for Testing
public ByteString encryptServiceId(ServiceId serviceId) { public ByteString encryptServiceId(ServiceId serviceId) {
return ByteString.copyFrom(clientZkGroupCipher.encrypt(serviceId.getLibSignalServiceId()).serialize()); return ByteString.copyFrom(clientZkGroupCipher.encrypt(serviceId.getLibSignalServiceId()).serialize());
@ -904,6 +910,19 @@ public final class GroupsV2Operations {
} }
} }
private ACI decryptAciOrUnknown(ByteString userId) {
try {
ServiceId result = ServiceId.fromLibSignal(clientZkGroupCipher.decrypt(new UuidCiphertext(userId.toByteArray())));
if (result instanceof ACI) {
return (ACI) result;
} else {
return ACI.UNKNOWN;
}
} catch (InvalidInputException | VerificationFailedException e) {
return ACI.UNKNOWN;
}
}
ByteString encryptTitle(String title) { ByteString encryptTitle(String title) {
try { try {
GroupAttributeBlob blob = GroupAttributeBlob.newBuilder().setTitle(title).build(); GroupAttributeBlob blob = GroupAttributeBlob.newBuilder().setTitle(title).build();

View file

@ -110,12 +110,18 @@ sealed class ServiceId(val libSignalServiceId: LibSignalServiceId) {
@JvmStatic @JvmStatic
fun from(uuid: UUID): ACI = ACI(LibSignalAci(uuid)) fun from(uuid: UUID): ACI = ACI(LibSignalAci(uuid))
@JvmStatic
fun fromLibSignal(aci: LibSignalAci): ACI = ACI(aci)
@JvmStatic @JvmStatic
fun parseOrNull(raw: String?): ACI? = ServiceId.parseOrNull(raw).let { if (it is ACI) it else null } fun parseOrNull(raw: String?): ACI? = ServiceId.parseOrNull(raw).let { if (it is ACI) it else null }
@JvmStatic @JvmStatic
fun parseOrNull(raw: ByteArray?): ACI? = ServiceId.parseOrNull(raw).let { if (it is ACI) it else null } fun parseOrNull(raw: ByteArray?): ACI? = ServiceId.parseOrNull(raw).let { if (it is ACI) it else null }
@JvmStatic
fun parseOrNull(bytes: ByteString): ACI? = parseOrNull(bytes.toByteArray())
@JvmStatic @JvmStatic
@Throws(IllegalArgumentException::class) @Throws(IllegalArgumentException::class)
fun parseOrThrow(raw: String?): ACI = parseOrNull(raw) ?: throw IllegalArgumentException("Invalid ACI!") fun parseOrThrow(raw: String?): ACI = parseOrNull(raw) ?: throw IllegalArgumentException("Invalid ACI!")

View file

@ -37,11 +37,11 @@ public final class ServiceIds {
return Objects.requireNonNull(pni); return Objects.requireNonNull(pni);
} }
public boolean matches(UUID uuid) { public boolean matches(ServiceId serviceId) {
return uuid.equals(aci.getRawUuid()) || (pni != null && uuid.equals(pni.getRawUuid())); return serviceId.equals(aci) || (pni != null && serviceId.equals(pni));
} }
public boolean matches(ByteString uuid) { public boolean matches(ByteString serviceIdsBytes) {
if (aciByteString == null) { if (aciByteString == null) {
aciByteString = aci.toByteString(); aciByteString = aci.toByteString();
} }
@ -50,6 +50,6 @@ public final class ServiceIds {
pniByteString = pni.toByteString(); pniByteString = pni.toByteString();
} }
return uuid.equals(aciByteString) || uuid.equals(pniByteString); return serviceIdsBytes.equals(aciByteString) || serviceIdsBytes.equals(pniByteString);
} }
} }

View file

@ -13,44 +13,44 @@ import "Groups.proto";
// Decrypted version of Member // Decrypted version of Member
// Keep field numbers in step // Keep field numbers in step
message DecryptedMember { message DecryptedMember {
bytes uuid = 1; bytes aciBytes = 1;
Member.Role role = 2; Member.Role role = 2;
bytes profileKey = 3; bytes profileKey = 3;
uint32 joinedAtRevision = 5; uint32 joinedAtRevision = 5;
bytes pni = 6; bytes pniBytes = 6;
} }
message DecryptedPendingMember { message DecryptedPendingMember {
bytes serviceIdBinary = 1; bytes serviceIdBytes = 1;
Member.Role role = 2; Member.Role role = 2;
bytes addedByUuid = 3; bytes addedByAci = 3;
uint64 timestamp = 4; uint64 timestamp = 4;
bytes uuidCipherText = 5; bytes serviceIdCipherText = 5;
} }
message DecryptedRequestingMember { message DecryptedRequestingMember {
bytes uuid = 1; bytes aciBytes = 1;
bytes profileKey = 2; bytes profileKey = 2;
uint64 timestamp = 4; uint64 timestamp = 4;
} }
message DecryptedBannedMember { message DecryptedBannedMember {
bytes serviceIdBinary = 1; bytes serviceIdBytes = 1;
uint64 timestamp = 2; uint64 timestamp = 2;
} }
message DecryptedPendingMemberRemoval { message DecryptedPendingMemberRemoval {
bytes serviceIdBinary = 1; bytes serviceIdBytes = 1;
bytes uuidCipherText = 2; bytes serviceIdCipherText = 2;
} }
message DecryptedApproveMember { message DecryptedApproveMember {
bytes uuid = 1; bytes aciBytes = 1;
Member.Role role = 2; Member.Role role = 2;
} }
message DecryptedModifyMemberRole { message DecryptedModifyMemberRole {
bytes uuid = 1; bytes aciBytes = 1;
Member.Role role = 2; Member.Role role = 2;
} }
@ -74,7 +74,7 @@ message DecryptedGroup {
// Decrypted version of message GroupChange.Actions // Decrypted version of message GroupChange.Actions
// Keep field numbers in step // Keep field numbers in step
message DecryptedGroupChange { message DecryptedGroupChange {
bytes editor = 1; bytes editorServiceIdBytes = 1;
uint32 revision = 2; uint32 revision = 2;
repeated DecryptedMember newMembers = 3; repeated DecryptedMember newMembers = 3;
repeated bytes deleteMembers = 4; repeated bytes deleteMembers = 4;

View file

@ -182,7 +182,7 @@ message GroupChange {
bool announcementsOnly = 1; bool announcementsOnly = 1;
} }
bytes sourceUuid = 1; bytes sourceServiceId = 1;
uint32 revision = 2; uint32 revision = 2;
repeated AddMemberAction addMembers = 3; repeated AddMemberAction addMembers = 3;
repeated DeleteMemberAction deleteMembers = 4; repeated DeleteMemberAction deleteMembers = 4;

View file

@ -4,12 +4,10 @@ import com.google.protobuf.ByteString;
import org.junit.Test; import org.junit.Test;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange; import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval; import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval;
import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
import java.util.List; import java.util.List;
@ -19,54 +17,32 @@ import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
public final class DecryptedGroupUtilTest { public final class DecryptedGroupUtilTest {
@Test
public void can_extract_uuid_from_decrypted_member() {
UUID uuid = UUID.randomUUID();
DecryptedMember decryptedMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid))
.build();
UUID parsed = DecryptedGroupUtil.toUuid(decryptedMember);
assertEquals(uuid, parsed);
}
@Test
public void can_extract_uuid_from_bad_decrypted_member() {
DecryptedMember decryptedMember = DecryptedMember.newBuilder()
.setUuid(ByteString.copyFrom(new byte[0]))
.build();
UUID parsed = DecryptedGroupUtil.toUuid(decryptedMember);
assertEquals(UuidUtil.UNKNOWN_UUID, parsed);
}
@Test @Test
public void can_extract_editor_uuid_from_decrypted_group_change() { public void can_extract_editor_uuid_from_decrypted_group_change() {
UUID uuid = UUID.randomUUID(); ACI aci = ACI.from(UUID.randomUUID());
ByteString editor = UuidUtil.toByteString(uuid); ByteString editor = aci.toByteString();
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()
.setEditor(editor) .setEditorServiceIdBytes(editor)
.build(); .build();
UUID parsed = DecryptedGroupUtil.editorUuid(groupChange).get(); ServiceId parsed = DecryptedGroupUtil.editorServiceId(groupChange).get();
assertEquals(uuid, parsed); assertEquals(aci, parsed);
} }
@Test @Test
public void can_extract_uuid_from_decrypted_pending_member() { public void can_extract_uuid_from_decrypted_pending_member() {
ACI aci = ACI.from(UUID.randomUUID()); ACI aci = ACI.from(UUID.randomUUID());
DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder() DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(aci.toByteString()) .setServiceIdBytes(aci.toByteString())
.build(); .build();
ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBinary()); ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBytes());
assertEquals(aci, parsed); assertEquals(aci, parsed);
} }
@ -74,10 +50,10 @@ public final class DecryptedGroupUtilTest {
@Test @Test
public void can_extract_uuid_from_bad_decrypted_pending_member() { public void can_extract_uuid_from_bad_decrypted_pending_member() {
DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder() DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18))) .setServiceIdBytes(ByteString.copyFrom(Util.getSecretBytes(18)))
.build(); .build();
ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBinary()); ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBytes());
assertNull(parsed); assertNull(parsed);
} }
@ -87,13 +63,13 @@ public final class DecryptedGroupUtilTest {
ACI aci1 = ACI.from(UUID.randomUUID()); ACI aci1 = ACI.from(UUID.randomUUID());
ACI aci2 = ACI.from(UUID.randomUUID()); ACI aci2 = ACI.from(UUID.randomUUID());
DecryptedPendingMember decryptedMember1 = DecryptedPendingMember.newBuilder() DecryptedPendingMember decryptedMember1 = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(aci1.toByteString()) .setServiceIdBytes(aci1.toByteString())
.build(); .build();
DecryptedPendingMember decryptedMember2 = DecryptedPendingMember.newBuilder() DecryptedPendingMember decryptedMember2 = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(aci2.toByteString()) .setServiceIdBytes(aci2.toByteString())
.build(); .build();
DecryptedPendingMember decryptedMember3 = DecryptedPendingMember.newBuilder() DecryptedPendingMember decryptedMember3 = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18))) .setServiceIdBytes(ByteString.copyFrom(Util.getSecretBytes(18)))
.build(); .build();
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()
@ -112,13 +88,13 @@ public final class DecryptedGroupUtilTest {
ACI aci1 = ACI.from(UUID.randomUUID()); ACI aci1 = ACI.from(UUID.randomUUID());
ACI aci2 = ACI.from(UUID.randomUUID()); ACI aci2 = ACI.from(UUID.randomUUID());
DecryptedPendingMemberRemoval decryptedMember1 = DecryptedPendingMemberRemoval.newBuilder() DecryptedPendingMemberRemoval decryptedMember1 = DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(aci1.toByteString()) .setServiceIdBytes(aci1.toByteString())
.build(); .build();
DecryptedPendingMemberRemoval decryptedMember2 = DecryptedPendingMemberRemoval.newBuilder() DecryptedPendingMemberRemoval decryptedMember2 = DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(aci2.toByteString()) .setServiceIdBytes(aci2.toByteString())
.build(); .build();
DecryptedPendingMemberRemoval decryptedMember3 = DecryptedPendingMemberRemoval.newBuilder() DecryptedPendingMemberRemoval decryptedMember3 = DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18))) .setServiceIdBytes(ByteString.copyFrom(Util.getSecretBytes(18)))
.build(); .build();
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()

View file

@ -146,7 +146,7 @@ public final class DecryptedGroupUtil_apply_Test {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addDeleteMembers(member1.getUuid()) .addDeleteMembers(member1.getAciBytes())
.build()); .build());
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
@ -168,8 +168,8 @@ public final class DecryptedGroupUtil_apply_Test {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addDeleteMembers(member1.getUuid()) .addDeleteMembers(member1.getAciBytes())
.addDeleteMembers(member2.getUuid()) .addDeleteMembers(member2.getAciBytes())
.build()); .build());
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
@ -189,7 +189,7 @@ public final class DecryptedGroupUtil_apply_Test {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addDeleteMembers(member2.getUuid()) .addDeleteMembers(member2.getAciBytes())
.build()); .build());
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
@ -211,8 +211,8 @@ public final class DecryptedGroupUtil_apply_Test {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setUuid(member1.getUuid()).setRole(Member.Role.ADMINISTRATOR)) .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setAciBytes(member1.getAciBytes()).setRole(Member.Role.ADMINISTRATOR))
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setUuid(member2.getUuid()).setRole(Member.Role.DEFAULT)) .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setAciBytes(member2.getAciBytes()).setRole(Member.Role.DEFAULT))
.build()); .build());
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
@ -236,7 +236,7 @@ public final class DecryptedGroupUtil_apply_Test {
.setRevision(14) .setRevision(14)
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.setUuid(member2.getUuid()) .setAciBytes(member2.getAciBytes())
.build()) .build())
.build()); .build());
} }
@ -252,7 +252,7 @@ public final class DecryptedGroupUtil_apply_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setUuid(member1.getUuid()) .setAciBytes(member1.getAciBytes())
.build()) .build())
.build()); .build());
} }
@ -321,7 +321,7 @@ public final class DecryptedGroupUtil_apply_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addModifiedProfileKeys(DecryptedMember.newBuilder(DecryptedMember.newBuilder() .addModifiedProfileKeys(DecryptedMember.newBuilder(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(adminUuid)) .setAciBytes(UuidUtil.toByteString(adminUuid))
.build()) .build())
.setProfileKey(ByteString.copyFrom(profileKey2b.serialize()))) .setProfileKey(ByteString.copyFrom(profileKey2b.serialize())))
.build()); .build());
@ -411,7 +411,7 @@ public final class DecryptedGroupUtil_apply_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(11) .setRevision(11)
.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setUuidCipherText(ProtoTestUtils.encrypt(pendingUuid)) .setServiceIdCipherText(ProtoTestUtils.encrypt(pendingUuid))
.build()) .build())
.build()); .build());
@ -434,7 +434,7 @@ public final class DecryptedGroupUtil_apply_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(11) .setRevision(11)
.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setUuidCipherText(ProtoTestUtils.encrypt(pendingUuid)) .setServiceIdCipherText(ProtoTestUtils.encrypt(pendingUuid))
.build()) .build())
.build()); .build());
@ -785,7 +785,7 @@ public final class DecryptedGroupUtil_apply_Test {
.build(), .build(),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addDeleteRequestingMembers(member1.getUuid()) .addDeleteRequestingMembers(member1.getAciBytes())
.build()); .build());
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
@ -817,10 +817,10 @@ public final class DecryptedGroupUtil_apply_Test {
.setRevision(14) .setRevision(14)
.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setUuid(member1.getUuid())) .setAciBytes(member1.getAciBytes()))
.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.setUuid(member2.getUuid())) .setAciBytes(member2.getAciBytes()))
.build()); .build());
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
@ -844,7 +844,7 @@ public final class DecryptedGroupUtil_apply_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(14) .setRevision(14)
.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setUuid(member.getUuid())) .setAciBytes(member.getAciBytes()))
.build()); .build());
} }
@ -949,7 +949,7 @@ public final class DecryptedGroupUtil_apply_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(11) .setRevision(11)
.addDeleteBannedMembers(DecryptedBannedMember.newBuilder() .addDeleteBannedMembers(DecryptedBannedMember.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(bannedUuid)) .setServiceIdBytes(UuidUtil.toByteString(bannedUuid))
.build()) .build())
.build()); .build());

View file

@ -811,23 +811,23 @@ public final class GroupChangeUtil_resolveConflict_Test {
DecryptedMember member2 = pendingPniAciMember(UUID.randomUUID(), UUID.randomUUID(), randomProfileKey()); DecryptedMember member2 = pendingPniAciMember(UUID.randomUUID(), UUID.randomUUID(), randomProfileKey());
DecryptedGroup groupState = DecryptedGroup.newBuilder() DecryptedGroup groupState = DecryptedGroup.newBuilder()
.addMembers(member(UuidUtil.fromByteString(member1.getUuid()))) .addMembers(member(UuidUtil.fromByteString(member1.getAciBytes())))
.build(); .build();
DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder()
.addPromotePendingPniAciMembers(pendingPniAciMember(member1.getUuid(), member1.getPni(), member1.getProfileKey())) .addPromotePendingPniAciMembers(pendingPniAciMember(member1.getAciBytes(), member1.getPniBytes(), member1.getProfileKey()))
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getUuid(), member2.getPni(), member2.getProfileKey())) .addPromotePendingPniAciMembers(pendingPniAciMember(member2.getAciBytes(), member2.getPniBytes(), member2.getProfileKey()))
.build(); .build();
GroupChange.Actions change = GroupChange.Actions.newBuilder() GroupChange.Actions change = GroupChange.Actions.newBuilder()
.addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder().setPresentation(presentation(member1.getPni(), member1.getProfileKey()))) .addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder().setPresentation(presentation(member1.getPniBytes(), member1.getProfileKey())))
.addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder().setPresentation(presentation(member2.getPni(), member2.getProfileKey()))) .addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder().setPresentation(presentation(member2.getPniBytes(), member2.getProfileKey())))
.build(); .build();
GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build(); GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
GroupChange.Actions expected = GroupChange.Actions.newBuilder() GroupChange.Actions expected = GroupChange.Actions.newBuilder()
.addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder().setPresentation(presentation(member2.getPni(), member2.getProfileKey()))) .addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder().setPresentation(presentation(member2.getPniBytes(), member2.getProfileKey())))
.build(); .build();
assertEquals(expected, resolvedActions); assertEquals(expected, resolvedActions);
} }

View file

@ -661,18 +661,18 @@ public final class GroupChangeUtil_resolveConflict_decryptedOnly_Test {
DecryptedMember member2 = pendingPniAciMember(UUID.randomUUID(), UUID.randomUUID(), randomProfileKey()); DecryptedMember member2 = pendingPniAciMember(UUID.randomUUID(), UUID.randomUUID(), randomProfileKey());
DecryptedGroup groupState = DecryptedGroup.newBuilder() DecryptedGroup groupState = DecryptedGroup.newBuilder()
.addMembers(member(UuidUtil.fromByteString(member1.getUuid()))) .addMembers(member(UuidUtil.fromByteString(member1.getAciBytes())))
.build(); .build();
DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder() DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder()
.addPromotePendingPniAciMembers(pendingPniAciMember(member1.getUuid(), member1.getPni(), member1.getProfileKey())) .addPromotePendingPniAciMembers(pendingPniAciMember(member1.getAciBytes(), member1.getPniBytes(), member1.getProfileKey()))
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getUuid(), member2.getPni(), member2.getProfileKey())) .addPromotePendingPniAciMembers(pendingPniAciMember(member2.getAciBytes(), member2.getPniBytes(), member2.getProfileKey()))
.build(); .build();
DecryptedGroupChange resolvedChanges = GroupChangeUtil.resolveConflict(groupState, decryptedChange).build(); DecryptedGroupChange resolvedChanges = GroupChangeUtil.resolveConflict(groupState, decryptedChange).build();
DecryptedGroupChange expected = DecryptedGroupChange.newBuilder() DecryptedGroupChange expected = DecryptedGroupChange.newBuilder()
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getUuid(), member2.getPni(), member2.getProfileKey())) .addPromotePendingPniAciMembers(pendingPniAciMember(member2.getAciBytes(), member2.getPniBytes(), member2.getProfileKey()))
.build(); .build();
assertEquals(expected, resolvedChanges); assertEquals(expected, resolvedChanges);

View file

@ -14,7 +14,6 @@ import org.signal.storageservice.protos.groups.GroupChange.Actions.DeleteBannedM
import org.signal.storageservice.protos.groups.local.DecryptedBannedMember; import org.signal.storageservice.protos.groups.local.DecryptedBannedMember;
import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
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;
@ -47,36 +46,36 @@ public final class GroupsV2Operations_ban_Test {
@Test @Test
public void addBanToEmptyList() { public void addBanToEmptyList() {
UUID ban = UUID.randomUUID(); ACI ban = ACI.from(UUID.randomUUID());
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(Collections.singleton(ban), GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(Collections.singleton(ban),
false, false,
Collections.emptyList()); Collections.emptyList());
assertThat(banUuidsChange.getAddBannedMembersCount(), is(1)); assertThat(banUuidsChange.getAddBannedMembersCount(), is(1));
assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(ban)))); assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ban)));
} }
@Test @Test
public void addBanToPartialFullList() { public void addBanToPartialFullList() {
UUID toBan = UUID.randomUUID(); ACI toBan = ACI.from(UUID.randomUUID());
List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(5); List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(5);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
alreadyBanned.add(bannedMember(UUID.randomUUID())); alreadyBanned.add(bannedMember(UUID.randomUUID()));
} }
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(Collections.singleton(toBan), GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(Collections.singleton(toBan),
false, false,
alreadyBanned); alreadyBanned);
assertThat(banUuidsChange.getAddBannedMembersCount(), is(1)); assertThat(banUuidsChange.getAddBannedMembersCount(), is(1));
assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(toBan)))); assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(toBan)));
} }
@Test @Test
public void addBanToFullList() { public void addBanToFullList() {
UUID toBan = UUID.randomUUID(); ACI toBan = ACI.from(UUID.randomUUID());
List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(10); List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(10);
DecryptedBannedMember oldest = null; DecryptedBannedMember oldest = null;
@ -90,23 +89,23 @@ public final class GroupsV2Operations_ban_Test {
Collections.shuffle(alreadyBanned); Collections.shuffle(alreadyBanned);
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(Collections.singleton(toBan), GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(Collections.singleton(toBan),
false, false,
alreadyBanned); alreadyBanned);
assertThat(banUuidsChange.getDeleteBannedMembersCount(), is(1)); assertThat(banUuidsChange.getDeleteBannedMembersCount(), is(1));
assertThat(banUuidsChange.getDeleteBannedMembers(0).getDeletedUserId(), is(groupOperations.encryptServiceId(ServiceId.parseOrThrow(oldest.getServiceIdBinary())))); assertThat(banUuidsChange.getDeleteBannedMembers(0).getDeletedUserId(), is(groupOperations.encryptServiceId(ServiceId.parseOrThrow(oldest.getServiceIdBytes()))));
assertThat(banUuidsChange.getAddBannedMembersCount(), is(1)); assertThat(banUuidsChange.getAddBannedMembersCount(), is(1));
assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(toBan)))); assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(toBan)));
} }
@Test @Test
public void addMultipleBanToFullList() { public void addMultipleBanToFullList() {
List<UUID> toBan = new ArrayList<>(); List<ACI> toBan = new ArrayList<>();
toBan.add(UUID.randomUUID()); toBan.add(ACI.from(UUID.randomUUID()));
toBan.add(UUID.randomUUID()); toBan.add(ACI.from(UUID.randomUUID()));
List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(10); List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(10);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
@ -114,12 +113,12 @@ public final class GroupsV2Operations_ban_Test {
} }
List<ByteString> oldest = new ArrayList<>(2); List<ByteString> oldest = new ArrayList<>(2);
oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(0).getServiceIdBinary()))); oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(0).getServiceIdBytes())));
oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(1).getServiceIdBinary()))); oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(1).getServiceIdBytes())));
Collections.shuffle(alreadyBanned); Collections.shuffle(alreadyBanned);
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(new HashSet<>(toBan), GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(new HashSet<>(toBan),
false, false,
alreadyBanned); alreadyBanned);
@ -137,7 +136,7 @@ public final class GroupsV2Operations_ban_Test {
.map(AddBannedMemberAction::getAdded) .map(AddBannedMemberAction::getAdded)
.map(BannedMember::getUserId) .map(BannedMember::getUserId)
.collect(Collectors.toList()), .collect(Collectors.toList()),
hasItems(groupOperations.encryptServiceId(ACI.from(toBan.get(0))), hasItems(groupOperations.encryptServiceId(toBan.get(0)),
groupOperations.encryptServiceId(ACI.from(toBan.get(1))))); groupOperations.encryptServiceId(toBan.get(1))));
} }
} }

View file

@ -109,7 +109,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setJoinedAtRevision(10) .setJoinedAtRevision(10)
.setUuid(newMember.toByteString()))); .setAciBytes(newMember.toByteString())));
} }
@Test @Test
@ -126,7 +126,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setJoinedAtRevision(10) .setJoinedAtRevision(10)
.setUuid(newMember.toByteString()))); .setAciBytes(newMember.toByteString())));
} }
@Test @Test
@ -144,7 +144,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setJoinedAtRevision(10) .setJoinedAtRevision(10)
.setUuid(newMember.toByteString()))); .setAciBytes(newMember.toByteString())));
} }
@Test(expected = InvalidGroupStateException.class) @Test(expected = InvalidGroupStateException.class)
@ -161,13 +161,13 @@ public final class GroupsV2Operations_decrypt_change_Test {
@Test @Test
public void can_decrypt_member_removals_field4() { public void can_decrypt_member_removals_field4() {
UUID oldMember = 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())
.setRevision(10), .setRevision(10),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(10) .setRevision(10)
.addDeleteMembers(UuidUtil.toByteString(oldMember))); .addDeleteMembers(oldMember.toByteString()));
} }
@Test(expected = InvalidGroupStateException.class) @Test(expected = InvalidGroupStateException.class)
@ -188,7 +188,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
assertDecryption(groupOperations.createChangeMemberRole(member, Member.Role.ADMINISTRATOR), assertDecryption(groupOperations.createChangeMemberRole(member, Member.Role.ADMINISTRATOR),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setUuid(member.toByteString()) .setAciBytes(member.toByteString())
.setRole(Member.Role.ADMINISTRATOR))); .setRole(Member.Role.ADMINISTRATOR)));
} }
@ -199,7 +199,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
assertDecryption(groupOperations.createChangeMemberRole(member, Member.Role.DEFAULT), assertDecryption(groupOperations.createChangeMemberRole(member, Member.Role.DEFAULT),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setUuid(member.toByteString()) .setAciBytes(member.toByteString())
.setRole(Member.Role.DEFAULT))); .setRole(Member.Role.DEFAULT)));
} }
@ -217,7 +217,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
.setRole(Member.Role.UNKNOWN) .setRole(Member.Role.UNKNOWN)
.setJoinedAtRevision(-1) .setJoinedAtRevision(-1)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setUuid(self.toByteString()))); .setAciBytes(self.toByteString())));
} }
@Test @Test
@ -231,10 +231,10 @@ public final class GroupsV2Operations_decrypt_change_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(13) .setRevision(13)
.addNewPendingMembers(DecryptedPendingMember.newBuilder() .addNewPendingMembers(DecryptedPendingMember.newBuilder()
.setAddedByUuid(self.toByteString()) .setAddedByAci(self.toByteString())
.setUuidCipherText(groupOperations.encryptServiceId(newMember)) .setServiceIdCipherText(groupOperations.encryptServiceId(newMember))
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setServiceIdBinary(newMember.toByteString()))); .setServiceIdBytes(newMember.toByteString())));
} }
@Test @Test
@ -245,8 +245,8 @@ public final class GroupsV2Operations_decrypt_change_Test {
assertDecryption(groupOperations.createRemoveInvitationChange(Collections.singleton(uuidCiphertext)), assertDecryption(groupOperations.createRemoveInvitationChange(Collections.singleton(uuidCiphertext)),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(oldMember.toByteString()) .setServiceIdBytes(oldMember.toByteString())
.setUuidCipherText(ByteString.copyFrom(uuidCiphertext.serialize())))); .setServiceIdCipherText(ByteString.copyFrom(uuidCiphertext.serialize()))));
} }
@Test @Test
@ -259,8 +259,8 @@ public final class GroupsV2Operations_decrypt_change_Test {
.setDeletedUserId(ByteString.copyFrom(uuidCiphertext))), .setDeletedUserId(ByteString.copyFrom(uuidCiphertext))),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(UuidUtil.UNKNOWN_UUID)) .setServiceIdBytes(UuidUtil.toByteString(UuidUtil.UNKNOWN_UUID))
.setUuidCipherText(ByteString.copyFrom(uuidCiphertext)))); .setServiceIdCipherText(ByteString.copyFrom(uuidCiphertext))));
} }
@Test @Test
@ -272,7 +272,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
assertDecryption(groupOperations.createAcceptInviteChange(groupCandidate.getExpiringProfileKeyCredential().get()), assertDecryption(groupOperations.createAcceptInviteChange(groupCandidate.getExpiringProfileKeyCredential().get()),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.addPromotePendingMembers(DecryptedMember.newBuilder() .addPromotePendingMembers(DecryptedMember.newBuilder()
.setUuid(newMember.toByteString()) .setAciBytes(newMember.toByteString())
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setJoinedAtRevision(-1))); .setJoinedAtRevision(-1)));
@ -339,20 +339,20 @@ public final class GroupsV2Operations_decrypt_change_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(10) .setRevision(10)
.addNewRequestingMembers(DecryptedRequestingMember.newBuilder() .addNewRequestingMembers(DecryptedRequestingMember.newBuilder()
.setUuid(newRequestingMember.toByteString()) .setAciBytes(newRequestingMember.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize())))); .setProfileKey(ByteString.copyFrom(profileKey.serialize()))));
} }
@Test @Test
public void can_decrypt_member_requests_refusals_field17() { public void can_decrypt_member_requests_refusals_field17() {
UUID newRequestingMember = 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())
.setRevision(10), .setRevision(10),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(10) .setRevision(10)
.addDeleteRequestingMembers(UuidUtil.toByteString(newRequestingMember)) .addDeleteRequestingMembers(newRequestingMember.toByteString())
.addNewBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBinary(UuidUtil.toByteString(newRequestingMember)).build())); .addNewBannedMembers(DecryptedBannedMember.newBuilder().setServiceIdBytes(newRequestingMember.toByteString()).build()));
} }
@Test @Test
@ -365,7 +365,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
.setRevision(15) .setRevision(15)
.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setUuid(UuidUtil.toByteString(newRequestingMember)))); .setAciBytes(UuidUtil.toByteString(newRequestingMember))));
} }
@Test @Test
@ -397,14 +397,14 @@ public final class GroupsV2Operations_decrypt_change_Test {
@Test @Test
public void can_decrypt_member_bans_field22() { public void can_decrypt_member_bans_field22() {
UUID ban = UUID.randomUUID(); ACI ban = ACI.from(UUID.randomUUID());
assertDecryption(groupOperations.createBanUuidsChange(Collections.singleton(ban), false, Collections.emptyList()) assertDecryption(groupOperations.createBanServiceIdsChange(Collections.singleton(ban), false, Collections.emptyList())
.setRevision(13), .setRevision(13),
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(13) .setRevision(13)
.addNewBannedMembers(DecryptedBannedMember.newBuilder() .addNewBannedMembers(DecryptedBannedMember.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(ban)))); .setServiceIdBytes(ban.toByteString())));
} }
@Test @Test
@ -416,7 +416,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setRevision(13) .setRevision(13)
.addDeleteBannedMembers(DecryptedBannedMember.newBuilder() .addDeleteBannedMembers(DecryptedBannedMember.newBuilder()
.setServiceIdBinary(ban.toByteString()))); .setServiceIdBytes(ban.toByteString())));
} }
@Test @Test
@ -426,7 +426,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
ProfileKey profileKey = newProfileKey(); ProfileKey profileKey = newProfileKey();
GroupChange.Actions.Builder builder = GroupChange.Actions.newBuilder() GroupChange.Actions.Builder builder = GroupChange.Actions.newBuilder()
.setSourceUuid(groupOperations.encryptServiceId(memberPni)) .setSourceServiceId(groupOperations.encryptServiceId(memberPni))
.setRevision(5) .setRevision(5)
.addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder() .addPromotePendingPniAciMembers(GroupChange.Actions.PromotePendingPniAciMemberProfileKeyAction.newBuilder()
.setUserId(groupOperations.encryptServiceId(memberAci)) .setUserId(groupOperations.encryptServiceId(memberAci))
@ -435,11 +435,11 @@ public final class GroupsV2Operations_decrypt_change_Test {
assertDecryptionWithEditorSet(builder, assertDecryptionWithEditorSet(builder,
DecryptedGroupChange.newBuilder() DecryptedGroupChange.newBuilder()
.setEditor(memberAci.toByteString()) .setEditorServiceIdBytes(memberAci.toByteString())
.setRevision(5) .setRevision(5)
.addPromotePendingPniAciMembers(DecryptedMember.newBuilder() .addPromotePendingPniAciMembers(DecryptedMember.newBuilder()
.setUuid(memberAci.toByteString()) .setAciBytes(memberAci.toByteString())
.setPni(memberPni.toByteString()) .setPniBytes(memberPni.toByteString())
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.setJoinedAtRevision(5))); .setJoinedAtRevision(5)));
@ -484,7 +484,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.setSourceUuid(groupOperations.encryptServiceId(editor)), expectedDecrypted.setEditor(editor.toByteString())); assertDecryptionWithEditorSet(inputChange.setSourceServiceId(groupOperations.encryptServiceId(editor)), expectedDecrypted.setEditorServiceIdBytes(editor.toByteString()));
} }
void assertDecryptionWithEditorSet(GroupChange.Actions.Builder inputChange, void assertDecryptionWithEditorSet(GroupChange.Actions.Builder inputChange,

View file

@ -145,13 +145,13 @@ public final class GroupsV2Operations_decrypt_group_Test {
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
.addMembers(DecryptedMember.newBuilder() .addMembers(DecryptedMember.newBuilder()
.setJoinedAtRevision(4) .setJoinedAtRevision(4)
.setUuid(admin1.toByteString()) .setAciBytes(admin1.toByteString())
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.setProfileKey(ByteString.copyFrom(adminProfileKey.serialize()))) .setProfileKey(ByteString.copyFrom(adminProfileKey.serialize())))
.addMembers(DecryptedMember.newBuilder() .addMembers(DecryptedMember.newBuilder()
.setJoinedAtRevision(7) .setJoinedAtRevision(7)
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setUuid(member1.toByteString()) .setAciBytes(member1.toByteString())
.setProfileKey(ByteString.copyFrom(memberProfileKey.serialize()))) .setProfileKey(ByteString.copyFrom(memberProfileKey.serialize())))
.build().getMembersList(), .build().getMembersList(),
decryptedGroup.getMembersList()); decryptedGroup.getMembersList());
@ -189,22 +189,22 @@ public final class GroupsV2Operations_decrypt_group_Test {
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
.addPendingMembers(DecryptedPendingMember.newBuilder() .addPendingMembers(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(admin1.toByteString()) .setServiceIdBytes(admin1.toByteString())
.setUuidCipherText(groupOperations.encryptServiceId(admin1)) .setServiceIdCipherText(groupOperations.encryptServiceId(admin1))
.setTimestamp(100) .setTimestamp(100)
.setAddedByUuid(inviter1.toByteString()) .setAddedByAci(inviter1.toByteString())
.setRole(Member.Role.ADMINISTRATOR)) .setRole(Member.Role.ADMINISTRATOR))
.addPendingMembers(DecryptedPendingMember.newBuilder() .addPendingMembers(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(member1.toByteString()) .setServiceIdBytes(member1.toByteString())
.setUuidCipherText(groupOperations.encryptServiceId(member1)) .setServiceIdCipherText(groupOperations.encryptServiceId(member1))
.setTimestamp(200) .setTimestamp(200)
.setAddedByUuid(inviter1.toByteString()) .setAddedByAci(inviter1.toByteString())
.setRole(Member.Role.DEFAULT)) .setRole(Member.Role.DEFAULT))
.addPendingMembers(DecryptedPendingMember.newBuilder() .addPendingMembers(DecryptedPendingMember.newBuilder()
.setServiceIdBinary(member2.toByteString()) .setServiceIdBytes(member2.toByteString())
.setUuidCipherText(groupOperations.encryptServiceId(member2)) .setServiceIdCipherText(groupOperations.encryptServiceId(member2))
.setTimestamp(1500) .setTimestamp(1500)
.setAddedByUuid(inviter2.toByteString()) .setAddedByAci(inviter2.toByteString())
.setRole(Member.Role.DEFAULT)) .setRole(Member.Role.DEFAULT))
.build().getPendingMembersList(), .build().getPendingMembersList(),
decryptedGroup.getPendingMembersList()); decryptedGroup.getPendingMembersList());
@ -232,11 +232,11 @@ public final class GroupsV2Operations_decrypt_group_Test {
assertEquals(DecryptedGroup.newBuilder() assertEquals(DecryptedGroup.newBuilder()
.addRequestingMembers(DecryptedRequestingMember.newBuilder() .addRequestingMembers(DecryptedRequestingMember.newBuilder()
.setUuid(admin1.toByteString()) .setAciBytes(admin1.toByteString())
.setProfileKey(ByteString.copyFrom(adminProfileKey.serialize())) .setProfileKey(ByteString.copyFrom(adminProfileKey.serialize()))
.setTimestamp(5000)) .setTimestamp(5000))
.addRequestingMembers(DecryptedRequestingMember.newBuilder() .addRequestingMembers(DecryptedRequestingMember.newBuilder()
.setUuid(member1.toByteString()) .setAciBytes(member1.toByteString())
.setProfileKey(ByteString.copyFrom(memberProfileKey.serialize())) .setProfileKey(ByteString.copyFrom(memberProfileKey.serialize()))
.setTimestamp(15000)) .setTimestamp(15000))
.build().getRequestingMembersList(), .build().getRequestingMembersList(),
@ -288,7 +288,7 @@ public final class GroupsV2Operations_decrypt_group_Test {
DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group); DecryptedGroup decryptedGroup = groupOperations.decryptGroup(group);
assertEquals(1, decryptedGroup.getBannedMembersCount()); assertEquals(1, decryptedGroup.getBannedMembersCount());
assertEquals(DecryptedBannedMember.newBuilder().setServiceIdBinary(member1.toByteString()).build(), decryptedGroup.getBannedMembers(0)); assertEquals(DecryptedBannedMember.newBuilder().setServiceIdBytes(member1.toByteString()).build(), decryptedGroup.getBannedMembers(0));
} }
private ByteString encryptProfileKey(ACI aci, ProfileKey profileKey) { private ByteString encryptProfileKey(ACI aci, ProfileKey profileKey) {

View file

@ -65,14 +65,14 @@ final class ProtoTestUtils {
static DecryptedModifyMemberRole promoteAdmin(UUID member) { static DecryptedModifyMemberRole promoteAdmin(UUID member) {
return DecryptedModifyMemberRole.newBuilder() return DecryptedModifyMemberRole.newBuilder()
.setUuid(UuidUtil.toByteString(member)) .setAciBytes(UuidUtil.toByteString(member))
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.build(); .build();
} }
static DecryptedModifyMemberRole demoteAdmin(UUID member) { static DecryptedModifyMemberRole demoteAdmin(UUID member) {
return DecryptedModifyMemberRole.newBuilder() return DecryptedModifyMemberRole.newBuilder()
.setUuid(UuidUtil.toByteString(member)) .setAciBytes(UuidUtil.toByteString(member))
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build(); .build();
} }
@ -91,14 +91,14 @@ final class ProtoTestUtils {
static DecryptedMember member(UUID uuid) { static DecryptedMember member(UUID uuid) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid)) .setAciBytes(UuidUtil.toByteString(uuid))
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build(); .build();
} }
static DecryptedMember member(UUID uuid, ByteString profileKey, int joinedAtRevision) { static DecryptedMember member(UUID uuid, ByteString profileKey, int joinedAtRevision) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid)) .setAciBytes(UuidUtil.toByteString(uuid))
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.setJoinedAtRevision(joinedAtRevision) .setJoinedAtRevision(joinedAtRevision)
.setProfileKey(profileKey) .setProfileKey(profileKey)
@ -107,15 +107,15 @@ final class ProtoTestUtils {
static DecryptedPendingMemberRemoval pendingMemberRemoval(UUID uuid) { static DecryptedPendingMemberRemoval pendingMemberRemoval(UUID uuid) {
return DecryptedPendingMemberRemoval.newBuilder() return DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(uuid)) .setServiceIdBytes(UuidUtil.toByteString(uuid))
.setUuidCipherText(encrypt(uuid)) .setServiceIdCipherText(encrypt(uuid))
.build(); .build();
} }
static DecryptedPendingMember pendingMember(UUID uuid) { static DecryptedPendingMember pendingMember(UUID uuid) {
return DecryptedPendingMember.newBuilder() return DecryptedPendingMember.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(uuid)) .setServiceIdBytes(UuidUtil.toByteString(uuid))
.setUuidCipherText(encrypt(uuid)) .setServiceIdCipherText(encrypt(uuid))
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build(); .build();
} }
@ -126,14 +126,14 @@ final class ProtoTestUtils {
static DecryptedRequestingMember requestingMember(UUID uuid, ProfileKey profileKey) { static DecryptedRequestingMember requestingMember(UUID uuid, ProfileKey profileKey) {
return DecryptedRequestingMember.newBuilder() return DecryptedRequestingMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid)) .setAciBytes(UuidUtil.toByteString(uuid))
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.build(); .build();
} }
static DecryptedBannedMember bannedMember(UUID uuid) { static DecryptedBannedMember bannedMember(UUID uuid) {
return DecryptedBannedMember.newBuilder() return DecryptedBannedMember.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(uuid)) .setServiceIdBytes(UuidUtil.toByteString(uuid))
.build(); .build();
} }
@ -147,7 +147,7 @@ final class ProtoTestUtils {
private static DecryptedApproveMember approve(UUID uuid, Member.Role role) { private static DecryptedApproveMember approve(UUID uuid, Member.Role role) {
return DecryptedApproveMember.newBuilder() return DecryptedApproveMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid)) .setAciBytes(UuidUtil.toByteString(uuid))
.setRole(role) .setRole(role)
.build(); .build();
} }
@ -158,16 +158,16 @@ final class ProtoTestUtils {
static DecryptedMember pendingPniAciMember(UUID uuid, UUID pni, ProfileKey profileKey) { static DecryptedMember pendingPniAciMember(UUID uuid, UUID pni, ProfileKey profileKey) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid)) .setAciBytes(UuidUtil.toByteString(uuid))
.setPni(UuidUtil.toByteString(pni)) .setPniBytes(UuidUtil.toByteString(pni))
.setProfileKey(ByteString.copyFrom(profileKey.serialize())) .setProfileKey(ByteString.copyFrom(profileKey.serialize()))
.build(); .build();
} }
static DecryptedMember pendingPniAciMember(ByteString uuid, ByteString pni, ByteString profileKey) { static DecryptedMember pendingPniAciMember(ByteString uuid, ByteString pni, ByteString profileKey) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(uuid) .setAciBytes(uuid)
.setPni(pni) .setPniBytes(pni)
.setProfileKey(profileKey) .setProfileKey(profileKey)
.build(); .build();
} }
@ -178,7 +178,7 @@ final class ProtoTestUtils {
static DecryptedMember admin(UUID uuid) { static DecryptedMember admin(UUID uuid) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(uuid)) .setAciBytes(UuidUtil.toByteString(uuid))
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.build(); .build();
} }
@ -191,14 +191,14 @@ final class ProtoTestUtils {
static DecryptedMember asAdmin(DecryptedMember member) { static DecryptedMember asAdmin(DecryptedMember member) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(member.getUuid()) .setAciBytes(member.getAciBytes())
.setRole(Member.Role.ADMINISTRATOR) .setRole(Member.Role.ADMINISTRATOR)
.build(); .build();
} }
static DecryptedMember asMember(DecryptedMember member) { static DecryptedMember asMember(DecryptedMember member) {
return DecryptedMember.newBuilder() return DecryptedMember.newBuilder()
.setUuid(member.getUuid()) .setAciBytes(member.getAciBytes())
.setRole(Member.Role.DEFAULT) .setRole(Member.Role.DEFAULT)
.build(); .build();
} }