mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
Update libsignal-service
This commit is contained in:
parent
5ff66728e3
commit
e51b1ee23a
10 changed files with 201 additions and 137 deletions
|
@ -36,7 +36,6 @@ public class ProofRequiredException extends Exception {
|
|||
|
||||
static Option from(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException.Option option) {
|
||||
return switch (option) {
|
||||
case RECAPTCHA -> CAPTCHA;
|
||||
case CAPTCHA -> CAPTCHA;
|
||||
case PUSH_CHALLENGE -> PUSH_CHALLENGE;
|
||||
};
|
||||
|
|
|
@ -27,19 +27,8 @@ public class ServiceConfig {
|
|||
public static final long UNREGISTERED_LIFESPAN = TimeUnit.DAYS.toMillis(30);
|
||||
|
||||
public static AccountAttributes.Capabilities getCapabilities(boolean isPrimaryDevice) {
|
||||
final var giftBadges = !isPrimaryDevice;
|
||||
final var pni = !isPrimaryDevice;
|
||||
final var paymentActivation = !isPrimaryDevice;
|
||||
final var deleteSync = !isPrimaryDevice;
|
||||
return new AccountAttributes.Capabilities(true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
giftBadges,
|
||||
pni,
|
||||
paymentActivation,
|
||||
deleteSync);
|
||||
return new AccountAttributes.Capabilities(true, deleteSync);
|
||||
}
|
||||
|
||||
public static ServiceEnvironmentConfig getServiceEnvironmentConfig(
|
||||
|
|
|
@ -33,13 +33,16 @@ import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
|||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.storageservice.protos.groups.GroupChange;
|
||||
import org.signal.storageservice.protos.groups.GroupChangeResponse;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupResponse;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ReceivedGroupSendEndorsements;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
|
@ -133,9 +136,10 @@ public class GroupHelper {
|
|||
}
|
||||
if (group == null) {
|
||||
try {
|
||||
group = context.getGroupV2Helper().getDecryptedGroup(groupSecretParams);
|
||||
final var response = context.getGroupV2Helper().getDecryptedGroup(groupSecretParams);
|
||||
|
||||
if (group != null) {
|
||||
if (response != null) {
|
||||
group = handleDecryptedGroupResponse(groupInfoV2, response);
|
||||
storeProfileKeysFromHistory(groupSecretParams, groupInfoV2, group);
|
||||
}
|
||||
} catch (NotAGroupMemberException ignored) {
|
||||
|
@ -156,6 +160,35 @@ public class GroupHelper {
|
|||
return groupInfoV2;
|
||||
}
|
||||
|
||||
private DecryptedGroup handleDecryptedGroupResponse(
|
||||
GroupInfoV2 groupInfoV2, final DecryptedGroupResponse decryptedGroupResponse
|
||||
) {
|
||||
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
|
||||
ReceivedGroupSendEndorsements groupSendEndorsements = dependencies.getGroupsV2Operations()
|
||||
.forGroup(groupSecretParams)
|
||||
.receiveGroupSendEndorsements(account.getAci(),
|
||||
decryptedGroupResponse.getGroup(),
|
||||
decryptedGroupResponse.getGroupSendEndorsementsResponse());
|
||||
|
||||
// TODO save group endorsements
|
||||
|
||||
return decryptedGroupResponse.getGroup();
|
||||
}
|
||||
|
||||
private GroupChange handleGroupChangeResponse(
|
||||
final GroupInfoV2 groupInfoV2, final GroupChangeResponse groupChangeResponse
|
||||
) {
|
||||
ReceivedGroupSendEndorsements groupSendEndorsements = dependencies.getGroupsV2Operations()
|
||||
.forGroup(GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()))
|
||||
.receiveGroupSendEndorsements(account.getAci(),
|
||||
groupInfoV2.getGroup(),
|
||||
groupChangeResponse.groupSendEndorsementsResponse);
|
||||
|
||||
// TODO save group endorsements
|
||||
|
||||
return groupChangeResponse.groupChange;
|
||||
}
|
||||
|
||||
public Pair<GroupId, SendGroupMessageResults> createGroup(
|
||||
String name, Set<RecipientId> members, String avatarFile
|
||||
) throws IOException, AttachmentInvalidException {
|
||||
|
@ -181,7 +214,7 @@ public class GroupHelper {
|
|||
final var gv2 = gv2Pair.first();
|
||||
final var decryptedGroup = gv2Pair.second();
|
||||
|
||||
gv2.setGroup(decryptedGroup);
|
||||
gv2.setGroup(handleDecryptedGroupResponse(gv2, decryptedGroup));
|
||||
gv2.setProfileSharingEnabled(true);
|
||||
if (avatarBytes != null) {
|
||||
context.getAvatarStore()
|
||||
|
@ -277,7 +310,7 @@ public class GroupHelper {
|
|||
var group = getGroupForUpdating(groupId);
|
||||
|
||||
if (group instanceof GroupInfoV2 groupInfoV2) {
|
||||
Pair<DecryptedGroup, GroupChange> groupChangePair;
|
||||
Pair<DecryptedGroup, GroupChangeResponse> groupChangePair;
|
||||
try {
|
||||
groupChangePair = context.getGroupV2Helper().updateSelfProfileKey(groupInfoV2);
|
||||
} catch (ConflictException e) {
|
||||
|
@ -286,7 +319,9 @@ public class GroupHelper {
|
|||
groupChangePair = context.getGroupV2Helper().updateSelfProfileKey(groupInfoV2);
|
||||
}
|
||||
if (groupChangePair != null) {
|
||||
sendUpdateGroupV2Message(groupInfoV2, groupChangePair.first(), groupChangePair.second());
|
||||
sendUpdateGroupV2Message(groupInfoV2,
|
||||
groupChangePair.first(),
|
||||
handleGroupChangeResponse(groupInfoV2, groupChangePair.second()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,11 +339,12 @@ public class GroupHelper {
|
|||
if (groupJoinInfo.pendingAdminApproval) {
|
||||
throw new PendingAdminApprovalException("You have already requested to join the group.");
|
||||
}
|
||||
final var groupChange = context.getGroupV2Helper()
|
||||
final var changeResponse = context.getGroupV2Helper()
|
||||
.joinGroup(inviteLinkUrl.getGroupMasterKey(), inviteLinkUrl.getPassword(), groupJoinInfo);
|
||||
final var group = getOrMigrateGroup(inviteLinkUrl.getGroupMasterKey(),
|
||||
groupJoinInfo.revision + 1,
|
||||
groupChange.encode());
|
||||
changeResponse.groupChange == null ? null : changeResponse.groupChange.encode());
|
||||
final var groupChange = handleGroupChangeResponse(group, changeResponse);
|
||||
|
||||
if (group.getGroup() == null) {
|
||||
// Only requested member, can't send update to group members
|
||||
|
@ -404,17 +440,17 @@ public class GroupHelper {
|
|||
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
|
||||
DecryptedGroup decryptedGroup;
|
||||
try {
|
||||
decryptedGroup = context.getGroupV2Helper().getDecryptedGroup(groupSecretParams);
|
||||
final var response = context.getGroupV2Helper().getDecryptedGroup(groupSecretParams);
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
decryptedGroup = handleDecryptedGroupResponse(groupInfoV2, response);
|
||||
} catch (NotAGroupMemberException e) {
|
||||
groupInfoV2.setPermissionDenied(true);
|
||||
account.getGroupStore().updateGroup(group);
|
||||
return;
|
||||
}
|
||||
|
||||
if (decryptedGroup == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
storeProfileKeysFromHistory(groupSecretParams, groupInfoV2, decryptedGroup);
|
||||
} catch (NotAGroupMemberException ignored) {
|
||||
|
@ -496,10 +532,12 @@ public class GroupHelper {
|
|||
) throws NotAGroupMemberException {
|
||||
final var revisionWeWereAdded = context.getGroupV2Helper().findRevisionWeWereAdded(newDecryptedGroup);
|
||||
final var localRevision = localGroup.getGroup() == null ? 0 : localGroup.getGroup().revision;
|
||||
final var sendEndorsementsExpirationMs = 0L;// TODO store expiration localGroup.getGroup() == null ? 0 : localGroup.getGroup().revision;
|
||||
var fromRevision = Math.max(revisionWeWereAdded, localRevision);
|
||||
final var newProfileKeys = new HashMap<RecipientId, ProfileKey>();
|
||||
while (true) {
|
||||
final var page = context.getGroupV2Helper().getDecryptedGroupHistoryPage(groupSecretParams, fromRevision);
|
||||
final var page = context.getGroupV2Helper()
|
||||
.getDecryptedGroupHistoryPage(groupSecretParams, fromRevision, sendEndorsementsExpirationMs);
|
||||
page.getChangeLogs()
|
||||
.stream()
|
||||
.map(DecryptedGroupChangeLog::getChange)
|
||||
|
@ -606,7 +644,9 @@ public class GroupHelper {
|
|||
final var groupV2Helper = context.getGroupV2Helper();
|
||||
if (group.isPendingMember(account.getSelfRecipientId())) {
|
||||
var groupGroupChangePair = groupV2Helper.acceptInvite(group);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (members != null) {
|
||||
|
@ -614,14 +654,18 @@ public class GroupHelper {
|
|||
requestingMembers.retainAll(group.getRequestingMembers());
|
||||
if (!requestingMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.approveJoinRequestMembers(group, requestingMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
final var newMembers = new HashSet<>(members);
|
||||
newMembers.removeAll(group.getMembers());
|
||||
newMembers.removeAll(group.getRequestingMembers());
|
||||
if (!newMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.addMembers(group, newMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -637,20 +681,26 @@ public class GroupHelper {
|
|||
existingRemoveMembers.remove(account.getSelfRecipientId());// self can be removed with sendQuitGroupMessage
|
||||
if (!existingRemoveMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.removeMembers(group, existingRemoveMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
var pendingRemoveMembers = new HashSet<>(removeMembers);
|
||||
pendingRemoveMembers.retainAll(group.getPendingMembers());
|
||||
if (!pendingRemoveMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.revokeInvitedMembers(group, pendingRemoveMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
var requestingRemoveMembers = new HashSet<>(removeMembers);
|
||||
requestingRemoveMembers.retainAll(group.getRequestingMembers());
|
||||
if (!requestingRemoveMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.refuseJoinRequestMembers(group, requestingRemoveMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +713,7 @@ public class GroupHelper {
|
|||
var groupGroupChangePair = groupV2Helper.setMemberAdmin(group, admin, true);
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
groupGroupChangePair.second());
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -676,7 +726,7 @@ public class GroupHelper {
|
|||
var groupGroupChangePair = groupV2Helper.setMemberAdmin(group, admin, false);
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
groupGroupChangePair.second());
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -686,7 +736,9 @@ public class GroupHelper {
|
|||
newlyBannedMembers.removeAll(group.getBannedMembers());
|
||||
if (!newlyBannedMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.banMembers(group, newlyBannedMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -695,38 +747,52 @@ public class GroupHelper {
|
|||
existingUnbanMembers.retainAll(group.getBannedMembers());
|
||||
if (!existingUnbanMembers.isEmpty()) {
|
||||
var groupGroupChangePair = groupV2Helper.unbanMembers(group, existingUnbanMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
}
|
||||
|
||||
if (resetGroupLink) {
|
||||
var groupGroupChangePair = groupV2Helper.resetGroupLinkPassword(group);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (groupLinkState != null) {
|
||||
var groupGroupChangePair = groupV2Helper.setGroupLinkState(group, groupLinkState);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (addMemberPermission != null) {
|
||||
var groupGroupChangePair = groupV2Helper.setAddMemberPermission(group, addMemberPermission);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (editDetailsPermission != null) {
|
||||
var groupGroupChangePair = groupV2Helper.setEditDetailsPermission(group, editDetailsPermission);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (expirationTimer != null) {
|
||||
var groupGroupChangePair = groupV2Helper.setMessageExpirationTimer(group, expirationTimer);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (isAnnouncementGroup != null) {
|
||||
var groupGroupChangePair = groupV2Helper.setIsAnnouncementGroup(group, isAnnouncementGroup);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
if (name != null || description != null || avatarFile != null) {
|
||||
|
@ -735,7 +801,9 @@ public class GroupHelper {
|
|||
context.getAvatarStore()
|
||||
.storeGroupAvatar(group.getGroupId(), outputStream -> outputStream.write(avatarFile));
|
||||
}
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
result = sendUpdateGroupV2Message(group,
|
||||
groupGroupChangePair.first(),
|
||||
handleGroupChangeResponse(group, groupGroupChangePair.second()));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -771,7 +839,8 @@ public class GroupHelper {
|
|||
groupInfoV2.setGroup(groupGroupChangePair.first());
|
||||
account.getGroupStore().updateGroup(groupInfoV2);
|
||||
|
||||
var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupGroupChangePair.second().encode());
|
||||
var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2,
|
||||
handleGroupChangeResponse(groupInfoV2, groupGroupChangePair.second()).encode());
|
||||
return sendGroupMessage(messageBuilder,
|
||||
groupInfoV2.getMembersIncludingPendingWithout(account.getSelfRecipientId()),
|
||||
groupInfoV2.getDistributionId());
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
|
|||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.GroupChange;
|
||||
import org.signal.storageservice.protos.groups.GroupChangeResponse;
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
|
@ -27,6 +28,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
|||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.groupsv2.GroupHistoryPage;
|
||||
|
@ -75,7 +77,7 @@ class GroupV2Helper {
|
|||
groupApiCredentials = null;
|
||||
}
|
||||
|
||||
DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) throws NotAGroupMemberException {
|
||||
DecryptedGroupResponse getDecryptedGroup(final GroupSecretParams groupSecretParams) throws NotAGroupMemberException {
|
||||
try {
|
||||
final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams);
|
||||
return dependencies.getGroupsV2Api().getGroup(groupSecretParams, groupsV2AuthorizationString);
|
||||
|
@ -85,7 +87,7 @@ class GroupV2Helper {
|
|||
}
|
||||
logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage());
|
||||
return null;
|
||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException | InvalidInputException e) {
|
||||
logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
@ -103,19 +105,23 @@ class GroupV2Helper {
|
|||
}
|
||||
|
||||
GroupHistoryPage getDecryptedGroupHistoryPage(
|
||||
final GroupSecretParams groupSecretParams, int fromRevision
|
||||
final GroupSecretParams groupSecretParams, int fromRevision, long sendEndorsementsExpirationMs
|
||||
) throws NotAGroupMemberException {
|
||||
try {
|
||||
final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams);
|
||||
return dependencies.getGroupsV2Api()
|
||||
.getGroupHistoryPage(groupSecretParams, fromRevision, groupsV2AuthorizationString, false);
|
||||
.getGroupHistoryPage(groupSecretParams,
|
||||
fromRevision,
|
||||
groupsV2AuthorizationString,
|
||||
false,
|
||||
sendEndorsementsExpirationMs);
|
||||
} catch (NonSuccessfulResponseCodeException e) {
|
||||
if (e.getCode() == 403) {
|
||||
throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null);
|
||||
}
|
||||
logger.warn("Failed to retrieve Group V2 history, ignoring: {}", e.getMessage());
|
||||
return null;
|
||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException | InvalidInputException e) {
|
||||
logger.warn("Failed to retrieve Group V2 history, ignoring: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
@ -132,7 +138,7 @@ class GroupV2Helper {
|
|||
return partialDecryptedGroup.revision;
|
||||
}
|
||||
|
||||
Pair<GroupInfoV2, DecryptedGroup> createGroup(
|
||||
Pair<GroupInfoV2, DecryptedGroupResponse> createGroup(
|
||||
String name, Set<RecipientId> members, byte[] avatarFile
|
||||
) {
|
||||
final var newGroup = buildNewGroup(name, members, avatarFile);
|
||||
|
@ -143,16 +149,16 @@ class GroupV2Helper {
|
|||
final var groupSecretParams = newGroup.getGroupSecretParams();
|
||||
|
||||
final GroupsV2AuthorizationString groupAuthForToday;
|
||||
final DecryptedGroup decryptedGroup;
|
||||
final DecryptedGroupResponse response;
|
||||
try {
|
||||
groupAuthForToday = getGroupAuthForToday(groupSecretParams);
|
||||
dependencies.getGroupsV2Api().putNewGroup(newGroup, groupAuthForToday);
|
||||
decryptedGroup = dependencies.getGroupsV2Api().getGroup(groupSecretParams, groupAuthForToday);
|
||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
||||
response = dependencies.getGroupsV2Api().getGroup(groupSecretParams, groupAuthForToday);
|
||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException | InvalidInputException e) {
|
||||
logger.warn("Failed to create V2 group: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
if (decryptedGroup == null) {
|
||||
if (response == null) {
|
||||
logger.warn("Failed to create V2 group, unknown error!");
|
||||
return null;
|
||||
}
|
||||
|
@ -161,7 +167,7 @@ class GroupV2Helper {
|
|||
final var masterKey = groupSecretParams.getMasterKey();
|
||||
var g = new GroupInfoV2(groupId, masterKey, context.getAccount().getRecipientResolver());
|
||||
|
||||
return new Pair<>(g, decryptedGroup);
|
||||
return new Pair<>(g, response);
|
||||
}
|
||||
|
||||
private GroupsV2Operations.NewGroup buildNewGroup(
|
||||
|
@ -195,7 +201,7 @@ class GroupV2Helper {
|
|||
0);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> updateGroup(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> updateGroup(
|
||||
GroupInfoV2 groupInfoV2, String name, String description, byte[] avatarFile
|
||||
) throws IOException {
|
||||
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
|
||||
|
@ -218,7 +224,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> addMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> addMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> newMembers
|
||||
) throws IOException {
|
||||
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -244,7 +250,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> leaveGroup(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> leaveGroup(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> membersToMakeAdmin
|
||||
) throws IOException {
|
||||
var pendingMembersList = groupInfoV2.getGroup().pendingMembers;
|
||||
|
@ -264,7 +270,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci, adminUuids));
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> removeMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> removeMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> members
|
||||
) throws IOException {
|
||||
final var memberUuids = members.stream()
|
||||
|
@ -276,7 +282,7 @@ class GroupV2Helper {
|
|||
return ejectMembers(groupInfoV2, memberUuids);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> approveJoinRequestMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> approveJoinRequestMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> members
|
||||
) throws IOException {
|
||||
final var memberUuids = members.stream()
|
||||
|
@ -287,7 +293,7 @@ class GroupV2Helper {
|
|||
return approveJoinRequest(groupInfoV2, memberUuids);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> refuseJoinRequestMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> refuseJoinRequestMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> members
|
||||
) throws IOException {
|
||||
final var memberUuids = members.stream()
|
||||
|
@ -297,7 +303,7 @@ class GroupV2Helper {
|
|||
return refuseJoinRequest(groupInfoV2, memberUuids);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> revokeInvitedMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> revokeInvitedMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> members
|
||||
) throws IOException {
|
||||
var pendingMembersList = groupInfoV2.getGroup().pendingMembers;
|
||||
|
@ -311,7 +317,7 @@ class GroupV2Helper {
|
|||
return revokeInvites(groupInfoV2, memberUuids);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> banMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> banMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> block
|
||||
) throws IOException {
|
||||
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -329,7 +335,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> unbanMembers(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> unbanMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> block
|
||||
) throws IOException {
|
||||
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -345,14 +351,14 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> resetGroupLinkPassword(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
Pair<DecryptedGroup, GroupChangeResponse> resetGroupLinkPassword(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
final var newGroupLinkPassword = GroupLinkPassword.createNew().serialize();
|
||||
final var change = groupOperations.createModifyGroupLinkPasswordChange(newGroupLinkPassword);
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> setGroupLinkState(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> setGroupLinkState(
|
||||
GroupInfoV2 groupInfoV2, GroupLinkState state
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -367,7 +373,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> setEditDetailsPermission(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> setEditDetailsPermission(
|
||||
GroupInfoV2 groupInfoV2, GroupPermission permission
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -377,7 +383,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> setAddMemberPermission(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> setAddMemberPermission(
|
||||
GroupInfoV2 groupInfoV2, GroupPermission permission
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -387,7 +393,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> updateSelfProfileKey(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
Pair<DecryptedGroup, GroupChangeResponse> updateSelfProfileKey(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
Optional<DecryptedMember> selfInGroup = groupInfoV2.getGroup() == null
|
||||
? Optional.empty()
|
||||
: DecryptedGroupUtil.findMemberByAci(groupInfoV2.getGroup().members, getSelfAci());
|
||||
|
@ -417,7 +423,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
GroupChange joinGroup(
|
||||
GroupChangeResponse joinGroup(
|
||||
GroupMasterKey groupMasterKey,
|
||||
GroupLinkPassword groupLinkPassword,
|
||||
DecryptedGroupJoinInfo decryptedGroupJoinInfo
|
||||
|
@ -444,7 +450,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupSecretParams, decryptedGroupJoinInfo.revision, change, groupLinkPassword);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> acceptInvite(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
Pair<DecryptedGroup, GroupChangeResponse> acceptInvite(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
||||
final var selfRecipientId = context.getAccount().getSelfRecipientId();
|
||||
|
@ -461,7 +467,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> setMemberAdmin(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> setMemberAdmin(
|
||||
GroupInfoV2 groupInfoV2, RecipientId recipientId, boolean admin
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -475,7 +481,7 @@ class GroupV2Helper {
|
|||
}
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> setMessageExpirationTimer(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> setMessageExpirationTimer(
|
||||
GroupInfoV2 groupInfoV2, int messageExpirationTimer
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -483,7 +489,7 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> setIsAnnouncementGroup(
|
||||
Pair<DecryptedGroup, GroupChangeResponse> setIsAnnouncementGroup(
|
||||
GroupInfoV2 groupInfoV2, boolean isAnnouncementGroup
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -511,7 +517,7 @@ class GroupV2Helper {
|
|||
return dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
|
||||
}
|
||||
|
||||
private Pair<DecryptedGroup, GroupChange> revokeInvites(
|
||||
private Pair<DecryptedGroup, GroupChangeResponse> revokeInvites(
|
||||
GroupInfoV2 groupInfoV2, Set<DecryptedPendingMember> pendingMembers
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
@ -525,28 +531,28 @@ class GroupV2Helper {
|
|||
return commitChange(groupInfoV2, groupOperations.createRemoveInvitationChange(uuidCipherTexts));
|
||||
}
|
||||
|
||||
private Pair<DecryptedGroup, GroupChange> approveJoinRequest(
|
||||
private Pair<DecryptedGroup, GroupChangeResponse> approveJoinRequest(
|
||||
GroupInfoV2 groupInfoV2, Set<UUID> uuids
|
||||
) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
return commitChange(groupInfoV2, groupOperations.createApproveGroupJoinRequest(uuids));
|
||||
}
|
||||
|
||||
private Pair<DecryptedGroup, GroupChange> refuseJoinRequest(
|
||||
private Pair<DecryptedGroup, GroupChangeResponse> refuseJoinRequest(
|
||||
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, GroupChange> ejectMembers(
|
||||
private Pair<DecryptedGroup, GroupChangeResponse> ejectMembers(
|
||||
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, GroupChange> commitChange(
|
||||
private Pair<DecryptedGroup, GroupChangeResponse> commitChange(
|
||||
GroupInfoV2 groupInfoV2, GroupChange.Actions.Builder change
|
||||
) throws IOException {
|
||||
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
|
||||
|
@ -567,10 +573,12 @@ class GroupV2Helper {
|
|||
var signedGroupChange = dependencies.getGroupsV2Api()
|
||||
.patchGroup(changeActions, getGroupAuthForToday(groupSecretParams), Optional.empty());
|
||||
|
||||
groupInfoV2.setGroup(decryptedGroupState);
|
||||
|
||||
return new Pair<>(decryptedGroupState, signedGroupChange);
|
||||
}
|
||||
|
||||
private GroupChange commitChange(
|
||||
private GroupChangeResponse commitChange(
|
||||
GroupSecretParams groupSecretParams,
|
||||
int currentRevision,
|
||||
GroupChange.Actions.Builder change,
|
||||
|
|
|
@ -16,13 +16,14 @@ import org.asamk.signal.manager.util.KeyUtils;
|
|||
import org.asamk.signal.manager.util.PaymentUtils;
|
||||
import org.asamk.signal.manager.util.ProfileUtils;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.SealedSenderAccess;
|
||||
import org.whispersystems.signalservice.api.profiles.AvatarUploadParams;
|
||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||
|
@ -387,7 +388,7 @@ public final class ProfileHelper {
|
|||
private Single<ProfileAndCredential> retrieveProfile(
|
||||
SignalServiceAddress address,
|
||||
Optional<ProfileKey> profileKey,
|
||||
Optional<UnidentifiedAccess> unidentifiedAccess,
|
||||
@Nullable SealedSenderAccess unidentifiedAccess,
|
||||
SignalServiceProfile.RequestType requestType
|
||||
) {
|
||||
final var profileService = dependencies.getProfileService();
|
||||
|
@ -450,13 +451,7 @@ public final class ProfileHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private Optional<UnidentifiedAccess> getUnidentifiedAccess(RecipientId recipientId) {
|
||||
var unidentifiedAccess = context.getUnidentifiedAccessHelper().getAccessFor(recipientId, true);
|
||||
|
||||
if (unidentifiedAccess.isPresent()) {
|
||||
return unidentifiedAccess.get().getTargetUnidentifiedAccess();
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
private @Nullable SealedSenderAccess getUnidentifiedAccess(RecipientId recipientId) {
|
||||
return context.getUnidentifiedAccessHelper().getSealedSenderAccessFor(recipientId, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.asamk.signal.manager.storage.SignalAccount;
|
|||
import org.asamk.signal.manager.storage.groups.GroupInfo;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.storage.sendLog.MessageSendLogEntry;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.InvalidRegistrationIdException;
|
||||
import org.signal.libsignal.protocol.NoSessionException;
|
||||
|
@ -22,9 +23,10 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||
import org.whispersystems.signalservice.api.crypto.SealedSenderAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupSendEndorsements;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEditMessage;
|
||||
|
@ -199,7 +201,7 @@ public class SendHelper {
|
|||
return SendMessageResult.success(account.getSelfAddress(), List.of(), false, false, 0, Optional.empty());
|
||||
}
|
||||
try {
|
||||
return messageSender.sendSyncMessage(message, context.getUnidentifiedAccessHelper().getAccessForSync());
|
||||
return messageSender.sendSyncMessage(message);
|
||||
} catch (UnregisteredUserException e) {
|
||||
var address = context.getRecipientHelper().resolveSignalServiceAddress(account.getSelfRecipientId());
|
||||
return SendMessageResult.unregisteredFailure(address);
|
||||
|
@ -380,10 +382,11 @@ public class SendHelper {
|
|||
() -> false,
|
||||
urgent,
|
||||
editTargetTimestamp.get());
|
||||
final SenderKeySenderHandler senderKeySender = (distId, recipients, unidentifiedAccess, isRecipientUpdate) -> messageSender.sendGroupDataMessage(
|
||||
final SenderKeySenderHandler senderKeySender = (distId, recipients, unidentifiedAccess, groupSendEndorsements, isRecipientUpdate) -> messageSender.sendGroupDataMessage(
|
||||
distId,
|
||||
recipients,
|
||||
unidentifiedAccess,
|
||||
groupSendEndorsements,
|
||||
isRecipientUpdate,
|
||||
contentHint,
|
||||
message,
|
||||
|
@ -436,9 +439,11 @@ public class SendHelper {
|
|||
unidentifiedAccess,
|
||||
message,
|
||||
() -> false),
|
||||
(distId, recipients, unidentifiedAccess, isRecipientUpdate) -> messageSender.sendGroupTyping(distId,
|
||||
(distId, recipients, unidentifiedAccess, groupSendEndorsements, isRecipientUpdate) -> messageSender.sendGroupTyping(
|
||||
distId,
|
||||
recipients,
|
||||
unidentifiedAccess,
|
||||
groupSendEndorsements,
|
||||
message),
|
||||
recipientIds,
|
||||
distributionId);
|
||||
|
@ -526,8 +531,8 @@ public class SendHelper {
|
|||
final var senderKeyTargets = new HashSet<RecipientId>();
|
||||
final var recipientList = new ArrayList<>(recipientIds);
|
||||
for (final var recipientId : recipientList) {
|
||||
final var access = context.getUnidentifiedAccessHelper().getAccessFor(recipientId);
|
||||
if (access.isEmpty() || access.get().getTargetUnidentifiedAccess().isEmpty()) {
|
||||
final var access = context.getUnidentifiedAccessHelper().getSealedSenderAccessFor(recipientId);
|
||||
if (access != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -562,7 +567,8 @@ public class SendHelper {
|
|||
final var addresses = recipientIdList.stream()
|
||||
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
||||
.toList();
|
||||
final var unidentifiedAccesses = context.getUnidentifiedAccessHelper().getAccessFor(recipientIdList);
|
||||
final var unidentifiedAccesses = context.getUnidentifiedAccessHelper()
|
||||
.getSealedSenderAccessFor(recipientIdList);
|
||||
try {
|
||||
final var results = sender.send(addresses, unidentifiedAccesses, isRecipientUpdate);
|
||||
|
||||
|
@ -601,15 +607,14 @@ public class SendHelper {
|
|||
List<UnidentifiedAccess> unidentifiedAccesses = context.getUnidentifiedAccessHelper()
|
||||
.getAccessFor(recipientIdList)
|
||||
.stream()
|
||||
.map(Optional::get)
|
||||
.map(UnidentifiedAccessPair::getTargetUnidentifiedAccess)
|
||||
.map(Optional::get)
|
||||
.toList();
|
||||
|
||||
final GroupSendEndorsements groupSendEndorsements = null;//TODO
|
||||
try {
|
||||
List<SendMessageResult> results = sender.send(distributionId,
|
||||
addresses,
|
||||
unidentifiedAccesses,
|
||||
groupSendEndorsements,
|
||||
isRecipientUpdate);
|
||||
|
||||
final var successCount = results.stream().filter(SendMessageResult::isSuccess).count();
|
||||
|
@ -684,7 +689,7 @@ public class SendHelper {
|
|||
try {
|
||||
return s.send(messageSender,
|
||||
address,
|
||||
context.getUnidentifiedAccessHelper().getAccessFor(recipientId),
|
||||
context.getUnidentifiedAccessHelper().getSealedSenderAccessFor(recipientId),
|
||||
includePniSignature);
|
||||
} catch (UnregisteredUserException e) {
|
||||
final RecipientId newRecipientId;
|
||||
|
@ -696,7 +701,7 @@ public class SendHelper {
|
|||
address = context.getRecipientHelper().resolveSignalServiceAddress(newRecipientId);
|
||||
return s.send(messageSender,
|
||||
address,
|
||||
context.getUnidentifiedAccessHelper().getAccessFor(newRecipientId),
|
||||
context.getUnidentifiedAccessHelper().getSealedSenderAccessFor(newRecipientId),
|
||||
includePniSignature);
|
||||
}
|
||||
} catch (UnregisteredUserException e) {
|
||||
|
@ -772,7 +777,7 @@ public class SendHelper {
|
|||
SendMessageResult send(
|
||||
SignalServiceMessageSender messageSender,
|
||||
SignalServiceAddress address,
|
||||
Optional<UnidentifiedAccessPair> unidentifiedAccess,
|
||||
@Nullable SealedSenderAccess unidentifiedAccess,
|
||||
boolean includePniSignature
|
||||
) throws IOException, UnregisteredUserException, ProofRequiredException, RateLimitException, org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
}
|
||||
|
@ -783,6 +788,7 @@ public class SendHelper {
|
|||
DistributionId distributionId,
|
||||
List<SignalServiceAddress> recipients,
|
||||
List<UnidentifiedAccess> unidentifiedAccess,
|
||||
GroupSendEndorsements groupSendEndorsements,
|
||||
boolean isRecipientUpdate
|
||||
) throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException;
|
||||
}
|
||||
|
@ -791,7 +797,7 @@ public class SendHelper {
|
|||
|
||||
List<SendMessageResult> send(
|
||||
List<SignalServiceAddress> recipients,
|
||||
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
|
||||
List<SealedSenderAccess> unidentifiedAccess,
|
||||
boolean isRecipientUpdate
|
||||
) throws IOException, UntrustedIdentityException;
|
||||
}
|
||||
|
|
|
@ -5,17 +5,17 @@ import org.asamk.signal.manager.api.Profile;
|
|||
import org.asamk.signal.manager.internal.SignalDependencies;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
|
||||
import org.signal.libsignal.metadata.certificate.SenderCertificate;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.crypto.SealedSenderAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class UnidentifiedAccessHelper {
|
||||
|
@ -42,57 +42,49 @@ public class UnidentifiedAccessHelper {
|
|||
senderCertificate = null;
|
||||
}
|
||||
|
||||
public List<Optional<UnidentifiedAccessPair>> getAccessFor(List<RecipientId> recipients) {
|
||||
public List<SealedSenderAccess> getSealedSenderAccessFor(List<RecipientId> recipients) {
|
||||
return recipients.stream().map(this::getAccessFor).map(SealedSenderAccess::forIndividual).toList();
|
||||
}
|
||||
|
||||
public @Nullable SealedSenderAccess getSealedSenderAccessFor(RecipientId recipient) {
|
||||
return getSealedSenderAccessFor(recipient, false);
|
||||
}
|
||||
|
||||
public @Nullable SealedSenderAccess getSealedSenderAccessFor(RecipientId recipient, boolean noRefresh) {
|
||||
return SealedSenderAccess.forIndividual(getAccessFor(recipient, noRefresh));
|
||||
}
|
||||
|
||||
public List<UnidentifiedAccess> getAccessFor(List<RecipientId> recipients) {
|
||||
return recipients.stream().map(this::getAccessFor).toList();
|
||||
}
|
||||
|
||||
public Optional<UnidentifiedAccessPair> getAccessFor(RecipientId recipient) {
|
||||
private @Nullable UnidentifiedAccess getAccessFor(RecipientId recipient) {
|
||||
return getAccessFor(recipient, false);
|
||||
}
|
||||
|
||||
public Optional<UnidentifiedAccessPair> getAccessFor(RecipientId recipientId, boolean noRefresh) {
|
||||
private @Nullable UnidentifiedAccess getAccessFor(RecipientId recipientId, boolean noRefresh) {
|
||||
var recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipientId, noRefresh);
|
||||
if (recipientUnidentifiedAccessKey == null) {
|
||||
logger.trace("Unidentified access not available for {}", recipientId);
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
|
||||
var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(noRefresh);
|
||||
if (selfUnidentifiedAccessKey == null) {
|
||||
logger.trace("Unidentified access not available for self");
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
|
||||
var senderCertificate = getSenderCertificateFor(recipientId);
|
||||
if (senderCertificate == null) {
|
||||
logger.trace("Unidentified access not available due to missing sender certificate");
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(recipientUnidentifiedAccessKey,
|
||||
senderCertificate,
|
||||
false), new UnidentifiedAccess(selfUnidentifiedAccessKey, senderCertificate, false)));
|
||||
return new UnidentifiedAccess(recipientUnidentifiedAccessKey, senderCertificate, false);
|
||||
} catch (InvalidCertificateException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<UnidentifiedAccessPair> getAccessForSync() {
|
||||
var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(false);
|
||||
var selfUnidentifiedAccessCertificate = getSenderCertificate();
|
||||
|
||||
if (selfUnidentifiedAccessKey == null || selfUnidentifiedAccessCertificate == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(selfUnidentifiedAccessKey,
|
||||
selfUnidentifiedAccessCertificate,
|
||||
false),
|
||||
new UnidentifiedAccess(selfUnidentifiedAccessKey, selfUnidentifiedAccessCertificate, false)));
|
||||
} catch (InvalidCertificateException e) {
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +113,7 @@ public class UnidentifiedAccessHelper {
|
|||
privacySenderCertificate = new SenderCertificate(certificate);
|
||||
return certificate;
|
||||
} catch (IOException | InvalidCertificateException e) {
|
||||
logger.warn("Failed to get sender certificate, ignoring: {}", e.getMessage());
|
||||
logger.warn("Failed to get sender certificate (pnp), ignoring: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue