use of org.signal.storageservice.protos.groups.local.DecryptedPendingMember in project Signal-Android by WhisperSystems.
the class DecryptedGroupUtil method applyAddPendingMemberActions.
private static void applyAddPendingMemberActions(DecryptedGroup.Builder builder, List<DecryptedPendingMember> newPendingMembersList) throws NotAbleToApplyGroupV2ChangeException {
Set<ByteString> fullMemberSet = getMemberUuidSet(builder.getMembersList());
Set<ByteString> pendingMemberCipherTexts = getPendingMemberCipherTextSet(builder.getPendingMembersList());
for (DecryptedPendingMember pendingMember : newPendingMembersList) {
if (fullMemberSet.contains(pendingMember.getUuid())) {
throw new NotAbleToApplyGroupV2ChangeException();
}
if (!pendingMemberCipherTexts.contains(pendingMember.getUuidCipherText())) {
builder.addPendingMembers(pendingMember);
}
}
}
use of org.signal.storageservice.protos.groups.local.DecryptedPendingMember in project Signal-Android by WhisperSystems.
the class GroupChangeReconstruct method reconstructGroupChange.
/**
* Given a {@param fromState} and a {@param toState} creates a {@link DecryptedGroupChange} that would take the {@param fromState} to the {@param toState}.
*/
public static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState) {
DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder().setRevision(toState.getRevision());
if (!fromState.getTitle().equals(toState.getTitle())) {
builder.setNewTitle(DecryptedString.newBuilder().setValue(toState.getTitle()));
}
if (!fromState.getDescription().equals(toState.getDescription())) {
builder.setNewDescription(DecryptedString.newBuilder().setValue(toState.getDescription()));
}
if (!fromState.getIsAnnouncementGroup().equals(toState.getIsAnnouncementGroup())) {
builder.setNewIsAnnouncementGroup(toState.getIsAnnouncementGroup());
}
if (!fromState.getAvatar().equals(toState.getAvatar())) {
builder.setNewAvatar(DecryptedString.newBuilder().setValue(toState.getAvatar()));
}
if (!fromState.getDisappearingMessagesTimer().equals(toState.getDisappearingMessagesTimer())) {
builder.setNewTimer(toState.getDisappearingMessagesTimer());
}
if (!fromState.getAccessControl().getAttributes().equals(toState.getAccessControl().getAttributes())) {
builder.setNewAttributeAccess(toState.getAccessControl().getAttributes());
}
if (!fromState.getAccessControl().getMembers().equals(toState.getAccessControl().getMembers())) {
builder.setNewMemberAccess(toState.getAccessControl().getMembers());
}
Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList());
Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList());
Set<ByteString> pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList());
Set<ByteString> pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList());
Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList());
Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList());
Set<ByteString> removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB);
Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB);
Set<ByteString> newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA);
Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA);
Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids);
Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids);
Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids);
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 = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids));
Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids));
for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) {
builder.addDeleteMembers(member.getUuid());
}
for (DecryptedMember member : addedMembers) {
builder.addNewMembers(member);
}
for (DecryptedMember member : addedMembersByInvitation) {
builder.addPromotePendingMembers(member);
}
for (DecryptedPendingMember uninvitedMember : uninvitedMembers) {
builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder().setUuid(uninvitedMember.getUuid()).setUuidCipherText(uninvitedMember.getUuidCipherText()));
}
for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) {
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());
for (DecryptedMember newState : changedMembers) {
DecryptedMember oldState = membersUuidMap.get(newState.getUuid());
if (oldState.getRole() != newState.getRole()) {
builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder().setUuid(newState.getUuid()).setRole(newState.getRole()));
}
if (!oldState.getProfileKey().equals(newState.getProfileKey())) {
builder.addModifiedProfileKeys(newState);
}
}
if (!fromState.getAccessControl().getAddFromInviteLink().equals(toState.getAccessControl().getAddFromInviteLink())) {
builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink());
}
for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) {
builder.addNewRequestingMembers(requestingMember);
}
for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) {
builder.addDeleteRequestingMembers(requestingMember.getUuid());
}
for (DecryptedMember member : addedMembersByRequestApproval) {
builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder().setUuid(member.getUuid()).setRole(member.getRole()));
}
if (!fromState.getInviteLinkPassword().equals(toState.getInviteLinkPassword())) {
builder.setNewInviteLinkPassword(toState.getInviteLinkPassword());
}
return builder.build();
}
use of org.signal.storageservice.protos.groups.local.DecryptedPendingMember in project Signal-Android by WhisperSystems.
the class GroupChangeUtil method resolveConflict.
private static void resolveConflict(DecryptedGroup groupState, DecryptedGroupChange conflictingChange, ChangeSetModifier changeSetModifier) {
HashMap<ByteString, DecryptedMember> fullMembersByUuid = new HashMap<>(groupState.getMembersCount());
HashMap<ByteString, DecryptedPendingMember> pendingMembersByUuid = new HashMap<>(groupState.getPendingMembersCount());
HashMap<ByteString, DecryptedRequestingMember> requestingMembersByUuid = new HashMap<>(groupState.getMembersCount());
for (DecryptedMember member : groupState.getMembersList()) {
fullMembersByUuid.put(member.getUuid(), member);
}
for (DecryptedPendingMember member : groupState.getPendingMembersList()) {
pendingMembersByUuid.put(member.getUuid(), member);
}
for (DecryptedRequestingMember member : groupState.getRequestingMembersList()) {
requestingMembersByUuid.put(member.getUuid(), member);
}
resolveField3AddMembers(conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByUuid);
resolveField4DeleteMembers(conflictingChange, changeSetModifier, fullMembersByUuid);
resolveField5ModifyMemberRoles(conflictingChange, changeSetModifier, fullMembersByUuid);
resolveField6ModifyProfileKeys(conflictingChange, changeSetModifier, fullMembersByUuid);
resolveField7AddPendingMembers(conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByUuid);
resolveField8DeletePendingMembers(conflictingChange, changeSetModifier, pendingMembersByUuid);
resolveField9PromotePendingMembers(conflictingChange, changeSetModifier, pendingMembersByUuid);
resolveField10ModifyTitle(groupState, conflictingChange, changeSetModifier);
resolveField11ModifyAvatar(groupState, conflictingChange, changeSetModifier);
resolveField12modifyDisappearingMessagesTimer(groupState, conflictingChange, changeSetModifier);
resolveField13modifyAttributesAccess(groupState, conflictingChange, changeSetModifier);
resolveField14modifyAttributesAccess(groupState, conflictingChange, changeSetModifier);
resolveField15modifyAddFromInviteLinkAccess(groupState, conflictingChange, changeSetModifier);
resolveField16AddRequestingMembers(conflictingChange, changeSetModifier, fullMembersByUuid, pendingMembersByUuid);
resolveField17DeleteMembers(conflictingChange, changeSetModifier, requestingMembersByUuid);
resolveField18PromoteRequestingMembers(conflictingChange, changeSetModifier, requestingMembersByUuid);
resolveField20ModifyDescription(groupState, conflictingChange, changeSetModifier);
resolveField21ModifyAnnouncementsOnly(groupState, conflictingChange, changeSetModifier);
}
use of org.signal.storageservice.protos.groups.local.DecryptedPendingMember in project Signal-Android by WhisperSystems.
the class DecryptedGroupUtil_apply_Test method skip_promote_pending_member_by_direct_add.
@Test
public void skip_promote_pending_member_by_direct_add() throws NotAbleToApplyGroupV2ChangeException {
ProfileKey profileKey2 = randomProfileKey();
ProfileKey profileKey3 = randomProfileKey();
DecryptedMember member1 = member(UUID.randomUUID());
UUID pending2Uuid = UUID.randomUUID();
UUID pending3Uuid = UUID.randomUUID();
UUID pending4Uuid = UUID.randomUUID();
DecryptedPendingMember pending2 = pendingMember(pending2Uuid);
DecryptedPendingMember pending3 = pendingMember(pending3Uuid);
DecryptedPendingMember pending4 = pendingMember(pending4Uuid);
DecryptedMember member2 = member(pending2Uuid, profileKey2);
DecryptedMember member3 = member(pending3Uuid, profileKey3);
DecryptedGroup newGroup = DecryptedGroupUtil.apply(DecryptedGroup.newBuilder().setRevision(10).addMembers(member1).addPendingMembers(pending2).addPendingMembers(pending3).addPendingMembers(pending4).build(), DecryptedGroupChange.newBuilder().setRevision(11).addNewMembers(member2).addNewMembers(member3).build());
assertEquals(DecryptedGroup.newBuilder().setRevision(11).addMembers(member1).addMembers(member2).addMembers(member3).addPendingMembers(pending4).build(), newGroup);
}
use of org.signal.storageservice.protos.groups.local.DecryptedPendingMember in project Signal-Android by WhisperSystems.
the class DecryptedGroupUtil_apply_Test method apply_new_pending_member_already_in_group.
@Test(expected = NotAbleToApplyGroupV2ChangeException.class)
public void apply_new_pending_member_already_in_group() throws NotAbleToApplyGroupV2ChangeException {
DecryptedMember member1 = member(UUID.randomUUID());
UUID uuid2 = UUID.randomUUID();
DecryptedMember member2 = member(uuid2);
DecryptedPendingMember pending2 = pendingMember(uuid2);
DecryptedGroupUtil.apply(DecryptedGroup.newBuilder().setRevision(10).addMembers(member1).addMembers(member2).build(), DecryptedGroupChange.newBuilder().setRevision(11).addNewPendingMembers(pending2).build());
}
Aggregations