import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.whispersystems.signalservice.api.groupsv2.DecryptChangeVerificationMode;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupResponse;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.util.UuidUtil;
+import org.whispersystems.signalservice.internal.push.exceptions.NotInGroupException;
import java.io.IOException;
import java.util.ArrayList;
final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams);
return dependencies.getGroupsV2Api().getGroup(groupSecretParams, groupsV2AuthorizationString);
} catch (NonSuccessfulResponseCodeException e) {
- if (e.getCode() == 403) {
+ if (e.code == 403) {
throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null);
}
logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage());
}
DecryptedGroupJoinInfo getDecryptedGroupJoinInfo(
- GroupMasterKey groupMasterKey, GroupLinkPassword password
+ GroupMasterKey groupMasterKey,
+ GroupLinkPassword password
) throws IOException, GroupLinkNotActiveException {
var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
}
GroupHistoryPage getDecryptedGroupHistoryPage(
- final GroupSecretParams groupSecretParams, int fromRevision, long sendEndorsementsExpirationMs
+ final GroupSecretParams groupSecretParams,
+ int fromRevision,
+ long sendEndorsementsExpirationMs
) throws NotAGroupMemberException {
try {
final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams);
groupsV2AuthorizationString,
false,
sendEndorsementsExpirationMs);
+ } catch (NotInGroupException e) {
+ throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null);
} catch (NonSuccessfulResponseCodeException e) {
- if (e.getCode() == 403) {
+ if (e.code == 403) {
throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null);
}
logger.warn("Failed to retrieve Group V2 history, ignoring: {}", e.getMessage());
return partialDecryptedGroup.revision;
}
- Pair<GroupInfoV2, DecryptedGroupResponse> createGroup(
- String name, Set<RecipientId> members, byte[] avatarFile
- ) {
+ Pair<GroupInfoV2, DecryptedGroupResponse> createGroup(String name, Set<RecipientId> members, byte[] avatarFile) {
final var newGroup = buildNewGroup(name, members, avatarFile);
if (newGroup == null) {
return null;
return new Pair<>(g, response);
}
- private GroupsV2Operations.NewGroup buildNewGroup(
- String name, Set<RecipientId> members, byte[] avatar
- ) {
+ private GroupsV2Operations.NewGroup buildNewGroup(String name, Set<RecipientId> members, byte[] avatar) {
final var profileKeyCredential = context.getProfileHelper()
.getExpiringProfileKeyCredential(context.getAccount().getSelfRecipientId());
if (profileKeyCredential == null) {
}
Pair<DecryptedGroup, GroupChangeResponse> updateGroup(
- GroupInfoV2 groupInfoV2, String name, String description, byte[] avatarFile
+ GroupInfoV2 groupInfoV2,
+ String name,
+ String description,
+ byte[] avatarFile
) throws IOException {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
}
Pair<DecryptedGroup, GroupChangeResponse> addMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> newMembers
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> newMembers
) throws IOException {
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
}
Pair<DecryptedGroup, GroupChangeResponse> leaveGroup(
- GroupInfoV2 groupInfoV2, Set<RecipientId> membersToMakeAdmin
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> membersToMakeAdmin
) throws IOException {
var pendingMembersList = groupInfoV2.getGroup().pendingMembers;
final var selfAci = getSelfAci();
}
Pair<DecryptedGroup, GroupChangeResponse> removeMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> members
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> members
) throws IOException {
final var memberUuids = members.stream()
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
}
Pair<DecryptedGroup, GroupChangeResponse> approveJoinRequestMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> members
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> members
) throws IOException {
final var memberUuids = members.stream()
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
}
Pair<DecryptedGroup, GroupChangeResponse> refuseJoinRequestMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> members
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> members
) throws IOException {
final var memberUuids = members.stream()
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
}
Pair<DecryptedGroup, GroupChangeResponse> revokeInvitedMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> members
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> members
) throws IOException {
var pendingMembersList = groupInfoV2.getGroup().pendingMembers;
final var memberUuids = members.stream()
}
Pair<DecryptedGroup, GroupChangeResponse> banMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> block
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> block
) throws IOException {
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
}
Pair<DecryptedGroup, GroupChangeResponse> unbanMembers(
- GroupInfoV2 groupInfoV2, Set<RecipientId> block
+ GroupInfoV2 groupInfoV2,
+ Set<RecipientId> block
) throws IOException {
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
}
Pair<DecryptedGroup, GroupChangeResponse> setGroupLinkState(
- GroupInfoV2 groupInfoV2, GroupLinkState state
+ GroupInfoV2 groupInfoV2,
+ GroupLinkState state
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
}
Pair<DecryptedGroup, GroupChangeResponse> setEditDetailsPermission(
- GroupInfoV2 groupInfoV2, GroupPermission permission
+ GroupInfoV2 groupInfoV2,
+ GroupPermission permission
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
}
Pair<DecryptedGroup, GroupChangeResponse> setAddMemberPermission(
- GroupInfoV2 groupInfoV2, GroupPermission permission
+ GroupInfoV2 groupInfoV2,
+ GroupPermission permission
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
}
Pair<DecryptedGroup, GroupChangeResponse> setMemberAdmin(
- GroupInfoV2 groupInfoV2, RecipientId recipientId, boolean admin
+ GroupInfoV2 groupInfoV2,
+ RecipientId recipientId,
+ boolean admin
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
final var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
}
Pair<DecryptedGroup, GroupChangeResponse> setMessageExpirationTimer(
- GroupInfoV2 groupInfoV2, int messageExpirationTimer
+ GroupInfoV2 groupInfoV2,
+ int messageExpirationTimer
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
final var change = groupOperations.createModifyGroupTimerChange(messageExpirationTimer);
}
Pair<DecryptedGroup, GroupChangeResponse> setIsAnnouncementGroup(
- GroupInfoV2 groupInfoV2, boolean isAnnouncementGroup
+ GroupInfoV2 groupInfoV2,
+ boolean isAnnouncementGroup
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
final var change = groupOperations.createAnnouncementGroupChange(isAnnouncementGroup);
}
private Pair<DecryptedGroup, GroupChangeResponse> revokeInvites(
- GroupInfoV2 groupInfoV2, Set<DecryptedPendingMember> pendingMembers
+ GroupInfoV2 groupInfoV2,
+ Set<DecryptedPendingMember> pendingMembers
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
final var uuidCipherTexts = pendingMembers.stream().map(member -> {
}
private Pair<DecryptedGroup, GroupChangeResponse> approveJoinRequest(
- GroupInfoV2 groupInfoV2, Set<UUID> uuids
+ GroupInfoV2 groupInfoV2,
+ Set<UUID> uuids
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
return commitChange(groupInfoV2, groupOperations.createApproveGroupJoinRequest(uuids));
}
private Pair<DecryptedGroup, GroupChangeResponse> refuseJoinRequest(
- GroupInfoV2 groupInfoV2, Set<ServiceId> serviceIds
+ GroupInfoV2 groupInfoV2,
+ Set<ServiceId> serviceIds
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
return commitChange(groupInfoV2, groupOperations.createRefuseGroupJoinRequest(serviceIds, false, List.of()));
}
private Pair<DecryptedGroup, GroupChangeResponse> ejectMembers(
- GroupInfoV2 groupInfoV2, Set<ACI> members
+ GroupInfoV2 groupInfoV2,
+ Set<ACI> members
) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
return commitChange(groupInfoV2, groupOperations.createRemoveMembersChange(members, false, List.of()));
}
private Pair<DecryptedGroup, GroupChangeResponse> commitChange(
- GroupInfoV2 groupInfoV2, GroupChange.Actions.Builder change
+ GroupInfoV2 groupInfoV2,
+ GroupChange.Actions.Builder change
) throws IOException {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
final var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
DecryptedGroupChange getDecryptedGroupChange(byte[] signedGroupChange, GroupMasterKey groupMasterKey) {
if (signedGroupChange != null) {
- var groupOperations = dependencies.getGroupsV2Operations()
- .forGroup(GroupSecretParams.deriveFromMasterKey(groupMasterKey));
+ final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
+ final var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
+ final var groupId = groupSecretParams.getPublicParams().getGroupIdentifier();
try {
- return groupOperations.decryptChange(GroupChange.ADAPTER.decode(signedGroupChange), true).orElse(null);
+ return groupOperations.decryptChange(GroupChange.ADAPTER.decode(signedGroupChange),
+ DecryptChangeVerificationMode.verify(groupId)).orElse(null);
} catch (VerificationFailedException | InvalidGroupStateException | IOException e) {
return null;
}
}
private GroupsV2AuthorizationString getAuthorizationString(
- final GroupSecretParams groupSecretParams, final long todaySeconds
+ final GroupSecretParams groupSecretParams,
+ final long todaySeconds
) throws VerificationFailedException {
var authCredentialResponse = groupApiCredentials.get(todaySeconds);
final var aci = getSelfAci();