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

View file

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

View file

@ -44,7 +44,6 @@ class ContactRecordProcessorTest {
}
val remote2 = buildRecord(STORAGE_ID_C) {
setAci(PNI_A.toString())
setPni(PNI_A.toString())
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.recipients.Recipient
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
/**
* Helper methods for creating groups for message processing tests et al.
*/
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()
.setUuid(serviceId.toByteString())
.setAciBytes(aci.toByteString())
.setJoinedAtRevision(revision)
.setRole(role)
.build()
@ -43,7 +43,7 @@ object GroupTestingUtils {
}
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)

View file

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

View file

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

View file

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

View file

@ -79,10 +79,10 @@ final class GroupsV2UpdateMessageProducer {
}
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 (selfIds.matches(foundingMemberUuid)) {
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() ||
(selfIds.getPni() != null && DecryptedGroupUtil.findMemberByUuid(group.getMembersList(), selfIds.getPni().getRawUuid()).isPresent()))
{
if (DecryptedGroupUtil.findMemberByAci(group.getMembersList(), selfIds.getAci()).isPresent()) {
return updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16);
} else {
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<>();
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);
describeUnknownEditorModifyMemberRoles(change, updates);
@ -167,12 +172,12 @@ final class GroupsV2UpdateMessageProducer {
* Handles case of future protocol versions where we don't know what has changed.
*/
private void describeUnknownChange(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedMember member : change.getNewMembersList()) {
boolean newMemberIsYou = selfIds.matches(member.getUuid());
boolean newMemberIsYou = selfIds.matches(member.getAciBytes());
if (editorIsYou) {
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));
} 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 {
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 {
if (member.getUuid().equals(change.getEditor())) {
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group_via_the_group_link, member.getUuid(), R.drawable.ic_update_group_accept_16));
if (member.getAciBytes().equals(change.getEditorServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_joined_the_group_via_the_group_link, member.getAciBytes(), R.drawable.ic_update_group_accept_16));
} 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) {
for (DecryptedMember member : change.getNewMembersList()) {
boolean newMemberIsYou = selfIds.matches(member.getUuid());
boolean newMemberIsYou = selfIds.matches(member.getAciBytes());
if (newMemberIsYou) {
updates.add(0, updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (ByteString member : change.getDeleteMembersList()) {
boolean removedMemberIsYou = selfIds.matches(member);
@ -232,12 +237,12 @@ final class GroupsV2UpdateMessageProducer {
}
} else {
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 {
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));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedModifyMemberRole roleChange : change.getModifyMemberRolesList()) {
boolean changedMemberIsYou = selfIds.matches(roleChange.getUuid());
boolean changedMemberIsYou = selfIds.matches(roleChange.getAciBytes());
if (roleChange.getRole() == Member.Role.ADMINISTRATOR) {
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 {
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 {
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 {
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 {
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 {
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) {
for (DecryptedModifyMemberRole roleChange : change.getModifyMemberRolesList()) {
boolean changedMemberIsYou = selfIds.matches(roleChange.getUuid());
boolean changedMemberIsYou = selfIds.matches(roleChange.getAciBytes());
if (roleChange.getRole() == Member.Role.ADMINISTRATOR) {
if (changedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_now_an_admin), R.drawable.ic_update_group_role_16));
} 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 {
if (changedMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_are_no_longer_an_admin), R.drawable.ic_update_group_role_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
int notYouInviteCount = 0;
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary());
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBytes());
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 {
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 {
notYouInviteCount++;
}
@ -325,7 +330,7 @@ final class GroupsV2UpdateMessageProducer {
}
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;
for (DecryptedPendingMember invitee : change.getNewPendingMembersList()) {
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBinary());
boolean newMemberIsYou = selfIds.matches(invitee.getServiceIdBytes());
if (newMemberIsYou) {
UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByUuid());
UUID uuid = UuidUtil.fromByteStringOrUnknown(invitee.getAddedByAci());
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));
} 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 {
notYouInviteCount++;
@ -354,19 +359,19 @@ final class GroupsV2UpdateMessageProducer {
}
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;
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
boolean decline = invitee.getServiceIdBinary().equals(change.getEditor());
boolean decline = invitee.getServiceIdBytes().equals(change.getEditorServiceIdBytes());
if (decline) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_declined_the_invitation_to_the_group), R.drawable.ic_update_group_decline_16));
} else {
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())) {
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, change.getEditor(), R.drawable.ic_update_group_decline_16));
} else if (selfIds.matches(invitee.getServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_revoked_your_invitation_to_the_group, change.getEditorServiceIdBytes(), R.drawable.ic_update_group_decline_16));
} else {
notDeclineCount++;
}
@ -376,7 +381,7 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) {
updates.add(updateDescription(context.getResources().getQuantityString(R.plurals.MessageRecord_you_revoked_invites, notDeclineCount, notDeclineCount), R.drawable.ic_update_group_decline_16));
} 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;
for (DecryptedPendingMemberRemoval invitee : change.getDeletePendingMembersList()) {
boolean inviteeWasYou = selfIds.matches(invitee.getServiceIdBinary());
boolean inviteeWasYou = selfIds.matches(invitee.getServiceIdBytes());
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));
@ -400,26 +405,26 @@ final class GroupsV2UpdateMessageProducer {
}
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()) {
ByteString uuid = newMember.getUuid();
boolean newMemberIsYou = selfIds.matches(uuid);
ByteString aci = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(aci);
if (editorIsYou) {
if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_accepted_invite), R.drawable.ic_update_group_accept_16));
} 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 {
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 {
if (uuid.equals(change.getEditor())) {
updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, uuid, R.drawable.ic_update_group_accept_16));
if (aci.equals(change.getEditorServiceIdBytes())) {
updates.add(updateDescription(R.string.MessageRecord_s_accepted_invite, aci, R.drawable.ic_update_group_accept_16));
} 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) {
for (DecryptedMember newMember : change.getPromotePendingMembersList()) {
ByteString uuid = newMember.getUuid();
boolean newMemberIsYou = selfIds.matches(uuid);
ByteString aci = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(aci);
if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewTitle()) {
String newTitle = StringUtil.isolateBidi(change.getNewTitle().getValue());
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));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewDescription()) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_description), R.drawable.ic_update_group_name_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewAvatar()) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_changed_the_group_avatar), R.drawable.ic_update_group_avatar_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.hasNewTimer()) {
String time = ExpirationUtil.getExpirationDisplayValue(context, change.getNewTimer().getDuration());
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.getNewAttributeAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewAttributeAccess());
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));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.getNewMemberAccess() != AccessControl.AccessRequired.UNKNOWN) {
String accessLevel = GV2AccessLevelUtil.toString(context, change.getNewMemberAccess());
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));
} 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();
}
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
boolean groupLinkEnabled = false;
switch (change.getNewInviteLinkAccess()) {
@ -578,9 +583,9 @@ final class GroupsV2UpdateMessageProducer {
}
} else {
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 {
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;
@ -594,9 +599,9 @@ final class GroupsV2UpdateMessageProducer {
}
} else {
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 {
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;
@ -604,7 +609,7 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_turned_off_the_group_link), R.drawable.ic_update_group_role_16));
} 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;
}
@ -613,7 +618,7 @@ final class GroupsV2UpdateMessageProducer {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_reset_the_group_link), R.drawable.ic_update_group_role_16));
} 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());
for (DecryptedRequestingMember member : change.getNewRequestingMembersList()) {
boolean requestingMemberIsYou = selfIds.matches(member.getUuid());
boolean requestingMemberIsYou = selfIds.matches(member.getAciBytes());
if (requestingMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_sent_a_request_to_join_the_group), R.drawable.ic_update_group_16));
} 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,
change.getDeleteRequestingMembersCount(),
member.getUuid(),
member.getAciBytes(),
change.getDeleteRequestingMembersCount(),
R.drawable.ic_update_group_16));
} 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) {
for (DecryptedApproveMember requestingMember : change.getPromoteRequestingMembersList()) {
boolean requestingMemberIsYou = selfIds.matches(requestingMember.getUuid());
boolean requestingMemberIsYou = selfIds.matches(requestingMember.getAciBytes());
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 {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
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 {
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) {
for (DecryptedApproveMember requestingMember : change.getPromoteRequestingMembersList()) {
boolean requestingMemberIsYou = selfIds.matches(requestingMember.getUuid());
boolean requestingMemberIsYou = selfIds.matches(requestingMember.getAciBytes());
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));
} 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) {
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()) {
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));
}
} else {
boolean editorIsCanceledMember = change.getEditor().equals(requestingMember);
boolean editorIsCanceledMember = change.getEditorServiceIdBytes().equals(requestingMember);
if (editorIsCanceledMember) {
updates.add(updateDescription(R.string.MessageRecord_s_canceled_their_request_to_join_the_group, requestingMember, R.drawable.ic_update_group_decline_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
if (change.getNewIsAnnouncementGroup() == EnabledState.ENABLED) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_only_admins_to_send), R.drawable.ic_update_group_role_16));
} 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) {
if (editorIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_allow_all_members_to_send), R.drawable.ic_update_group_role_16));
} 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) {
boolean editorIsYou = selfIds.matches(change.getEditor());
boolean editorIsYou = selfIds.matches(change.getEditorServiceIdBytes());
for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) {
ByteString uuid = newMember.getUuid();
ByteString uuid = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(uuid);
if (editorIsYou) {
@ -788,12 +793,12 @@ final class GroupsV2UpdateMessageProducer {
}
} else {
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 {
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));
} 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) {
for (DecryptedMember newMember : change.getPromotePendingPniAciMembersList()) {
ByteString uuid = newMember.getUuid();
boolean newMemberIsYou = selfIds.matches(uuid);
ByteString aci = newMember.getAciBytes();
boolean newMemberIsYou = selfIds.matches(aci);
if (newMemberIsYou) {
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_joined_the_group), R.drawable.ic_update_group_add_16));
} 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) {
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) {
@ -349,10 +349,15 @@ public abstract class MessageRecord extends DisplayRecord {
boolean invited = DecryptedGroupUtil.findPendingByServiceId(groupState.getPendingMembersList(), SignalStore.account().requireAci()).isPresent();
if (decryptedGroupV2Context.hasChange()) {
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
ServiceId changeEditor = ServiceId.parseOrNull(decryptedGroupV2Context.getChange().getEditorServiceIdBytes());
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 isGroupV2JoinRequest(UuidUtil.toByteString(serviceId.getRawUuid()));
}
public boolean isGroupV2JoinRequest(@NonNull ByteString uuid) {
DecryptedGroupV2Context decryptedGroupV2Context = getDecryptedGroupV2Context();
if (decryptedGroupV2Context != null && decryptedGroupV2Context.hasChange()) {
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;
}
@ -490,7 +494,7 @@ public abstract class MessageRecord extends DisplayRecord {
DecryptedGroupChange change = decryptedGroupV2Context.getChange();
return change.getNewRequestingMembersCount() > 0 &&
change.getDeleteRequestingMembersCount() > 0 &&
(serviceId == null || change.getEditor().equals(UuidUtil.toByteString(serviceId.getRawUuid())));
(serviceId == null || change.getEditorServiceIdBytes().equals(serviceId.toByteString()));
}
return false;
}

View file

@ -169,7 +169,7 @@ public final class GroupManager {
throws GroupChangeBusyException, GroupChangeFailedException, GroupInsufficientRightsException, GroupNotAMemberException, IOException
{
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);
}
}
@ -319,13 +319,13 @@ public final class GroupManager {
GroupTable.V2GroupProperties groupProperties = SignalDatabase.groups().requireGroup(groupId).requireV2GroupProperties();
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);
return;
}
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;
}
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByUuid(latest.getMembersList(), selfAci.getRawUuid());
Optional<DecryptedMember> selfInFullMemberList = DecryptedGroupUtil.findMemberByAci(latest.getMembersList(), selfAci);
if (!selfInFullMemberList.isPresent()) {
return latest;
@ -309,7 +309,7 @@ final class GroupManagerV2 {
SignalDatabase.recipients().setProfileSharing(groupRecipient.getId(), true);
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder(GroupChangeReconstruct.reconstructGroupChange(DecryptedGroup.newBuilder().build(), decryptedGroup))
.setEditor(selfAci.toByteString())
.setEditorServiceIdBytes(selfAci.toByteString())
.build();
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)
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
Set<UUID> uuids = Stream.of(recipientIds)
.map(r -> Recipient.resolved(r).requireServiceId().getRawUuid())
Set<ACI> uuids = Stream.of(recipientIds)
.map(r -> Recipient.resolved(r).requireAci())
.collect(Collectors.toSet());
return commitChangeWithConflictResolution(selfAci, groupOperations.createRefuseGroupJoinRequest(uuids, true, v2GroupProperties.getDecryptedGroup().getBannedMembersList()));
@ -463,7 +463,7 @@ final class GroupManagerV2 {
{
GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
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> pniPendingMember = DecryptedGroupUtil.findPendingByServiceId(decryptedGroup.getPendingMembersList(), selfPni);
Optional<DecryptedPendingMember> selfPendingMember = Optional.empty();
@ -478,23 +478,23 @@ final class GroupManagerV2 {
if (selfPendingMember.isPresent()) {
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) {
throw new AssertionError(e);
}
} else if (selfMember.isPresent()) {
ejectMember(serviceId, true, false, sendToMembers);
ejectMember(selfAci, true, false, sendToMembers);
} else {
Log.i(TAG, "Unable to leave group we are not pending or in");
}
}
@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
{
return commitChangeWithConflictResolution(selfAci,
groupOperations.createRemoveMembersChange(Collections.singleton(serviceId.getRawUuid()),
groupOperations.createRemoveMembersChange(Collections.singleton(aci),
ban,
ban ? v2GroupProperties.getDecryptedGroup().getBannedMembersList()
: Collections.emptyList()),
@ -508,7 +508,7 @@ final class GroupManagerV2 {
{
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));
}
@ -518,7 +518,7 @@ final class GroupManagerV2 {
{
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
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()) {
Log.w(TAG, "Self not in group " + groupId);
@ -548,7 +548,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
{
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()) {
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");
}
public GroupManager.GroupActionResult ban(UUID uuid)
public GroupManager.GroupActionResult ban(ServiceId serviceId)
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{
ByteString uuidByteString = UuidUtil.toByteString(uuid);
boolean rejectJoinRequest = v2GroupProperties.getDecryptedGroup().getRequestingMembersList().stream().anyMatch(m -> m.getUuid().equals(uuidByteString));
ByteString serviceIdByteString = serviceId.toByteString();
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)
@ -650,7 +650,7 @@ final class GroupManagerV2 {
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
{
boolean refetchedAddMemberCredentials = false;
change.setSourceUuid(UuidUtil.toByteString(authServiceId.getRawUuid()));
change.setSourceServiceId(UuidUtil.toByteString(authServiceId.getRawUuid()));
for (int attempt = 0; attempt < 5; attempt++) {
try {
@ -1070,16 +1070,16 @@ final class GroupManagerV2 {
.setRevision(GroupsV2StateProcessor.PLACEHOLDER_REVISION);
Recipient self = Recipient.self();
ByteString selfUuid = selfAci.toByteString();
ByteString selfAciBytes = selfAci.toByteString();
ByteString profileKey = ByteString.copyFrom(Objects.requireNonNull(self.getProfileKey()));
if (requestToJoin) {
group.addRequestingMembers(DecryptedRequestingMember.newBuilder()
.setUuid(selfUuid)
.setAciBytes(selfAciBytes)
.setProfileKey(profileKey));
} else {
group.addMembers(DecryptedMember.newBuilder()
.setUuid(selfUuid)
.setAciBytes(selfAciBytes)
.setProfileKey(profileKey));
}
@ -1104,7 +1104,7 @@ final class GroupManagerV2 {
GroupChange.Actions.Builder change = requestToJoin ? groupOperations.createGroupJoinRequest(expiringProfileKeyCredential)
: groupOperations.createGroupJoinDirect(expiringProfileKeyCredential);
change.setSourceUuid(selfAci.toByteString());
change.setSourceServiceId(selfAci.toByteString());
return commitJoinChangeWithConflictResolution(currentRevision, change);
}
@ -1203,7 +1203,7 @@ final class GroupManagerV2 {
void cancelJoinRequest()
throws GroupChangeFailedException, IOException
{
Set<UUID> uuids = Collections.singleton(selfAci.getRawUuid());
Set<ACI> uuids = Collections.singleton(selfAci);
GroupChange signedGroupChange;
try {

View file

@ -36,12 +36,12 @@ public final class GroupProtoUtil {
{
ByteString bytes = self.toByteString();
for (DecryptedMember decryptedMember : partialDecryptedGroup.getMembersList()) {
if (decryptedMember.getUuid().equals(bytes)) {
if (decryptedMember.getAciBytes().equals(bytes)) {
return decryptedMember.getJoinedAtRevision();
}
}
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
return partialDecryptedGroup.getRevision();
}
@ -80,12 +80,12 @@ public final class GroupProtoUtil {
}
@WorkerThread
public static Recipient pendingMemberToRecipient(@NonNull Context context, @NonNull DecryptedPendingMember pendingMember) {
return pendingMemberServiceIdToRecipient(context, pendingMember.getServiceIdBinary());
public static Recipient pendingMemberToRecipient(@NonNull DecryptedPendingMember pendingMember) {
return pendingMemberServiceIdToRecipient(pendingMember.getServiceIdBytes());
}
@WorkerThread
public static Recipient pendingMemberServiceIdToRecipient(@NonNull Context context, @NonNull ByteString serviceIdBinary) {
public static Recipient pendingMemberServiceIdToRecipient(@NonNull ByteString serviceIdBinary) {
ServiceId serviceId = ServiceId.parseOrThrow(serviceIdBinary);
if (serviceId.isUnknown()) {
@ -106,11 +106,11 @@ public final class GroupProtoUtil {
return RecipientId.from(serviceId);
}
public static boolean isMember(@NonNull UUID uuid, @NonNull List<DecryptedMember> membersList) {
ByteString uuidBytes = UuidUtil.toByteString(uuid);
public static boolean isMember(@NonNull ACI aci, @NonNull List<DecryptedMember> membersList) {
ByteString aciBytes = aci.toByteString();
for (DecryptedMember member : membersList) {
if (uuidBytes.equals(member.getUuid())) {
if (aciBytes.equals(member.getAciBytes())) {
return true;
}
}

View file

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

View file

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

View file

@ -42,7 +42,7 @@ public final class ProfileKeySet {
* authoritative.
*/
public void addKeysFromGroupChange(@NonNull DecryptedGroupChange change) {
UUID editor = UuidUtil.fromByteStringOrNull(change.getEditor());
ServiceId editor = ServiceId.parseOrNull(change.getEditorServiceIdBytes());
for (DecryptedMember member : change.getNewMembersList()) {
addMemberKey(member, editor);
@ -57,7 +57,7 @@ public final class ProfileKeySet {
}
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) {
addMemberKey(changeSource, member.getUuid(), member.getProfileKey());
private void addMemberKey(@NonNull DecryptedMember member, @Nullable ServiceId changeSource) {
addMemberKey(changeSource, member.getAciBytes(), member.getProfileKey());
}
private void addMemberKey(@Nullable UUID changeSource,
@NonNull ByteString memberUuidBytes,
private void addMemberKey(@Nullable ServiceId changeSource,
@NonNull ByteString memberAciBytes,
@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");
return;
}
@ -98,11 +98,11 @@ public final class ProfileKeySet {
}
if (memberUuid.equals(changeSource)) {
authoritativeProfileKeys.put(ACI.from(memberUuid), profileKey);
profileKeys.remove(ACI.from(memberUuid));
authoritativeProfileKeys.put(memberUuid, profileKey);
profileKeys.remove(memberUuid);
} else {
if (!authoritativeProfileKeys.containsKey(ACI.from(memberUuid))) {
profileKeys.put(ACI.from(memberUuid), profileKey);
if (!authoritativeProfileKeys.containsKey(memberUuid)) {
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.NotAbleToApplyGroupV2ChangeException;
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.ServiceIds;
import org.whispersystems.signalservice.api.util.UuidUtil;
@ -69,7 +70,6 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
* Advances a groups state to a specified revision.
@ -373,20 +373,20 @@ public class GroupsV2StateProcessor {
boolean addedAsMember = signedGroupChange.getNewMembersList()
.stream()
.map(DecryptedMember::getUuid)
.map(UuidUtil::fromByteStringOrNull)
.map(DecryptedMember::getAciBytes)
.map(ACI::parseOrNull)
.filter(Objects::nonNull)
.anyMatch(serviceIds::matches);
boolean addedAsPendingMember = signedGroupChange.getNewPendingMembersList()
.stream()
.map(DecryptedPendingMember::getServiceIdBinary)
.map(DecryptedPendingMember::getServiceIdBytes)
.anyMatch(serviceIds::matches);
boolean addedAsRequestingMember = signedGroupChange.getNewRequestingMembersList()
.stream()
.map(DecryptedRequestingMember::getUuid)
.map(UuidUtil::fromByteStringOrNull)
.map(DecryptedRequestingMember::getAciBytes)
.map(ACI::parseOrNull)
.filter(Objects::nonNull)
.anyMatch(serviceIds::matches);
@ -396,7 +396,7 @@ public class GroupsV2StateProcessor {
private boolean notHavingInviteRevoked(@NonNull DecryptedGroupChange signedGroupChange) {
boolean havingInviteRevoked = signedGroupChange.getDeletePendingMembersList()
.stream()
.map(DecryptedPendingMemberRemoval::getServiceIdBinary)
.map(DecryptedPendingMemberRemoval::getServiceIdBytes)
.anyMatch(serviceIds::matches);
return !havingInviteRevoked;
@ -421,12 +421,12 @@ public class GroupsV2StateProcessor {
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");
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");
inputGroupState = new GlobalGroupState(localState, Collections.singletonList(new ServerGroupLogEntry(latestServerGroup.getFullyDecryptedGroup(), null)));
} else {
@ -437,7 +437,7 @@ public class GroupsV2StateProcessor {
localState == null ||
localState.getRevision() < 0 ||
localState.getRevision() == revisionWeWereAdded ||
!GroupProtoUtil.isMember(serviceIds.getAci().getRawUuid(), localState.getMembersList()) ||
!GroupProtoUtil.isMember(serviceIds.getAci(), localState.getMembersList()) ||
(revision == LATEST && localState.getRevision() + 1 < latestServerGroup.getRevision());
info("Requesting from server currentRevision: " + (localState != null ? localState.getRevision() : "null") +
@ -552,18 +552,17 @@ public class GroupsV2StateProcessor {
}
Recipient groupRecipient = Recipient.externalGroupExact(groupId);
UUID selfUuid = serviceIds.getAci().getRawUuid();
DecryptedGroup decryptedGroup = groupDatabase.requireGroup(groupId)
.requireV2GroupProperties()
.getDecryptedGroup();
DecryptedGroup simulatedGroupState = DecryptedGroupUtil.removeMember(decryptedGroup, selfUuid, decryptedGroup.getRevision() + 1);
DecryptedGroup simulatedGroupState = DecryptedGroupUtil.removeMember(decryptedGroup, serviceIds.getAci(), decryptedGroup.getRevision() + 1);
DecryptedGroupChange simulatedGroupChange = DecryptedGroupChange.newBuilder()
.setEditor(UuidUtil.toByteString(UuidUtil.UNKNOWN_UUID))
.setEditorServiceIdBytes(ACI.UNKNOWN.toByteString())
.setRevision(simulatedGroupState.getRevision())
.addDeleteMembers(UuidUtil.toByteString(selfUuid))
.addDeleteMembers(serviceIds.getAci().toByteString())
.build();
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) {
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) {
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);
if (selfAsMemberOptional.isPresent()) {
@ -700,8 +699,8 @@ public class GroupsV2StateProcessor {
.map(ServerGroupLogEntry::getChange)
.filter(c -> c != null && c.getRevision() == revisionJoinedAt)
.findFirst()
.map(c -> Optional.ofNullable(UuidUtil.fromByteStringOrNull(c.getEditor()))
.map(uuid -> Recipient.externalPush(ACI.from(uuid))))
.map(c -> Optional.ofNullable(ServiceId.parseOrNull(c.getEditorServiceIdBytes()))
.map(Recipient::externalPush))
.orElse(Optional.empty());
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()));
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.");
ApplicationDependencies.getJobManager().add(new LeaveGroupV2Job(groupId));
//noinspection UnnecessaryReturnStatement
@ -725,7 +724,7 @@ public class GroupsV2StateProcessor {
Log.w(TAG, "Could not find founding member during gv2 create. Not enabling profile sharing.");
}
} 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))));
if (addedBy.isPresent() && addedBy.get().isBlocked()) {
@ -791,7 +790,7 @@ public class GroupsV2StateProcessor {
}
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());
@ -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();
Optional<UUID> changeEditor = DecryptedGroupUtil.editorUuid(change);
Optional<ServiceId> changeEditor = DecryptedGroupUtil.editorServiceId(change);
if (changeEditor.isPresent()) {
return changeEditor;
} else {
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByServiceId(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci);
if (pendingByUuid.isPresent()) {
return Optional.ofNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid()));
Optional<DecryptedPendingMember> pending = DecryptedGroupUtil.findPendingByServiceId(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci);
if (pending.isPresent()) {
return Optional.ofNullable(ACI.parseOrNull(pending.get().getAddedByAci()));
}
}
return Optional.empty();

View file

@ -119,10 +119,10 @@ public final class GroupV2UpdateSelfProfileKeyJob extends BaseJob {
continue;
}
ByteString selfUuidBytes = UuidUtil.toByteString(Recipient.self().requireAci().getRawUuid());
ByteString selfUuidBytes = Recipient.self().requireAci().toByteString();
DecryptedMember selfMember = group.get().requireV2GroupProperties().getDecryptedGroup().getMembersList()
.stream()
.filter(m -> m.getUuid().equals(selfUuidBytes))
.filter(m -> m.getAciBytes().equals(selfUuidBytes))
.findFirst()
.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.ACI;
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
@ -73,13 +71,12 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
@NonNull DecryptedGroup decryptedGroup,
@NonNull OutgoingMessage groupMessage)
{
List<UUID> memberUuids = DecryptedGroupUtil.toUuidList(decryptedGroup.getMembersList());
List<ACI> memberAcis = DecryptedGroupUtil.toAciList(decryptedGroup.getMembersList());
List<ServiceId> pendingServiceIds = DecryptedGroupUtil.pendingToServiceIdList(decryptedGroup.getPendingMembersList());
Stream<ServiceId> memberServiceIds = Stream.of(memberUuids)
.filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid))
.filter(uuid -> !SignalStore.account().requireAci().getRawUuid().equals(uuid))
.map(ACI::from);
Stream<ACI> memberServiceIds = Stream.of(memberAcis)
.filter(ACI::isValid)
.filter(aci -> !SignalStore.account().requireAci().equals(aci));
Stream<ServiceId> filteredPendingServiceIds = Stream.of(pendingServiceIds)
.filterNot(ServiceId::isUnknown);

View file

@ -16,15 +16,13 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.Base64;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
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.GroupContextV2;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
/**
* Represents either a GroupV1 or GroupV2 encoded context.
@ -166,11 +164,11 @@ public final class MessageGroupContext {
return decryptedGroupV2Context.getChange();
}
public @NonNull List<ServiceId> getAllActivePendingAndRemovedMembers() {
public @NonNull List<? extends ServiceId> getAllActivePendingAndRemovedMembers() {
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
DecryptedGroupChange groupChange = decryptedGroupV2Context.getChange();
return Stream.of(DecryptedGroupUtil.membersToServiceIdList(groupState.getMembersList()),
return Stream.of(DecryptedGroupUtil.toAciList(groupState.getMembersList()),
DecryptedGroupUtil.pendingToServiceIdList(groupState.getPendingMembersList()),
DecryptedGroupUtil.removedMembersServiceIdList(groupChange),
DecryptedGroupUtil.removedPendingMembersServiceIdList(groupChange),
@ -190,7 +188,7 @@ public final class MessageGroupContext {
List<RecipientId> members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount());
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)) {
members.add(recipient);
}

View file

@ -7,6 +7,8 @@ import com.google.protobuf.ByteString;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.thoughtcrime.securesms.mms.MessageGroupContext;
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;
@ -37,7 +39,7 @@ public final class GroupV2UpdateMessageUtil {
private static boolean changeEditorOnlyWasRemoved(@NonNull DecryptedGroupChange decryptedGroupChange) {
return decryptedGroupChange.getDeleteMembersCount() == 1 &&
decryptedGroupChange.getDeleteMembers(0).equals(decryptedGroupChange.getEditor());
decryptedGroupChange.getDeleteMembers(0).equals(decryptedGroupChange.getEditorServiceIdBytes());
}
private static boolean noChangesOtherThanDeletes(@NonNull DecryptedGroupChange decryptedGroupChange) {
@ -65,9 +67,9 @@ public final class GroupV2UpdateMessageUtil {
return -1;
}
public static Optional<ByteString> getChangeEditor(MessageGroupContext groupContext) {
public static Optional<ServiceId> getChangeEditor(MessageGroupContext 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();
}

View file

@ -4,6 +4,8 @@ import com.google.protobuf.ByteString;
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
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;
@ -52,7 +54,7 @@ public final class IncomingGroupUpdateMessage extends IncomingTextMessage {
return GroupV2UpdateMessageUtil.getChangeRevision(groupContext);
}
public Optional<ByteString> getChangeEditor() {
public Optional<ServiceId> getChangeEditor() {
return GroupV2UpdateMessageUtil.getChangeEditor(groupContext);
}
}

View file

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

View file

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

View file

@ -57,9 +57,9 @@ import static java.util.Collections.singletonList;
@Config(manifest = Config.NONE, application = Application.class)
public final class GroupsV2UpdateMessageProducerTest {
private UUID you;
private UUID alice;
private UUID bob;
private ACI you;
private ACI alice;
private ACI bob;
private GroupsV2UpdateMessageProducer producer;
@ -74,9 +74,9 @@ public final class GroupsV2UpdateMessageProducerTest {
@Before
public void setup() {
you = UUID.randomUUID();
alice = UUID.randomUUID();
bob = UUID.randomUUID();
you = ACI.from(UUID.randomUUID());
alice = ACI.from(UUID.randomUUID());
bob = ACI.from(UUID.randomUUID());
recipientIdMockedStatic.when(() -> RecipientId.from(anyLong())).thenCallRealMethod();
@ -86,10 +86,10 @@ public final class GroupsV2UpdateMessageProducerTest {
Recipient aliceRecipient = recipientWithName(aliceId, "Alice");
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(ACI.from(bob))).thenReturn(bobId);
recipientIdMockedStatic.when(() -> RecipientId.from(alice)).thenReturn(aliceId);
recipientIdMockedStatic.when(() -> RecipientId.from(bob)).thenReturn(bobId);
recipientMockedStatic.when(() -> Recipient.resolved(aliceId)).thenReturn(aliceRecipient);
recipientMockedStatic.when(() -> Recipient.resolved(bobId)).thenReturn(bobRecipient);
}
@ -436,7 +436,7 @@ public final class GroupsV2UpdateMessageProducerTest {
public void member_invited_2_persons() {
DecryptedGroupChange change = changeBy(alice)
.invite(bob)
.invite(UUID.randomUUID())
.invite(ACI.from(UUID.randomUUID()))
.build();
assertThat(describeChange(change), is(singletonList("Alice invited 2 people to the group.")));
@ -447,8 +447,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeBy(bob)
.invite(alice)
.invite(you)
.invite(UUID.randomUUID())
.invite(UUID.randomUUID())
.invite(ACI.from(UUID.randomUUID()))
.invite(ACI.from(UUID.randomUUID()))
.build();
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()
.invite(alice)
.invite(you)
.invite(UUID.randomUUID())
.invite(UUID.randomUUID())
.invite(ACI.from(UUID.randomUUID()))
.invite(ACI.from(UUID.randomUUID()))
.build();
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()
.invite(alice)
.inviteBy(you, bob)
.invite(UUID.randomUUID())
.invite(UUID.randomUUID())
.invite(ACI.from(UUID.randomUUID()))
.invite(ACI.from(UUID.randomUUID()))
.build();
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)
.addMember(alice)
.invite(you)
.invite(UUID.randomUUID())
.invite(UUID.randomUUID())
.invite(ACI.from(UUID.randomUUID()))
.invite(ACI.from(UUID.randomUUID()))
.build();
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() {
DecryptedGroupChange change = changeBy(alice)
.uninvite(bob)
.uninvite(UUID.randomUUID())
.uninvite(ACI.from(UUID.randomUUID()))
.build();
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() {
DecryptedGroupChange change = changeBy(you)
.uninvite(bob)
.uninvite(UUID.randomUUID())
.uninvite(ACI.from(UUID.randomUUID()))
.build();
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() {
DecryptedGroupChange change = changeByUnknown()
.uninvite(bob)
.uninvite(UUID.randomUUID())
.uninvite(ACI.from(UUID.randomUUID()))
.build();
assertThat(describeChange(change), is(singletonList("2 invitations to the group were revoked.")));
@ -638,8 +638,8 @@ public final class GroupsV2UpdateMessageProducerTest {
DecryptedGroupChange change = changeByUnknown()
.uninvite(bob)
.uninvite(you)
.uninvite(UUID.randomUUID())
.uninvite(UUID.randomUUID())
.uninvite(ACI.from(UUID.randomUUID()))
.uninvite(ACI.from(UUID.randomUUID()))
.build();
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));
}
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()
.setAccessControl(AccessControl.newBuilder()
.setAddFromInviteLink(fromAccess))
@ -1441,12 +1441,12 @@ public final class GroupsV2UpdateMessageProducerTest {
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);
}
private void assertSingleChangeMentioning(DecryptedGroupChange change, List<UUID> expectedMentions) {
List<ServiceId> expectedMentionSids = expectedMentions.stream().map(ACI::from).collect(Collectors.toList());
private void assertSingleChangeMentioning(DecryptedGroupChange change, List<ACI> expectedMentions) {
List<ServiceId> expectedMentionSids = expectedMentions.stream().collect(Collectors.toList());
List<UpdateDescription> changes = producer.describeChanges(null, change);
@ -1466,23 +1466,23 @@ public final class GroupsV2UpdateMessageProducerTest {
private final DecryptedGroup.Builder builder;
GroupStateBuilder(@NonNull UUID foundingMember, int revision) {
GroupStateBuilder(@NonNull ACI foundingMember, int revision) {
builder = DecryptedGroup.newBuilder()
.setRevision(revision)
.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()
.setServiceIdBinary(UuidUtil.toByteString(invitee))
.setAddedByUuid(UuidUtil.toByteString(inviter)));
.setServiceIdBytes(invitee.toByteString())
.setAddedByAci(inviter.toByteString()));
return this;
}
GroupStateBuilder member(@NonNull UUID member) {
GroupStateBuilder member(@NonNull ACI member) {
builder.addMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(member)));
.setAciBytes(member.toByteString()));
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.groups.v2.ChangeBuilder
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 java.util.Random
import java.util.UUID
@ -48,8 +48,8 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
*/
@Test
fun appendDeleteToExistingContext() {
val alice = UUID.randomUUID()
val aliceByteString = UuidUtil.toByteString(alice)
val alice = ACI.from(UUID.randomUUID())
val aliceByteString = alice.toByteString()
val change = ChangeBuilder.changeBy(alice)
.requestJoin(alice)
.build()
@ -71,7 +71,7 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
val newContext = DecryptedGroupV2Context.parseFrom(Base64.decode(newEncodedBody))
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))
}

View file

@ -151,8 +151,8 @@ class GroupManagerV2Test_edit {
then { patchedGroup ->
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("Other is now an admin in the group", patchedGroup.membersList.find { it.uuid == otherAci.toByteString() }?.role, `is`(Member.Role.ADMINISTRATOR))
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.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.DecryptedTimer;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.UUID;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
public final class ChangeBuilder {
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);
}
@ -36,10 +34,10 @@ public final class ChangeBuilder {
return new ChangeBuilder();
}
ChangeBuilder(@NonNull UUID editor) {
ChangeBuilder(@NonNull ACI editor) {
this.editor = editor;
this.builder = DecryptedGroupChange.newBuilder()
.setEditor(UuidUtil.toByteString(editor));
.setEditorServiceIdBytes(editor.toByteString());
}
ChangeBuilder() {
@ -47,74 +45,74 @@ public final class ChangeBuilder {
this.builder = DecryptedGroupChange.newBuilder();
}
public ChangeBuilder addMember(@NonNull UUID newMember) {
public ChangeBuilder addMember(@NonNull ACI newMember) {
builder.addNewMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMember)));
.setAciBytes(newMember.toByteString()));
return this;
}
public ChangeBuilder addMember(@NonNull UUID newMember, @NonNull ProfileKey profileKey) {
public ChangeBuilder addMember(@NonNull ACI newMember, @NonNull ProfileKey profileKey) {
builder.addNewMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMember))
.setAciBytes(newMember.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize())));
return this;
}
public ChangeBuilder deleteMember(@NonNull UUID removedMember) {
builder.addDeleteMembers(UuidUtil.toByteString(removedMember));
public ChangeBuilder deleteMember(@NonNull ACI removedMember) {
builder.addDeleteMembers(removedMember.toByteString());
return this;
}
public ChangeBuilder promoteToAdmin(@NonNull UUID member) {
public ChangeBuilder promoteToAdmin(@NonNull ACI member) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setRole(Member.Role.ADMINISTRATOR)
.setUuid(UuidUtil.toByteString(member)));
.setAciBytes(member.toByteString()));
return this;
}
public ChangeBuilder demoteToMember(@NonNull UUID member) {
public ChangeBuilder demoteToMember(@NonNull ACI member) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder()
.setRole(Member.Role.DEFAULT)
.setUuid(UuidUtil.toByteString(member)));
.setAciBytes(member.toByteString()));
return this;
}
public ChangeBuilder invite(@NonNull UUID potentialMember) {
return inviteBy(potentialMember, UuidUtil.UNKNOWN_UUID);
public ChangeBuilder invite(@NonNull ACI potentialMember) {
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()
.setServiceIdBinary(UuidUtil.toByteString(potentialMember))
.setAddedByUuid(UuidUtil.toByteString(inviter)));
.setServiceIdBytes(potentialMember.toByteString())
.setAddedByAci(inviter.toByteString()));
return this;
}
public ChangeBuilder uninvite(@NonNull UUID pendingMember) {
public ChangeBuilder uninvite(@NonNull ACI pendingMember) {
builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(UuidUtil.toByteString(pendingMember)));
.setServiceIdBytes(pendingMember.toByteString()));
return this;
}
public ChangeBuilder promote(@NonNull UUID pendingMember) {
builder.addPromotePendingMembers(DecryptedMember.newBuilder().setUuid(UuidUtil.toByteString(pendingMember)));
public ChangeBuilder promote(@NonNull ACI pendingMember) {
builder.addPromotePendingMembers(DecryptedMember.newBuilder().setAciBytes(pendingMember.toByteString()));
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());
}
public ChangeBuilder profileKeyUpdate(@NonNull UUID member, @NonNull byte[] profileKey) {
public ChangeBuilder profileKeyUpdate(@NonNull ACI member, @NonNull byte[] profileKey) {
builder.addModifiedProfileKeys(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(member))
.setAciBytes(member.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey)));
return this;
}
public ChangeBuilder promote(@NonNull UUID pendingMember, @NonNull ProfileKey profileKey) {
public ChangeBuilder promote(@NonNull ACI pendingMember, @NonNull ProfileKey profileKey) {
builder.addPromotePendingMembers(DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(pendingMember))
.setAciBytes(pendingMember.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize())));
return this;
}
@ -162,7 +160,7 @@ public final class ChangeBuilder {
return requestJoin(editor, newProfileKey());
}
public ChangeBuilder requestJoin(@NonNull UUID requester) {
public ChangeBuilder requestJoin(@NonNull ACI requester) {
return requestJoin(requester, newProfileKey());
}
@ -171,22 +169,22 @@ public final class ChangeBuilder {
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()
.setUuid(UuidUtil.toByteString(requester))
.setAciBytes(requester.toByteString())
.setProfileKey(ByteString.copyFrom(profileKey.serialize())));
return this;
}
public ChangeBuilder approveRequest(@NonNull UUID approvedMember) {
public ChangeBuilder approveRequest(@NonNull ACI approvedMember) {
builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder()
.setRole(Member.Role.DEFAULT)
.setUuid(UuidUtil.toByteString(approvedMember)));
.setAciBytes(approvedMember.toByteString()));
return this;
}
public ChangeBuilder denyRequest(@NonNull UUID approvedMember) {
builder.addDeleteRequestingMembers(UuidUtil.toByteString(approvedMember));
public ChangeBuilder denyRequest(@NonNull ACI approvedMember) {
builder.addDeleteRequestingMembers(approvedMember.toByteString());
return this;
}

View file

@ -22,7 +22,7 @@ public final class ProfileKeySetTest {
@Test
public void empty_change() {
UUID editor = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).build());
@ -33,95 +33,95 @@ public final class ProfileKeySetTest {
@Test
public void new_member_is_not_authoritative() {
UUID editor = UUID.randomUUID();
UUID newMember = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).addMember(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
}
@Test
public void new_member_by_self_is_authoritative() {
UUID newMember = UUID.randomUUID();
ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(newMember).addMember(newMember, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
}
@Test
public void new_member_by_self_promote_is_authoritative() {
UUID newMember = UUID.randomUUID();
ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(newMember).promote(newMember, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
}
@Test
public void new_member_by_promote_by_other_editor_is_not_authoritative() {
UUID editor = UUID.randomUUID();
UUID newMember = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI newMember = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).promote(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
}
@Test
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();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeByUnknown().promote(newMember, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(newMember), profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(newMember, profileKey)));
}
@Test
public void profile_key_update_by_self_is_authoritative() {
UUID member = UUID.randomUUID();
ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey)));
}
@Test
public void profile_key_update_by_another_is_not_authoritative() {
UUID editor = UUID.randomUUID();
UUID member = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(member, profileKey)));
}
@Test
public void multiple_updates_overwrite() {
UUID editor = UUID.randomUUID();
UUID member = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey1 = ProfileKeyUtil.createNew();
ProfileKey profileKey2 = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
@ -130,13 +130,13 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getAuthoritativeProfileKeys().isEmpty());
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey2)));
assertThat(profileKeySet.getProfileKeys(), is(Collections.singletonMap(member, profileKey2)));
}
@Test
public void authoritative_takes_priority_when_seen_first() {
UUID editor = UUID.randomUUID();
UUID member = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey1 = ProfileKeyUtil.createNew();
ProfileKey profileKey2 = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
@ -145,13 +145,13 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(editor).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey1)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey1)));
}
@Test
public void authoritative_takes_priority_when_seen_second() {
UUID editor = UUID.randomUUID();
UUID member = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI member = ACI.from(UUID.randomUUID());
ProfileKey profileKey1 = ProfileKeyUtil.createNew();
ProfileKey profileKey2 = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
@ -160,14 +160,14 @@ public final class ProfileKeySetTest {
profileKeySet.addKeysFromGroupChange(changeBy(member).profileKeyUpdate(member, profileKey2).build());
assertTrue(profileKeySet.getProfileKeys().isEmpty());
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(ACI.from(member), profileKey2)));
assertThat(profileKeySet.getAuthoritativeProfileKeys(), is(Collections.singletonMap(member, profileKey2)));
}
@Test
public void bad_profile_key() {
LogRecorder logRecorder = new LogRecorder();
UUID editor = UUID.randomUUID();
UUID member = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI member = ACI.from(UUID.randomUUID());
byte[] badProfileKey = new byte[10];
ProfileKeySet profileKeySet = new ProfileKeySet();
@ -181,26 +181,26 @@ public final class ProfileKeySetTest {
@Test
public void new_requesting_member_if_editor_is_authoritative() {
UUID editor = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
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());
}
@Test
public void new_requesting_member_if_not_editor_is_not_authoritative() {
UUID editor = UUID.randomUUID();
UUID requesting = UUID.randomUUID();
ACI editor = ACI.from(UUID.randomUUID());
ACI requesting = ACI.from(UUID.randomUUID());
ProfileKey profileKey = ProfileKeyUtil.createNew();
ProfileKeySet profileKeySet = new ProfileKeySet();
profileKeySet.addKeysFromGroupChange(changeBy(editor).requestJoin(requesting, profileKey).build());
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.DecryptedString;
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 java.util.UUID;
@ -261,7 +263,7 @@ public final class GroupStateMapperTest {
DecryptedGroup currentState = state(6);
ServerGroupLogEntry log7 = serverLogEntry(7);
DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID()))
.setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build();
DecryptedGroup state7b = DecryptedGroup.newBuilder()
.setRevision(8)
@ -323,12 +325,12 @@ public final class GroupStateMapperTest {
@Test
public void clears_changes_duplicated_in_the_placeholder() {
UUID newMemberUuid = UUID.randomUUID();
ACI newMemberAci = ACI.from(UUID.randomUUID());
DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMemberUuid))
.setAciBytes(newMemberAci.toByteString())
.build();
DecryptedMember existingMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID()))
.setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build();
DecryptedGroup currentState = DecryptedGroup.newBuilder()
.setRevision(GroupStateMapper.PLACEHOLDER_REVISION)
@ -343,7 +345,7 @@ public final class GroupStateMapperTest {
.build(),
DecryptedGroupChange.newBuilder()
.setRevision(8)
.setEditor(UuidUtil.toByteString(newMemberUuid))
.setEditorServiceIdBytes(newMemberAci.toByteString())
.addNewMembers(newMember)
.build());
@ -357,13 +359,13 @@ public final class GroupStateMapperTest {
@Test
public void clears_changes_duplicated_in_a_non_placeholder() {
UUID editorUuid = UUID.randomUUID();
UUID newMemberUuid = UUID.randomUUID();
ACI editorAci = ACI.from(UUID.randomUUID());
ACI newMemberAci = ACI.from(UUID.randomUUID());
DecryptedMember newMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(newMemberUuid))
.setAciBytes(newMemberAci.toByteString())
.build();
DecryptedMember existingMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID()))
.setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build();
DecryptedGroup currentState = DecryptedGroup.newBuilder()
.setRevision(8)
@ -378,14 +380,14 @@ public final class GroupStateMapperTest {
.build(),
DecryptedGroupChange.newBuilder()
.setRevision(8)
.setEditor(UuidUtil.toByteString(editorUuid))
.setEditorServiceIdBytes(editorAci.toByteString())
.addNewMembers(existingMember)
.addNewMembers(newMember)
.build());
DecryptedGroupChange expectedChange = DecryptedGroupChange.newBuilder()
.setRevision(8)
.setEditor(UuidUtil.toByteString(editorUuid))
.setEditorServiceIdBytes(editorAci.toByteString())
.addNewMembers(newMember)
.build();
@ -399,12 +401,12 @@ public final class GroupStateMapperTest {
@Test
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()
.setUuid(UuidUtil.toByteString(newMemberUuid))
.setAciBytes(newMemberAci.toByteString())
.build();
DecryptedMember existingMember = DecryptedMember.newBuilder()
.setUuid(UuidUtil.toByteString(UUID.randomUUID()))
.setAciBytes(ACI.from(UUID.randomUUID()).toByteString())
.build();
DecryptedGroup currentState = DecryptedGroup.newBuilder()
.setRevision(GroupStateMapper.PLACEHOLDER_REVISION)
@ -421,7 +423,7 @@ public final class GroupStateMapperTest {
.build(),
DecryptedGroupChange.newBuilder()
.setRevision(8)
.setEditor(UuidUtil.toByteString(newMemberUuid))
.setEditorServiceIdBytes(newMemberAci.toByteString())
.addNewMembers(newMember)
.build());
@ -448,7 +450,7 @@ public final class GroupStateMapperTest {
.build(),
DecryptedGroupChange.newBuilder()
.setRevision(2)
.setEditor(UuidUtil.toByteString(KNOWN_EDITOR))
.setEditorServiceIdBytes(UuidUtil.toByteString(KNOWN_EDITOR))
.setNewTitle(DecryptedString.newBuilder().setValue(log1.getGroup().getTitle()))
.build());
@ -457,7 +459,7 @@ public final class GroupStateMapperTest {
assertThat(advanceGroupStateResult.getProcessedLogEntries(), is(asList(asLocal(log1),
new LocalGroupLogEntry(log2.getGroup(), DecryptedGroupChange.newBuilder()
.setRevision(2)
.setEditor(UuidUtil.toByteString(KNOWN_EDITOR))
.setEditorServiceIdBytes(UuidUtil.toByteString(KNOWN_EDITOR))
.build()))));
assertTrue(advanceGroupStateResult.getNewGlobalGroupState().getServerHistory().isEmpty());
assertEquals(log2.getGroup(), advanceGroupStateResult.getNewGlobalGroupState().getLocalState());
@ -494,7 +496,7 @@ public final class GroupStateMapperTest {
private static DecryptedGroupChange change(int revision) {
return DecryptedGroupChange.newBuilder()
.setRevision(revision)
.setEditor(UuidUtil.toByteString(KNOWN_EDITOR))
.setEditorServiceIdBytes(UuidUtil.toByteString(KNOWN_EDITOR))
.setNewTitle(DecryptedString.newBuilder().setValue("Group Revision " + revision))
.build();
}

View file

@ -428,7 +428,7 @@ class GroupsV2StateProcessorTest {
}
changeLog(101) {
change {
addDeleteMembers(randomMembers[1].uuid)
addDeleteMembers(randomMembers[1].aciBytes)
addModifiedProfileKeys(randomMembers[0])
}
}
@ -449,7 +449,7 @@ class GroupsV2StateProcessorTest {
}
changeLog(101) {
change {
addDeleteMembers(randomMembers[1].uuid)
addDeleteMembers(randomMembers[1].aciBytes)
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.groups.v2.ChangeBuilder;
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 java.util.Random;
@ -22,7 +24,7 @@ public class GroupV2UpdateMessageUtilTest {
@Test
public void isJustAGroupLeave_whenEditorIsRemoved_shouldReturnTrue() {
// GIVEN
UUID alice = UUID.randomUUID();
ACI alice = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(alice)
.build();
@ -45,8 +47,8 @@ public class GroupV2UpdateMessageUtilTest {
@Test
public void isJustAGroupLeave_whenOtherIsRemoved_shouldReturnFalse() {
// GIVEN
UUID alice = UUID.randomUUID();
UUID bob = UUID.randomUUID();
ACI alice = ACI.from(UUID.randomUUID());
ACI bob = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(bob)
.build();
@ -69,8 +71,8 @@ public class GroupV2UpdateMessageUtilTest {
@Test
public void isJustAGroupLeave_whenEditorIsRemovedAndOtherChanges_shouldReturnFalse() {
// GIVEN
UUID alice = UUID.randomUUID();
UUID bob = UUID.randomUUID();
ACI alice = ACI.from(UUID.randomUUID());
ACI bob = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(alice)
.addMember(bob)
@ -94,7 +96,7 @@ public class GroupV2UpdateMessageUtilTest {
@Test
public void isJoinRequestCancel_whenChangeRemovesRequestingMembers_shouldReturnTrue() {
// GIVEN
UUID alice = UUID.randomUUID();
ACI alice = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.denyRequest(alice)
.build();
@ -117,8 +119,8 @@ public class GroupV2UpdateMessageUtilTest {
@Test
public void isJoinRequestCancel_whenChangeContainsNoRemoveRequestingMembers_shouldReturnFalse() {
// GIVEN
UUID alice = UUID.randomUUID();
UUID bob = UUID.randomUUID();
ACI alice = ACI.from(UUID.randomUUID());
ACI bob = ACI.from(UUID.randomUUID());
DecryptedGroupChange change = ChangeBuilder.changeBy(alice)
.deleteMember(alice)
.addMember(bob)

View file

@ -21,7 +21,7 @@ fun groupContext(masterKey: GroupMasterKey, init: DecryptedGroupV2Context.Builde
fun groupChange(editor: ServiceId, init: DecryptedGroupChange.Builder.() -> Unit): DecryptedGroupChange {
val builder = DecryptedGroupChange.newBuilder()
builder.editor = editor.toByteString()
builder.editorServiceIdBytes = editor.toByteString()
builder.init()
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 {
return DecryptedMember.newBuilder()
.setRole(role)
.setUuid(aci.toByteString())
.setAciBytes(aci.toByteString())
.setJoinedAtRevision(joinedAt)
.build()
}
fun requestingMember(serviceId: ServiceId): DecryptedRequestingMember {
return DecryptedRequestingMember.newBuilder()
.setUuid(serviceId.toByteString())
.setAciBytes(serviceId.toByteString())
.build()
}
fun pendingMember(serviceId: ServiceId): DecryptedPendingMember {
return DecryptedPendingMember.newBuilder()
.setServiceIdBinary(serviceId.toByteString())
.setServiceIdBytes(serviceId.toByteString())
.build()
}

View file

@ -103,7 +103,7 @@ final class DecryptedGroupChangeActionsBuilderChangeSetModifier implements Chang
result.removeNewRequestingMembers(i);
DecryptedMember build = DecryptedMember.newBuilder()
.setUuid(addMemberAction.getUuid())
.setAciBytes(addMemberAction.getAciBytes())
.setProfileKey(addMemberAction.getProfileKey())
.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.EnabledState;
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.util.UuidUtil;
import java.util.ArrayList;
import java.util.Collection;
@ -27,60 +27,58 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
public final class DecryptedGroupUtil {
private static final String TAG = DecryptedGroupUtil.class.getSimpleName();
public static ArrayList<UUID> toUuidList(Collection<DecryptedMember> membersList) {
ArrayList<UUID> uuidList = new ArrayList<>(membersList.size());
public static ArrayList<ACI> toAciListWithUnknowns(Collection<DecryptedMember> membersList) {
ArrayList<ACI> serviceIdList = new ArrayList<>(membersList.size());
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) {
ArrayList<ServiceId> serviceIdList = new ArrayList<>(membersList.size());
/** Converts the list of members to ACI's, filtering out unknown ACI's. */
public static ArrayList<ACI> toAciList(Collection<DecryptedMember> membersList) {
ArrayList<ACI> serviceIdList = new ArrayList<>(membersList.size());
for (DecryptedMember member : membersList) {
ServiceId serviceId = ServiceId.parseOrNull(member.getUuid());
ACI aci = ACI.parseOrNull(member.getAciBytes());
if (serviceId != null) {
serviceIdList.add(serviceId);
if (aci != null) {
serviceIdList.add(aci);
}
}
return serviceIdList;
}
public static Set<ByteString> membersToUuidByteStringSet(Collection<DecryptedMember> membersList) {
Set<ByteString> uuidList = new HashSet<>(membersList.size());
public static Set<ByteString> membersToAciByteStringSet(Collection<DecryptedMember> membersList) {
Set<ByteString> aciList = new HashSet<>(membersList.size());
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) {
ArrayList<ServiceId> serviceIdList = new ArrayList<>(membersList.size());
for (DecryptedPendingMember member : membersList) {
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary());
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBytes());
if (serviceId != null) {
serviceIdList.add(serviceId);
} 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) {
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) {
List<DecryptedPendingMemberRemoval> deletedPendingMembers = groupChange.getDeletePendingMembersList();
ArrayList<ServiceId> serviceIdList = new ArrayList<>(deletedPendingMembers.size());
for (DecryptedPendingMemberRemoval member : deletedPendingMembers) {
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary());
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBytes());
if(serviceId != null) {
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) {
List<ByteString> deleteRequestingMembers = groupChange.getDeleteRequestingMembersList();
@ -145,7 +143,7 @@ public final class DecryptedGroupUtil {
Set<ServiceId> serviceIdSet = new HashSet<>(membersList.size());
for (DecryptedBannedMember member : membersList) {
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBinary());
ServiceId serviceId = ServiceId.parseOrNull(member.getServiceIdBytes());
if (serviceId != null) {
serviceIdSet.add(serviceId);
}
@ -154,26 +152,18 @@ public final class DecryptedGroupUtil {
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) {
return Optional.ofNullable(change != null ? UuidUtil.fromByteStringOrNull(change.getEditor()) : null);
public static Optional<ServiceId> editorServiceId(DecryptedGroupChange change) {
return Optional.ofNullable(change != null ? ServiceId.parseOrNull(change.getEditorServiceIdBytes()) : null);
}
public static Optional<DecryptedMember> findMemberByUuid(Collection<DecryptedMember> members, UUID uuid) {
ByteString uuidBytes = UuidUtil.toByteString(uuid);
public static Optional<DecryptedMember> findMemberByAci(Collection<DecryptedMember> members, ACI aci) {
ByteString aciBytes = aci.toByteString();
for (DecryptedMember member : members) {
if (uuidBytes.equals(member.getUuid())) {
if (aciBytes.equals(member.getAciBytes())) {
return Optional.of(member);
}
}
@ -185,7 +175,7 @@ public final class DecryptedGroupUtil {
ByteString serviceIdBinary = serviceId.toByteString();
for (DecryptedPendingMember member : members) {
if (serviceIdBinary.equals(member.getServiceIdBinary())) {
if (serviceIdBinary.equals(member.getServiceIdBytes())) {
return Optional.of(member);
}
}
@ -195,7 +185,7 @@ public final class DecryptedGroupUtil {
public static Optional<DecryptedPendingMember> findPendingByServiceIds(Collection<DecryptedPendingMember> members, ServiceIds serviceIds) {
for (DecryptedPendingMember member : members) {
if (serviceIds.matches(member.getServiceIdBinary())) {
if (serviceIds.matches(member.getServiceIdBytes())) {
return Optional.of(member);
}
}
@ -203,10 +193,10 @@ public final class DecryptedGroupUtil {
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++) {
DecryptedPendingMember member = members.get(i);
if (cipherText.equals(member.getUuidCipherText())) {
if (cipherText.equals(member.getServiceIdCipherText())) {
return i;
}
}
@ -217,7 +207,7 @@ public final class DecryptedGroupUtil {
private static int findPendingIndexByServiceId(List<DecryptedPendingMember> members, ByteString serviceIdBinary) {
for (int i = 0; i < members.size(); i++) {
DecryptedPendingMember member = members.get(i);
if (serviceIdBinary.equals(member.getServiceIdBinary())) {
if (serviceIdBinary.equals(member.getServiceIdBytes())) {
return i;
}
}
@ -225,11 +215,11 @@ public final class DecryptedGroupUtil {
return -1;
}
public static Optional<DecryptedRequestingMember> findRequestingByUuid(Collection<DecryptedRequestingMember> members, UUID uuid) {
ByteString uuidBytes = UuidUtil.toByteString(uuid);
public static Optional<DecryptedRequestingMember> findRequestingByAci(Collection<DecryptedRequestingMember> members, ACI aci) {
ByteString aciBytes = aci.toByteString();
for (DecryptedRequestingMember member : members) {
if (uuidBytes.equals(member.getUuid())) {
if (aciBytes.equals(member.getAciBytes())) {
return Optional.of(member);
}
}
@ -239,7 +229,7 @@ public final class DecryptedGroupUtil {
public static Optional<DecryptedRequestingMember> findRequestingByServiceIds(Collection<DecryptedRequestingMember> members, ServiceIds serviceIds) {
for (DecryptedRequestingMember member : members) {
if (serviceIds.matches(member.getUuid())) {
if (serviceIds.matches(member.getAciBytes())) {
return Optional.of(member);
}
}
@ -252,25 +242,25 @@ public final class DecryptedGroupUtil {
findRequestingByServiceIds(group.getRequestingMembersList(), serviceIds).isPresent();
}
public static boolean isRequesting(DecryptedGroup group, UUID uuid) {
return findRequestingByUuid(group.getRequestingMembersList(), uuid).isPresent();
public static boolean isRequesting(DecryptedGroup group, ACI aci) {
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>
* 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.
*/
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);
ByteString uuidString = UuidUtil.toByteString(uuid);
ByteString aciByteString = aci.toByteString();
boolean removed = false;
ArrayList<DecryptedMember> decryptedMembers = new ArrayList<>(builder.getMembersList());
Iterator<DecryptedMember> membersList = decryptedMembers.iterator();
while (membersList.hasNext()) {
if (uuidString.equals(membersList.next().getUuid())) {
if (aciByteString.equals(membersList.next().getAciBytes())) {
membersList.remove();
removed = true;
}
@ -355,11 +345,11 @@ public final class DecryptedGroupUtil {
LinkedHashMap<ByteString, DecryptedMember> members = new LinkedHashMap<>();
for (DecryptedMember member : builder.getMembersList()) {
members.put(member.getUuid(), member);
members.put(member.getAciBytes(), member);
}
for (DecryptedMember member : newMembersList) {
members.put(member.getUuid(), member);
members.put(member.getAciBytes(), member);
}
builder.clearMembers();
@ -370,7 +360,7 @@ public final class DecryptedGroupUtil {
protected static void applyDeleteMemberActions(DecryptedGroup.Builder builder, List<ByteString> deleteMembersList) {
for (ByteString removedMember : deleteMembersList) {
int index = indexOfUuid(builder.getMembersList(), removedMember);
int index = indexOfAci(builder.getMembersList(), removedMember);
if (index == -1) {
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 {
for (DecryptedModifyMemberRole modifyMemberRole : modifyMemberRolesList) {
int index = indexOfUuid(builder.getMembersList(), modifyMemberRole.getUuid());
int index = indexOfAci(builder.getMembersList(), modifyMemberRole.getAciBytes());
if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException();
@ -400,7 +390,7 @@ public final class DecryptedGroupUtil {
private static void applyModifyMemberProfileKeyActions(DecryptedGroup.Builder builder, List<DecryptedMember> modifiedProfileKeysList) throws NotAbleToApplyGroupV2ChangeException {
for (DecryptedMember modifyProfileKey : modifiedProfileKeysList) {
int index = indexOfUuid(builder.getMembersList(), modifyProfileKey.getUuid());
int index = indexOfAci(builder.getMembersList(), modifyProfileKey.getAciBytes());
if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException();
@ -411,15 +401,15 @@ public final class DecryptedGroupUtil {
}
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());
for (DecryptedPendingMember pendingMember : newPendingMembersList) {
if (fullMemberSet.contains(pendingMember.getServiceIdBinary())) {
if (fullMemberSet.contains(pendingMember.getServiceIdBytes())) {
throw new NotAbleToApplyGroupV2ChangeException();
}
if (!pendingMemberCipherTexts.contains(pendingMember.getUuidCipherText())) {
if (!pendingMemberCipherTexts.contains(pendingMember.getServiceIdCipherText())) {
builder.addPendingMembers(pendingMember);
}
}
@ -427,7 +417,7 @@ public final class DecryptedGroupUtil {
protected static void applyDeletePendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMemberRemoval> deletePendingMembersList) {
for (DecryptedPendingMemberRemoval removedMember : deletePendingMembersList) {
int index = findPendingIndexByUuidCipherText(builder.getPendingMembersList(), removedMember.getUuidCipherText());
int index = findPendingIndexByServiceIdCipherText(builder.getPendingMembersList(), removedMember.getServiceIdCipherText());
if (index == -1) {
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 {
for (DecryptedMember newMember : promotePendingMembersList) {
int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getUuid());
int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getAciBytes());
if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException();
@ -515,7 +505,7 @@ public final class DecryptedGroupUtil {
private static void applyDeleteRequestingMembers(DecryptedGroup.Builder builder, List<ByteString> deleteRequestingMembersList) {
for (ByteString removedMember : deleteRequestingMembersList) {
int index = indexOfUuidInRequestingList(builder.getRequestingMembersList(), removedMember);
int index = indexOfAciInRequestingList(builder.getRequestingMembersList(), removedMember);
if (index == -1) {
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 {
for (DecryptedApproveMember approvedMember : promoteRequestingMembers) {
int index = indexOfUuidInRequestingList(builder.getRequestingMembersList(), approvedMember.getUuid());
int index = indexOfAciInRequestingList(builder.getRequestingMembersList(), approvedMember.getAciBytes());
if (index == -1) {
Log.w(TAG, "Deleted member on change not found in group");
@ -542,7 +532,7 @@ public final class DecryptedGroupUtil {
builder.removeRequestingMembers(index)
.addMembers(DecryptedMember.newBuilder()
.setUuid(approvedMember.getUuid())
.setAciBytes(approvedMember.getAciBytes())
.setProfileKey(requestingMember.getProfileKey())
.setRole(role));
}
@ -558,7 +548,7 @@ public final class DecryptedGroupUtil {
Set<ByteString> bannedMemberServiceIdSet = getBannedMemberServiceIdSet(builder.getBannedMembersList());
for (DecryptedBannedMember member : newBannedMembersList) {
if (bannedMemberServiceIdSet.contains(member.getServiceIdBinary())) {
if (bannedMemberServiceIdSet.contains(member.getServiceIdBytes())) {
Log.w(TAG, "Banned member already in banned list");
} else {
builder.addBannedMembers(member);
@ -568,7 +558,7 @@ public final class DecryptedGroupUtil {
private static void applyDeleteBannedMembersActions(DecryptedGroup.Builder builder, List<DecryptedBannedMember> deleteMembersList) {
for (DecryptedBannedMember removedMember : deleteMembersList) {
int index = indexOfServiceIdInBannedMemberList(builder.getBannedMembersList(), removedMember.getServiceIdBinary());
int index = indexOfServiceIdInBannedMemberList(builder.getBannedMembersList(), removedMember.getServiceIdBytes());
if (index == -1) {
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 {
for (DecryptedMember newMember : promotePendingPniAciMembersList) {
int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getPni());
int index = findPendingIndexByServiceId(builder.getPendingMembersList(), newMember.getPniBytes());
if (index == -1) {
throw new NotAbleToApplyGroupV2ChangeException();
@ -598,21 +588,21 @@ public final class DecryptedGroupUtil {
.build();
}
private static Set<ByteString> getMemberUuidSet(List<DecryptedMember> membersList) {
Set<ByteString> memberUuids = new HashSet<>(membersList.size());
private static Set<ByteString> getMemberAciSet(List<DecryptedMember> membersList) {
Set<ByteString> memberAcis = new HashSet<>(membersList.size());
for (DecryptedMember members : membersList) {
memberUuids.add(members.getUuid());
memberAcis.add(members.getAciBytes());
}
return memberUuids;
return memberAcis;
}
private static Set<ByteString> getPendingMemberCipherTextSet(List<DecryptedPendingMember> pendingMemberList) {
Set<ByteString> pendingMemberCipherTexts = new HashSet<>(pendingMemberList.size());
for (DecryptedPendingMember pendingMember : pendingMemberList) {
pendingMemberCipherTexts.add(pendingMember.getUuidCipherText());
pendingMemberCipherTexts.add(pendingMember.getServiceIdCipherText());
}
return pendingMemberCipherTexts;
@ -622,25 +612,25 @@ public final class DecryptedGroupUtil {
Set<ByteString> memberServiceIds = new HashSet<>(bannedMemberList.size());
for (DecryptedBannedMember member : bannedMemberList) {
memberServiceIds.add(member.getServiceIdBinary());
memberServiceIds.add(member.getServiceIdBytes());
}
return memberServiceIds;
}
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--) {
DecryptedPendingMember pendingMember = builder.getPendingMembers(i);
if (allMembers.contains(pendingMember.getServiceIdBinary())) {
if (allMembers.contains(pendingMember.getServiceIdBytes())) {
builder.removePendingMembers(i);
}
}
for (int i = builder.getRequestingMembersCount() - 1; i >= 0; i--) {
DecryptedRequestingMember requestingMember = builder.getRequestingMembers(i);
if (allMembers.contains(requestingMember.getUuid())) {
if (allMembers.contains(requestingMember.getAciBytes())) {
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++) {
if (uuid.equals(memberList.get(i).getUuid())) return i;
if (aci.equals(memberList.get(i).getAciBytes())) {
return i;
}
}
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++) {
if (uuid.equals(memberList.get(i).getUuid())) return i;
if (aci.equals(memberList.get(i).getAciBytes())) {
return i;
}
}
return -1;
}
private static int indexOfServiceIdInBannedMemberList(List<DecryptedBannedMember> memberList, ByteString serviceIdBinary) {
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;
}

View file

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

View file

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

View file

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

View file

@ -110,12 +110,18 @@ sealed class ServiceId(val libSignalServiceId: LibSignalServiceId) {
@JvmStatic
fun from(uuid: UUID): ACI = ACI(LibSignalAci(uuid))
@JvmStatic
fun fromLibSignal(aci: LibSignalAci): ACI = ACI(aci)
@JvmStatic
fun parseOrNull(raw: String?): ACI? = ServiceId.parseOrNull(raw).let { if (it is ACI) it else null }
@JvmStatic
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
@Throws(IllegalArgumentException::class)
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);
}
public boolean matches(UUID uuid) {
return uuid.equals(aci.getRawUuid()) || (pni != null && uuid.equals(pni.getRawUuid()));
public boolean matches(ServiceId serviceId) {
return serviceId.equals(aci) || (pni != null && serviceId.equals(pni));
}
public boolean matches(ByteString uuid) {
public boolean matches(ByteString serviceIdsBytes) {
if (aciByteString == null) {
aciByteString = aci.toByteString();
}
@ -50,6 +50,6 @@ public final class ServiceIds {
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
// Keep field numbers in step
message DecryptedMember {
bytes uuid = 1;
bytes aciBytes = 1;
Member.Role role = 2;
bytes profileKey = 3;
uint32 joinedAtRevision = 5;
bytes pni = 6;
bytes pniBytes = 6;
}
message DecryptedPendingMember {
bytes serviceIdBinary = 1;
bytes serviceIdBytes = 1;
Member.Role role = 2;
bytes addedByUuid = 3;
bytes addedByAci = 3;
uint64 timestamp = 4;
bytes uuidCipherText = 5;
bytes serviceIdCipherText = 5;
}
message DecryptedRequestingMember {
bytes uuid = 1;
bytes aciBytes = 1;
bytes profileKey = 2;
uint64 timestamp = 4;
}
message DecryptedBannedMember {
bytes serviceIdBinary = 1;
bytes serviceIdBytes = 1;
uint64 timestamp = 2;
}
message DecryptedPendingMemberRemoval {
bytes serviceIdBinary = 1;
bytes uuidCipherText = 2;
bytes serviceIdBytes = 1;
bytes serviceIdCipherText = 2;
}
message DecryptedApproveMember {
bytes uuid = 1;
bytes aciBytes = 1;
Member.Role role = 2;
}
message DecryptedModifyMemberRole {
bytes uuid = 1;
bytes aciBytes = 1;
Member.Role role = 2;
}
@ -74,7 +74,7 @@ message DecryptedGroup {
// Decrypted version of message GroupChange.Actions
// Keep field numbers in step
message DecryptedGroupChange {
bytes editor = 1;
bytes editorServiceIdBytes = 1;
uint32 revision = 2;
repeated DecryptedMember newMembers = 3;
repeated bytes deleteMembers = 4;

View file

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

View file

@ -4,12 +4,10 @@ import com.google.protobuf.ByteString;
import org.junit.Test;
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.DecryptedPendingMemberRemoval;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util;
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.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static java.util.Arrays.asList;
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
public void can_extract_editor_uuid_from_decrypted_group_change() {
UUID uuid = UUID.randomUUID();
ByteString editor = UuidUtil.toByteString(uuid);
ACI aci = ACI.from(UUID.randomUUID());
ByteString editor = aci.toByteString();
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()
.setEditor(editor)
.setEditorServiceIdBytes(editor)
.build();
UUID parsed = DecryptedGroupUtil.editorUuid(groupChange).get();
ServiceId parsed = DecryptedGroupUtil.editorServiceId(groupChange).get();
assertEquals(uuid, parsed);
assertEquals(aci, parsed);
}
@Test
public void can_extract_uuid_from_decrypted_pending_member() {
ACI aci = ACI.from(UUID.randomUUID());
DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(aci.toByteString())
.setServiceIdBytes(aci.toByteString())
.build();
ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBinary());
ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBytes());
assertEquals(aci, parsed);
}
@ -74,10 +50,10 @@ public final class DecryptedGroupUtilTest {
@Test
public void can_extract_uuid_from_bad_decrypted_pending_member() {
DecryptedPendingMember decryptedMember = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18)))
.setServiceIdBytes(ByteString.copyFrom(Util.getSecretBytes(18)))
.build();
ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBinary());
ServiceId parsed = ServiceId.parseOrNull(decryptedMember.getServiceIdBytes());
assertNull(parsed);
}
@ -87,13 +63,13 @@ public final class DecryptedGroupUtilTest {
ACI aci1 = ACI.from(UUID.randomUUID());
ACI aci2 = ACI.from(UUID.randomUUID());
DecryptedPendingMember decryptedMember1 = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(aci1.toByteString())
.setServiceIdBytes(aci1.toByteString())
.build();
DecryptedPendingMember decryptedMember2 = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(aci2.toByteString())
.setServiceIdBytes(aci2.toByteString())
.build();
DecryptedPendingMember decryptedMember3 = DecryptedPendingMember.newBuilder()
.setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18)))
.setServiceIdBytes(ByteString.copyFrom(Util.getSecretBytes(18)))
.build();
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()
@ -112,13 +88,13 @@ public final class DecryptedGroupUtilTest {
ACI aci1 = ACI.from(UUID.randomUUID());
ACI aci2 = ACI.from(UUID.randomUUID());
DecryptedPendingMemberRemoval decryptedMember1 = DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(aci1.toByteString())
.setServiceIdBytes(aci1.toByteString())
.build();
DecryptedPendingMemberRemoval decryptedMember2 = DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(aci2.toByteString())
.setServiceIdBytes(aci2.toByteString())
.build();
DecryptedPendingMemberRemoval decryptedMember3 = DecryptedPendingMemberRemoval.newBuilder()
.setServiceIdBinary(ByteString.copyFrom(Util.getSecretBytes(18)))
.setServiceIdBytes(ByteString.copyFrom(Util.getSecretBytes(18)))
.build();
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()

View file

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

View file

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

View file

@ -661,18 +661,18 @@ public final class GroupChangeUtil_resolveConflict_decryptedOnly_Test {
DecryptedMember member2 = pendingPniAciMember(UUID.randomUUID(), UUID.randomUUID(), randomProfileKey());
DecryptedGroup groupState = DecryptedGroup.newBuilder()
.addMembers(member(UuidUtil.fromByteString(member1.getUuid())))
.addMembers(member(UuidUtil.fromByteString(member1.getAciBytes())))
.build();
DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder()
.addPromotePendingPniAciMembers(pendingPniAciMember(member1.getUuid(), member1.getPni(), member1.getProfileKey()))
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getUuid(), member2.getPni(), member2.getProfileKey()))
.addPromotePendingPniAciMembers(pendingPniAciMember(member1.getAciBytes(), member1.getPniBytes(), member1.getProfileKey()))
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getAciBytes(), member2.getPniBytes(), member2.getProfileKey()))
.build();
DecryptedGroupChange resolvedChanges = GroupChangeUtil.resolveConflict(groupState, decryptedChange).build();
DecryptedGroupChange expected = DecryptedGroupChange.newBuilder()
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getUuid(), member2.getPni(), member2.getProfileKey()))
.addPromotePendingPniAciMembers(pendingPniAciMember(member2.getAciBytes(), member2.getPniBytes(), member2.getProfileKey()))
.build();
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.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.util.Util;
import org.whispersystems.signalservice.testutil.LibSignalLibraryUtil;
@ -47,36 +46,36 @@ public final class GroupsV2Operations_ban_Test {
@Test
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,
Collections.emptyList());
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
public void addBanToPartialFullList() {
UUID toBan = UUID.randomUUID();
ACI toBan = ACI.from(UUID.randomUUID());
List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(5);
for (int i = 0; i < 5; i++) {
alreadyBanned.add(bannedMember(UUID.randomUUID()));
}
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(Collections.singleton(toBan),
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(Collections.singleton(toBan),
false,
alreadyBanned);
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
public void addBanToFullList() {
UUID toBan = UUID.randomUUID();
ACI toBan = ACI.from(UUID.randomUUID());
List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(10);
DecryptedBannedMember oldest = null;
@ -90,23 +89,23 @@ public final class GroupsV2Operations_ban_Test {
Collections.shuffle(alreadyBanned);
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(Collections.singleton(toBan),
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(Collections.singleton(toBan),
false,
alreadyBanned);
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.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(ACI.from(toBan))));
assertThat(banUuidsChange.getAddBannedMembers(0).getAdded().getUserId(), is(groupOperations.encryptServiceId(toBan)));
}
@Test
public void addMultipleBanToFullList() {
List<UUID> toBan = new ArrayList<>();
toBan.add(UUID.randomUUID());
toBan.add(UUID.randomUUID());
List<ACI> toBan = new ArrayList<>();
toBan.add(ACI.from(UUID.randomUUID()));
toBan.add(ACI.from(UUID.randomUUID()));
List<DecryptedBannedMember> alreadyBanned = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
@ -114,12 +113,12 @@ public final class GroupsV2Operations_ban_Test {
}
List<ByteString> oldest = new ArrayList<>(2);
oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(0).getServiceIdBinary())));
oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(1).getServiceIdBinary())));
oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(0).getServiceIdBytes())));
oldest.add(groupOperations.encryptServiceId(ServiceId.parseOrThrow(alreadyBanned.get(1).getServiceIdBytes())));
Collections.shuffle(alreadyBanned);
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanUuidsChange(new HashSet<>(toBan),
GroupChange.Actions.Builder banUuidsChange = groupOperations.createBanServiceIdsChange(new HashSet<>(toBan),
false,
alreadyBanned);
@ -137,7 +136,7 @@ public final class GroupsV2Operations_ban_Test {
.map(AddBannedMemberAction::getAdded)
.map(BannedMember::getUserId)
.collect(Collectors.toList()),
hasItems(groupOperations.encryptServiceId(ACI.from(toBan.get(0))),
groupOperations.encryptServiceId(ACI.from(toBan.get(1)))));
hasItems(groupOperations.encryptServiceId(toBan.get(0)),
groupOperations.encryptServiceId(toBan.get(1))));
}
}

View file

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

View file

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

View file

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