mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-27 12:15:50 +01:00
GV2 Group Manager.
This commit is contained in:
@@ -6,6 +6,7 @@ import org.junit.Test;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -17,7 +18,7 @@ public final class DecryptedGroupUtilTest {
|
||||
public void can_extract_uuid_from_decrypted_member() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
DecryptedMember decryptedMember = DecryptedMember.newBuilder()
|
||||
.setUuid(ByteString.copyFrom(UUIDUtil.serialize(uuid)))
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.build();
|
||||
|
||||
UUID parsed = DecryptedGroupUtil.toUuid(decryptedMember);
|
||||
@@ -28,7 +29,7 @@ public final class DecryptedGroupUtilTest {
|
||||
@Test
|
||||
public void can_extract_editor_uuid_from_decrypted_group_change() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
ByteString editor = ByteString.copyFrom(UUIDUtil.serialize(uuid));
|
||||
ByteString editor = UuidUtil.toByteString(uuid);
|
||||
DecryptedGroupChange groupChange = DecryptedGroupChange.newBuilder()
|
||||
.setEditor(editor)
|
||||
.build();
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
package org.whispersystems.signalservice.api.groupsv2;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedString;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedTimer;
|
||||
import org.signal.zkgroup.profiles.ProfileKey;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.admin;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.asAdmin;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.asMember;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.member;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.pendingMember;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.randomProfileKey;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.withProfileKey;
|
||||
|
||||
public final class DecryptedGroupUtil_apply_Test {
|
||||
|
||||
@Test
|
||||
public void apply_version() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(9)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(10)
|
||||
.build());
|
||||
|
||||
assertEquals(10, newGroup.getVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_new_member() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
DecryptedMember member2 = member(UUID.randomUUID());
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.addMembers(member1)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.addNewMembers(member2)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_remove_member() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
DecryptedMember member2 = member(UUID.randomUUID());
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(13)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(14)
|
||||
.addDeleteMembers(member1.getUuid())
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(14)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_remove_members() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
DecryptedMember member2 = member(UUID.randomUUID());
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(13)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(14)
|
||||
.addDeleteMembers(member1.getUuid())
|
||||
.addDeleteMembers(member2.getUuid())
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(14)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test(expected = DecryptedGroupUtil.NotAbleToApplyChangeException.class)
|
||||
public void apply_remove_members_not_found() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
DecryptedMember member2 = member(UUID.randomUUID());
|
||||
|
||||
DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(13)
|
||||
.addMembers(member1)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(14)
|
||||
.addDeleteMembers(member2.getUuid())
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_modify_member_role() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
DecryptedMember member2 = admin(UUID.randomUUID());
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(13)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(14)
|
||||
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setUuid(member1.getUuid()).setRole(Member.Role.ADMINISTRATOR))
|
||||
.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setUuid(member2.getUuid()).setRole(Member.Role.DEFAULT))
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(14)
|
||||
.addMembers(asAdmin(member1))
|
||||
.addMembers(asMember(member2))
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_modify_member_profile_keys() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
ProfileKey profileKey1 = randomProfileKey();
|
||||
ProfileKey profileKey2a = randomProfileKey();
|
||||
ProfileKey profileKey2b = randomProfileKey();
|
||||
DecryptedMember member1 = member(UUID.randomUUID(), profileKey1);
|
||||
DecryptedMember member2a = member(UUID.randomUUID(), profileKey2a);
|
||||
DecryptedMember member2b = withProfileKey(member2a, profileKey2b);
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(13)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2a)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(14)
|
||||
.addModifiedProfileKeys(member2b)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(14)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2b)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_new_pending_member() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
DecryptedPendingMember pending = pendingMember(UUID.randomUUID());
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.addMembers(member1)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.addNewPendingMembers(pending)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.addMembers(member1)
|
||||
.addPendingMembers(pending)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remove_pending_member() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
UUID pendingUuid = UUID.randomUUID();
|
||||
DecryptedPendingMember pending = pendingMember(pendingUuid);
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.addMembers(member1)
|
||||
.addPendingMembers(pending)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder()
|
||||
.setUuidCipherText(ProtoTestUtils.encrypt(pendingUuid))
|
||||
.build())
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.addMembers(member1)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void promote_pending_member() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
ProfileKey profileKey2 = randomProfileKey();
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
UUID pending2Uuid = UUID.randomUUID();
|
||||
DecryptedPendingMember pending2 = pendingMember(pending2Uuid);
|
||||
DecryptedMember member2 = member(pending2Uuid, profileKey2);
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.addMembers(member1)
|
||||
.addPendingMembers(pending2)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.addPromotePendingMembers(member2)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void promote_direct_to_admin() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
ProfileKey profileKey2 = randomProfileKey();
|
||||
DecryptedMember member1 = member(UUID.randomUUID());
|
||||
UUID pending2Uuid = UUID.randomUUID();
|
||||
DecryptedPendingMember pending2 = pendingMember(pending2Uuid);
|
||||
DecryptedMember member2 = withProfileKey(admin(pending2Uuid), profileKey2);
|
||||
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.addMembers(member1)
|
||||
.addPendingMembers(pending2)
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.addPromotePendingMembers(member2)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.addMembers(member1)
|
||||
.addMembers(member2)
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void title() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.setTitle("Old title")
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.setNewTitle(DecryptedString.newBuilder().setValue("New title").build())
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.setTitle("New title")
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void avatar() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.setAvatar("https://cnd/oldavatar")
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.setNewAvatar(DecryptedString.newBuilder().setValue("https://cnd/newavatar").build())
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.setAvatar("https://cnd/newavatar")
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timer() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.setDisappearingMessagesTimer(DecryptedTimer.newBuilder().setDuration(100))
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.setNewTimer(DecryptedTimer.newBuilder().setDuration(2000))
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.setDisappearingMessagesTimer(DecryptedTimer.newBuilder().setDuration(2000))
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attribute_access() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.setAccessControl(AccessControl.newBuilder()
|
||||
.setAttributes(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.setMembers(AccessControl.AccessRequired.MEMBER)
|
||||
.build())
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.setNewAttributeAccess(AccessControl.AccessRequired.MEMBER)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.setAccessControl(AccessControl.newBuilder()
|
||||
.setAttributes(AccessControl.AccessRequired.MEMBER)
|
||||
.setMembers(AccessControl.AccessRequired.MEMBER)
|
||||
.build())
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void membership_access() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.setAccessControl(AccessControl.newBuilder()
|
||||
.setAttributes(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.setMembers(AccessControl.AccessRequired.MEMBER)
|
||||
.build())
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.setNewMemberAccess(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.setAccessControl(AccessControl.newBuilder()
|
||||
.setAttributes(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.setMembers(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.build())
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void change_both_access_levels() throws DecryptedGroupUtil.NotAbleToApplyChangeException {
|
||||
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder()
|
||||
.setVersion(10)
|
||||
.setAccessControl(AccessControl.newBuilder()
|
||||
.setAttributes(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.setMembers(AccessControl.AccessRequired.MEMBER)
|
||||
.build())
|
||||
.build(),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setVersion(11)
|
||||
.setNewAttributeAccess(AccessControl.AccessRequired.MEMBER)
|
||||
.setNewMemberAccess(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.build());
|
||||
|
||||
assertEquals(DecryptedGroup.newBuilder()
|
||||
.setVersion(11)
|
||||
.setAccessControl(AccessControl.newBuilder()
|
||||
.setAttributes(AccessControl.AccessRequired.MEMBER)
|
||||
.setMembers(AccessControl.AccessRequired.ADMINISTRATOR)
|
||||
.build())
|
||||
.build(),
|
||||
newGroup);
|
||||
}
|
||||
}
|
||||
@@ -4,27 +4,30 @@ import com.google.protobuf.ByteString;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.DisappearingMessagesTimer;
|
||||
import org.signal.storageservice.protos.groups.GroupChange;
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.PendingMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedString;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedTimer;
|
||||
import org.signal.zkgroup.profiles.ProfileKey;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.admin;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.demoteAdmin;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.encrypt;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.encryptedMember;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.member;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.pendingMember;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.pendingMemberRemoval;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.presentation;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.promoteAdmin;
|
||||
import static org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.randomProfileKey;
|
||||
|
||||
public final class GroupChangeUtil_resolveConflict_Test {
|
||||
|
||||
@@ -257,9 +260,9 @@ public final class GroupChangeUtil_resolveConflict_Test {
|
||||
.addPendingMembers(pendingMember(member2))
|
||||
.build();
|
||||
DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder()
|
||||
.addPromotePendingMembers(UuidUtil.toByteString(member1))
|
||||
.addPromotePendingMembers(UuidUtil.toByteString(member2))
|
||||
.addPromotePendingMembers(UuidUtil.toByteString(member3))
|
||||
.addPromotePendingMembers(member(member1))
|
||||
.addPromotePendingMembers(member(member2))
|
||||
.addPromotePendingMembers(member(member3))
|
||||
.build();
|
||||
GroupChange.Actions change = GroupChange.Actions.newBuilder()
|
||||
.addPromotePendingMembers(GroupChange.Actions.PromotePendingMemberAction.newBuilder().setPresentation(presentation(member1, randomProfileKey())))
|
||||
@@ -370,10 +373,10 @@ public final class GroupChangeUtil_resolveConflict_Test {
|
||||
@Test
|
||||
public void field_12__timer_change_is_preserved() {
|
||||
DecryptedGroup groupState = DecryptedGroup.newBuilder()
|
||||
.setDisappearingMessagesTimer(DisappearingMessagesTimer.newBuilder().setDuration(123))
|
||||
.setDisappearingMessagesTimer(DecryptedTimer.newBuilder().setDuration(123))
|
||||
.build();
|
||||
DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder()
|
||||
.setNewTimer(DisappearingMessagesTimer.newBuilder().setDuration(456))
|
||||
.setNewTimer(DecryptedTimer.newBuilder().setDuration(456))
|
||||
.build();
|
||||
GroupChange.Actions change = GroupChange.Actions.newBuilder()
|
||||
.setModifyDisappearingMessagesTimer(GroupChange.Actions.ModifyDisappearingMessagesTimerAction.newBuilder().setTimer(ByteString.EMPTY))
|
||||
@@ -387,10 +390,10 @@ public final class GroupChangeUtil_resolveConflict_Test {
|
||||
@Test
|
||||
public void field_12__no_timer_change_is_removed() {
|
||||
DecryptedGroup groupState = DecryptedGroup.newBuilder()
|
||||
.setDisappearingMessagesTimer(DisappearingMessagesTimer.newBuilder().setDuration(123))
|
||||
.setDisappearingMessagesTimer(DecryptedTimer.newBuilder().setDuration(123))
|
||||
.build();
|
||||
DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder()
|
||||
.setNewTimer(DisappearingMessagesTimer.newBuilder().setDuration(123))
|
||||
.setNewTimer(DecryptedTimer.newBuilder().setDuration(123))
|
||||
.build();
|
||||
GroupChange.Actions change = GroupChange.Actions.newBuilder()
|
||||
.setModifyDisappearingMessagesTimer(GroupChange.Actions.ModifyDisappearingMessagesTimerAction.newBuilder().setTimer(ByteString.EMPTY))
|
||||
@@ -468,92 +471,4 @@ public final class GroupChangeUtil_resolveConflict_Test {
|
||||
|
||||
assertTrue(GroupChangeUtil.changeIsEmpty(resolvedActions));
|
||||
}
|
||||
|
||||
private static ProfileKey randomProfileKey() {
|
||||
byte[] contents = new byte[32];
|
||||
new SecureRandom().nextBytes(contents);
|
||||
try {
|
||||
return new ProfileKey(contents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates encryption by creating a unique {@link ByteString} that won't equal a byte string created from the {@link UUID}.
|
||||
*/
|
||||
private static ByteString encrypt(UUID uuid) {
|
||||
byte[] uuidBytes = UuidUtil.toByteArray(uuid);
|
||||
return ByteString.copyFrom(Arrays.copyOf(uuidBytes, uuidBytes.length + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates a presentation by concatenating the uuid and profile key which makes it suitable for
|
||||
* equality assertions in these tests.
|
||||
*/
|
||||
private static ByteString presentation(UUID uuid, ProfileKey profileKey) {
|
||||
byte[] uuidBytes = UuidUtil.toByteArray(uuid);
|
||||
byte[] profileKeyBytes = profileKey.serialize();
|
||||
byte[] concat = new byte[uuidBytes.length + profileKeyBytes.length];
|
||||
|
||||
System.arraycopy(uuidBytes, 0, concat, 0, uuidBytes.length);
|
||||
System.arraycopy(profileKeyBytes, 0, concat, uuidBytes.length, profileKeyBytes.length);
|
||||
|
||||
return ByteString.copyFrom(concat);
|
||||
}
|
||||
|
||||
private static DecryptedModifyMemberRole promoteAdmin(UUID member) {
|
||||
return DecryptedModifyMemberRole.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(member))
|
||||
.setRole(Member.Role.ADMINISTRATOR)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static DecryptedModifyMemberRole demoteAdmin(UUID member) {
|
||||
return DecryptedModifyMemberRole.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(member))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Member encryptedMember(UUID uuid, ProfileKey profileKey) {
|
||||
return Member.newBuilder()
|
||||
.setPresentation(presentation(uuid, profileKey))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static DecryptedMember member(UUID uuid) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static DecryptedPendingMemberRemoval pendingMemberRemoval(UUID uuid) {
|
||||
return DecryptedPendingMemberRemoval.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static DecryptedPendingMember pendingMember(UUID uuid) {
|
||||
return DecryptedPendingMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static DecryptedMember member(UUID uuid, ProfileKey profileKey) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static DecryptedMember admin(UUID uuid) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setRole(Member.Role.ADMINISTRATOR)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package org.whispersystems.signalservice.api.groupsv2;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedModifyMemberRole;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMemberRemoval;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.profiles.ProfileKey;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
final class ProtoTestUtils {
|
||||
|
||||
static ProfileKey randomProfileKey() {
|
||||
byte[] contents = new byte[32];
|
||||
new SecureRandom().nextBytes(contents);
|
||||
try {
|
||||
return new ProfileKey(contents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates encryption by creating a unique {@link ByteString} that won't equal a byte string created from the {@link UUID}.
|
||||
*/
|
||||
static ByteString encrypt(UUID uuid) {
|
||||
byte[] uuidBytes = UuidUtil.toByteArray(uuid);
|
||||
return ByteString.copyFrom(Arrays.copyOf(uuidBytes, uuidBytes.length + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates a presentation by concatenating the uuid and profile key which makes it suitable for
|
||||
* equality assertions in these tests.
|
||||
*/
|
||||
static ByteString presentation(UUID uuid, ProfileKey profileKey) {
|
||||
byte[] uuidBytes = UuidUtil.toByteArray(uuid);
|
||||
byte[] profileKeyBytes = profileKey.serialize();
|
||||
byte[] concat = new byte[uuidBytes.length + profileKeyBytes.length];
|
||||
|
||||
System.arraycopy(uuidBytes, 0, concat, 0, uuidBytes.length);
|
||||
System.arraycopy(profileKeyBytes, 0, concat, uuidBytes.length, profileKeyBytes.length);
|
||||
|
||||
return ByteString.copyFrom(concat);
|
||||
}
|
||||
|
||||
static DecryptedModifyMemberRole promoteAdmin(UUID member) {
|
||||
return DecryptedModifyMemberRole.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(member))
|
||||
.setRole(Member.Role.ADMINISTRATOR)
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedModifyMemberRole demoteAdmin(UUID member) {
|
||||
return DecryptedModifyMemberRole.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(member))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
|
||||
static Member encryptedMember(UUID uuid, ProfileKey profileKey) {
|
||||
return Member.newBuilder()
|
||||
.setPresentation(presentation(uuid, profileKey))
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedMember member(UUID uuid) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedPendingMemberRemoval pendingMemberRemoval(UUID uuid) {
|
||||
return DecryptedPendingMemberRemoval.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setUuidCipherText(encrypt(uuid))
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedPendingMember pendingMember(UUID uuid) {
|
||||
return DecryptedPendingMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setUuidCipherText(encrypt(uuid))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedMember member(UUID uuid, ProfileKey profileKey) {
|
||||
return withProfileKey(member(uuid), profileKey);
|
||||
}
|
||||
|
||||
static DecryptedMember admin(UUID uuid) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(UuidUtil.toByteString(uuid))
|
||||
.setRole(Member.Role.ADMINISTRATOR)
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedMember withProfileKey(DecryptedMember member, ProfileKey profileKey) {
|
||||
return DecryptedMember.newBuilder(member)
|
||||
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedMember asAdmin(DecryptedMember member) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(member.getUuid())
|
||||
.setRole(Member.Role.ADMINISTRATOR)
|
||||
.build();
|
||||
}
|
||||
|
||||
static DecryptedMember asMember(DecryptedMember member) {
|
||||
return DecryptedMember.newBuilder()
|
||||
.setUuid(member.getUuid())
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user