mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Refactor RecipientAddress
This commit is contained in:
parent
34cc64f8ce
commit
7eb7ee44f2
40 changed files with 392 additions and 127 deletions
|
@ -14,6 +14,7 @@ import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.PendingAdminApprovalException;
|
import org.asamk.signal.manager.api.PendingAdminApprovalException;
|
||||||
import org.asamk.signal.manager.api.ReceiveConfig;
|
import org.asamk.signal.manager.api.ReceiveConfig;
|
||||||
|
import org.asamk.signal.manager.api.Recipient;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
||||||
import org.asamk.signal.manager.api.SendMessageResults;
|
import org.asamk.signal.manager.api.SendMessageResults;
|
||||||
|
@ -32,7 +33,6 @@ import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
|
||||||
import org.asamk.signal.manager.groups.LastGroupAdminException;
|
import org.asamk.signal.manager.groups.LastGroupAdminException;
|
||||||
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
||||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||||
import org.asamk.signal.manager.storage.recipients.Recipient;
|
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.PendingAdminApprovalException;
|
import org.asamk.signal.manager.api.PendingAdminApprovalException;
|
||||||
import org.asamk.signal.manager.api.ReceiveConfig;
|
import org.asamk.signal.manager.api.ReceiveConfig;
|
||||||
|
import org.asamk.signal.manager.api.Recipient;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
||||||
import org.asamk.signal.manager.api.SendMessageResult;
|
import org.asamk.signal.manager.api.SendMessageResult;
|
||||||
|
@ -54,7 +55,6 @@ import org.asamk.signal.manager.storage.SignalAccount;
|
||||||
import org.asamk.signal.manager.storage.groups.GroupInfo;
|
import org.asamk.signal.manager.storage.groups.GroupInfo;
|
||||||
import org.asamk.signal.manager.storage.identities.IdentityInfo;
|
import org.asamk.signal.manager.storage.identities.IdentityInfo;
|
||||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||||
import org.asamk.signal.manager.storage.recipients.Recipient;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
import org.asamk.signal.manager.storage.stickerPacks.JsonStickerPack;
|
import org.asamk.signal.manager.storage.stickerPacks.JsonStickerPack;
|
||||||
import org.asamk.signal.manager.storage.stickerPacks.StickerPackStore;
|
import org.asamk.signal.manager.storage.stickerPacks.StickerPackStore;
|
||||||
|
@ -707,13 +707,13 @@ class ManagerImpl implements Manager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteRecipient(final RecipientIdentifier.Single recipient) {
|
public void deleteRecipient(final RecipientIdentifier.Single recipient) {
|
||||||
account.removeRecipient(account.getRecipientResolver().resolveRecipient(recipient.toPartialRecipientAddress()));
|
account.removeRecipient(account.getRecipientResolver().resolveRecipient(recipient.getIdentifier()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteContact(final RecipientIdentifier.Single recipient) {
|
public void deleteContact(final RecipientIdentifier.Single recipient) {
|
||||||
account.getContactStore()
|
account.getContactStore()
|
||||||
.deleteContact(account.getRecipientResolver().resolveRecipient(recipient.toPartialRecipientAddress()));
|
.deleteContact(account.getRecipientResolver().resolveRecipient(recipient.getIdentifier()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1005,7 +1005,16 @@ class ManagerImpl implements Manager {
|
||||||
}
|
}
|
||||||
// refresh profiles of explicitly given recipients
|
// refresh profiles of explicitly given recipients
|
||||||
context.getProfileHelper().refreshRecipientProfiles(recipientIds);
|
context.getProfileHelper().refreshRecipientProfiles(recipientIds);
|
||||||
return account.getRecipientStore().getRecipients(onlyContacts, blocked, recipientIds, name);
|
return account.getRecipientStore()
|
||||||
|
.getRecipients(onlyContacts, blocked, recipientIds, name)
|
||||||
|
.stream()
|
||||||
|
.map(s -> new Recipient(s.getRecipientId(),
|
||||||
|
s.getAddress().toApiRecipientAddress(),
|
||||||
|
s.getContact(),
|
||||||
|
s.getProfileKey(),
|
||||||
|
s.getExpiringProfileKeyCredential(),
|
||||||
|
s.getProfile()))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1049,7 +1058,7 @@ class ManagerImpl implements Manager {
|
||||||
.resolveRecipientAddress(account.getRecipientResolver().resolveRecipient(identityInfo.getServiceId()));
|
.resolveRecipientAddress(account.getRecipientResolver().resolveRecipient(identityInfo.getServiceId()));
|
||||||
final var scannableFingerprint = context.getIdentityHelper()
|
final var scannableFingerprint = context.getIdentityHelper()
|
||||||
.computeSafetyNumberForScanning(identityInfo.getServiceId(), identityInfo.getIdentityKey());
|
.computeSafetyNumberForScanning(identityInfo.getServiceId(), identityInfo.getIdentityKey());
|
||||||
return new Identity(address,
|
return new Identity(address.toApiRecipientAddress(),
|
||||||
identityInfo.getIdentityKey(),
|
identityInfo.getIdentityKey(),
|
||||||
context.getIdentityHelper()
|
context.getIdentityHelper()
|
||||||
.computeSafetyNumber(identityInfo.getServiceId(), identityInfo.getIdentityKey()),
|
.computeSafetyNumber(identityInfo.getServiceId(), identityInfo.getIdentityKey()),
|
||||||
|
|
|
@ -5,7 +5,6 @@ import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
|
||||||
import org.asamk.signal.manager.groups.GroupPermission;
|
import org.asamk.signal.manager.groups.GroupPermission;
|
||||||
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
||||||
import org.asamk.signal.manager.storage.groups.GroupInfo;
|
import org.asamk.signal.manager.storage.groups.GroupInfo;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -40,22 +39,27 @@ public record Group(
|
||||||
groupInfo.getMembers()
|
groupInfo.getMembers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(recipientStore::resolveRecipientAddress)
|
.map(recipientStore::resolveRecipientAddress)
|
||||||
|
.map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress)
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
groupInfo.getPendingMembers()
|
groupInfo.getPendingMembers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(recipientStore::resolveRecipientAddress)
|
.map(recipientStore::resolveRecipientAddress)
|
||||||
|
.map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress)
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
groupInfo.getRequestingMembers()
|
groupInfo.getRequestingMembers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(recipientStore::resolveRecipientAddress)
|
.map(recipientStore::resolveRecipientAddress)
|
||||||
|
.map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress)
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
groupInfo.getAdminMembers()
|
groupInfo.getAdminMembers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(recipientStore::resolveRecipientAddress)
|
.map(recipientStore::resolveRecipientAddress)
|
||||||
|
.map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress)
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
groupInfo.getBannedMembers()
|
groupInfo.getBannedMembers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(recipientStore::resolveRecipientAddress)
|
.map(recipientStore::resolveRecipientAddress)
|
||||||
|
.map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress)
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
groupInfo.isBlocked(),
|
groupInfo.isBlocked(),
|
||||||
groupInfo.getMessageExpirationTimer(),
|
groupInfo.getMessageExpirationTimer(),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.signal.libsignal.protocol.IdentityKey;
|
import org.signal.libsignal.protocol.IdentityKey;
|
||||||
|
|
||||||
public record Identity(
|
public record Identity(
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.asamk.signal.manager.api;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.groups.GroupUtils;
|
import org.asamk.signal.manager.groups.GroupUtils;
|
||||||
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||||
import org.signal.libsignal.metadata.ProtocolException;
|
import org.signal.libsignal.metadata.ProtocolException;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
|
@ -184,7 +183,7 @@ public record MessageEnvelope(
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new StoryContext(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
return new StoryContext(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
||||||
storyContext.getAuthorServiceId())), storyContext.getSentTimestamp());
|
storyContext.getAuthorServiceId())).toApiRecipientAddress(), storyContext.getSentTimestamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +204,8 @@ public record MessageEnvelope(
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new Reaction(reaction.getTargetSentTimestamp(),
|
return new Reaction(reaction.getTargetSentTimestamp(),
|
||||||
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(reaction.getTargetAuthor())),
|
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(reaction.getTargetAuthor()))
|
||||||
|
.toApiRecipientAddress(),
|
||||||
reaction.getEmoji(),
|
reaction.getEmoji(),
|
||||||
reaction.isRemove());
|
reaction.isRemove());
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,8 @@ public record MessageEnvelope(
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
return new Quote(quote.getId(),
|
return new Quote(quote.getId(),
|
||||||
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())),
|
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor()))
|
||||||
|
.toApiRecipientAddress(),
|
||||||
Optional.ofNullable(quote.getText()),
|
Optional.ofNullable(quote.getText()),
|
||||||
quote.getMentions() == null
|
quote.getMentions() == null
|
||||||
? List.of()
|
? List.of()
|
||||||
|
@ -255,9 +256,8 @@ public record MessageEnvelope(
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new Mention(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(mention.getServiceId())),
|
return new Mention(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(mention.getServiceId()))
|
||||||
mention.getStart(),
|
.toApiRecipientAddress(), mention.getStart(), mention.getLength());
|
||||||
mention.getLength());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,10 +552,12 @@ public record MessageEnvelope(
|
||||||
return new Sent(sentMessage.getTimestamp(),
|
return new Sent(sentMessage.getTimestamp(),
|
||||||
sentMessage.getExpirationStartTimestamp(),
|
sentMessage.getExpirationStartTimestamp(),
|
||||||
sentMessage.getDestination()
|
sentMessage.getDestination()
|
||||||
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))),
|
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))
|
||||||
|
.toApiRecipientAddress()),
|
||||||
sentMessage.getRecipients()
|
sentMessage.getRecipients()
|
||||||
.stream()
|
.stream()
|
||||||
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)))
|
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))
|
||||||
|
.toApiRecipientAddress())
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
sentMessage.getDataMessage()
|
sentMessage.getDataMessage()
|
||||||
.map(message -> Data.from(message, recipientResolver, addressResolver, fileProvider)),
|
.map(message -> Data.from(message, recipientResolver, addressResolver, fileProvider)),
|
||||||
|
@ -572,7 +574,8 @@ public record MessageEnvelope(
|
||||||
) {
|
) {
|
||||||
return new Blocked(blockedListMessage.getAddresses()
|
return new Blocked(blockedListMessage.getAddresses()
|
||||||
.stream()
|
.stream()
|
||||||
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)))
|
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))
|
||||||
|
.toApiRecipientAddress())
|
||||||
.toList(), blockedListMessage.getGroupIds().stream().map(GroupId::unknownVersion).toList());
|
.toList(), blockedListMessage.getGroupIds().stream().map(GroupId::unknownVersion).toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,8 +587,8 @@ public record MessageEnvelope(
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new Read(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender())),
|
return new Read(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender()))
|
||||||
readMessage.getTimestamp());
|
.toApiRecipientAddress(), readMessage.getTimestamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,8 +599,8 @@ public record MessageEnvelope(
|
||||||
RecipientResolver recipientResolver,
|
RecipientResolver recipientResolver,
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new Viewed(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender())),
|
return new Viewed(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender()))
|
||||||
readMessage.getTimestamp());
|
.toApiRecipientAddress(), readMessage.getTimestamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,7 +612,7 @@ public record MessageEnvelope(
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new ViewOnceOpen(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
return new ViewOnceOpen(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
||||||
readMessage.getSender())), readMessage.getTimestamp());
|
readMessage.getSender())).toApiRecipientAddress(), readMessage.getTimestamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +640,8 @@ public record MessageEnvelope(
|
||||||
return new MessageRequestResponse(Type.from(messageRequestResponse.getType()),
|
return new MessageRequestResponse(Type.from(messageRequestResponse.getType()),
|
||||||
messageRequestResponse.getGroupId().map(GroupId::unknownVersion),
|
messageRequestResponse.getGroupId().map(GroupId::unknownVersion),
|
||||||
messageRequestResponse.getPerson()
|
messageRequestResponse.getPerson()
|
||||||
.map(p -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(p))));
|
.map(p -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(p))
|
||||||
|
.toApiRecipientAddress()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -898,7 +902,7 @@ public record MessageEnvelope(
|
||||||
|
|
||||||
return new MessageEnvelope(source == null
|
return new MessageEnvelope(source == null
|
||||||
? Optional.empty()
|
? Optional.empty()
|
||||||
: Optional.of(addressResolver.resolveRecipientAddress(source)),
|
: Optional.of(addressResolver.resolveRecipientAddress(source).toApiRecipientAddress()),
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
envelope.getTimestamp(),
|
envelope.getTimestamp(),
|
||||||
envelope.getServerReceivedTimestamp(),
|
envelope.getServerReceivedTimestamp(),
|
||||||
|
|
153
lib/src/main/java/org/asamk/signal/manager/api/Recipient.java
Normal file
153
lib/src/main/java/org/asamk/signal/manager/api/Recipient.java
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.storage.recipients.Contact;
|
||||||
|
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||||
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
|
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
|
||||||
|
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Recipient {
|
||||||
|
|
||||||
|
private final RecipientId recipientId;
|
||||||
|
|
||||||
|
private final RecipientAddress address;
|
||||||
|
|
||||||
|
private final Contact contact;
|
||||||
|
|
||||||
|
private final ProfileKey profileKey;
|
||||||
|
|
||||||
|
private final ExpiringProfileKeyCredential expiringProfileKeyCredential;
|
||||||
|
|
||||||
|
private final Profile profile;
|
||||||
|
|
||||||
|
public Recipient(
|
||||||
|
final RecipientId recipientId,
|
||||||
|
final RecipientAddress address,
|
||||||
|
final Contact contact,
|
||||||
|
final ProfileKey profileKey,
|
||||||
|
final ExpiringProfileKeyCredential expiringProfileKeyCredential,
|
||||||
|
final Profile profile
|
||||||
|
) {
|
||||||
|
this.recipientId = recipientId;
|
||||||
|
this.address = address;
|
||||||
|
this.contact = contact;
|
||||||
|
this.profileKey = profileKey;
|
||||||
|
this.expiringProfileKeyCredential = expiringProfileKeyCredential;
|
||||||
|
this.profile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Recipient(final Builder builder) {
|
||||||
|
recipientId = builder.recipientId;
|
||||||
|
address = builder.address;
|
||||||
|
contact = builder.contact;
|
||||||
|
profileKey = builder.profileKey;
|
||||||
|
expiringProfileKeyCredential = builder.expiringProfileKeyCredential1;
|
||||||
|
profile = builder.profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder newBuilder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder newBuilder(final Recipient copy) {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
builder.recipientId = copy.getRecipientId();
|
||||||
|
builder.address = copy.getAddress();
|
||||||
|
builder.contact = copy.getContact();
|
||||||
|
builder.profileKey = copy.getProfileKey();
|
||||||
|
builder.expiringProfileKeyCredential1 = copy.getExpiringProfileKeyCredential();
|
||||||
|
builder.profile = copy.getProfile();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientId getRecipientId() {
|
||||||
|
return recipientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientAddress getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Contact getContact() {
|
||||||
|
return contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileKey getProfileKey() {
|
||||||
|
return profileKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpiringProfileKeyCredential getExpiringProfileKeyCredential() {
|
||||||
|
return expiringProfileKeyCredential;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Profile getProfile() {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final Recipient recipient = (Recipient) o;
|
||||||
|
return Objects.equals(recipientId, recipient.recipientId)
|
||||||
|
&& Objects.equals(address, recipient.address)
|
||||||
|
&& Objects.equals(contact, recipient.contact)
|
||||||
|
&& Objects.equals(profileKey, recipient.profileKey)
|
||||||
|
&& Objects.equals(expiringProfileKeyCredential, recipient.expiringProfileKeyCredential)
|
||||||
|
&& Objects.equals(profile, recipient.profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(recipientId, address, contact, profileKey, expiringProfileKeyCredential, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
|
private RecipientId recipientId;
|
||||||
|
private RecipientAddress address;
|
||||||
|
private Contact contact;
|
||||||
|
private ProfileKey profileKey;
|
||||||
|
private ExpiringProfileKeyCredential expiringProfileKeyCredential1;
|
||||||
|
private Profile profile;
|
||||||
|
|
||||||
|
private Builder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withRecipientId(final RecipientId val) {
|
||||||
|
recipientId = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withAddress(final RecipientAddress val) {
|
||||||
|
address = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withContact(final Contact val) {
|
||||||
|
contact = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withProfileKey(final ProfileKey val) {
|
||||||
|
profileKey = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withExpiringProfileKeyCredential(final ExpiringProfileKeyCredential val) {
|
||||||
|
expiringProfileKeyCredential1 = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withProfile(final Profile val) {
|
||||||
|
profile = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Recipient build() {
|
||||||
|
return new Recipient(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
||||||
|
|
||||||
|
public static final UUID UNKNOWN_UUID = ServiceId.UNKNOWN.uuid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a RecipientAddress.
|
||||||
|
*
|
||||||
|
* @param uuid The UUID of the user, if available.
|
||||||
|
* @param number The phone number of the user, if available.
|
||||||
|
*/
|
||||||
|
public RecipientAddress {
|
||||||
|
uuid = uuid.isPresent() && uuid.get().equals(UNKNOWN_UUID) ? Optional.empty() : uuid;
|
||||||
|
if (uuid.isEmpty() && number.isEmpty()) {
|
||||||
|
throw new AssertionError("Must have either a UUID or E164 number!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientAddress(UUID uuid, String e164) {
|
||||||
|
this(Optional.ofNullable(uuid), Optional.ofNullable(e164));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientAddress(SignalServiceAddress address) {
|
||||||
|
this(Optional.of(address.getServiceId().uuid()), address.getNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientAddress(UUID uuid) {
|
||||||
|
this(Optional.of(uuid), Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceId getServiceId() {
|
||||||
|
return ServiceId.from(uuid.orElse(UNKNOWN_UUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier() {
|
||||||
|
if (uuid.isPresent()) {
|
||||||
|
return uuid.get().toString();
|
||||||
|
} else if (number.isPresent()) {
|
||||||
|
return number.get();
|
||||||
|
} else {
|
||||||
|
throw new AssertionError("Given the checks in the constructor, this should not be possible.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLegacyIdentifier() {
|
||||||
|
if (number.isPresent()) {
|
||||||
|
return number.get();
|
||||||
|
} else if (uuid.isPresent()) {
|
||||||
|
return uuid.get().toString();
|
||||||
|
} else {
|
||||||
|
throw new AssertionError("Given the checks in the constructor, this should not be possible.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(RecipientAddress other) {
|
||||||
|
return (uuid.isPresent() && other.uuid.isPresent() && uuid.get().equals(other.uuid.get())) || (
|
||||||
|
number.isPresent() && other.number.isPresent() && number.get().equals(other.number.get())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignalServiceAddress toSignalServiceAddress() {
|
||||||
|
return new SignalServiceAddress(getServiceId(), number);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||||
import org.signal.libsignal.protocol.IdentityKey;
|
import org.signal.libsignal.protocol.IdentityKey;
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ public record SendMessageResult(
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new SendMessageResult(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
return new SendMessageResult(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
||||||
sendMessageResult.getAddress())),
|
sendMessageResult.getAddress())).toApiRecipientAddress(),
|
||||||
sendMessageResult.isSuccess(),
|
sendMessageResult.isSuccess(),
|
||||||
sendMessageResult.isNetworkFailure(),
|
sendMessageResult.isNetworkFailure(),
|
||||||
sendMessageResult.isUnregisteredFailure(),
|
sendMessageResult.isUnregisteredFailure(),
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
|
|
||||||
public class UnregisteredRecipientException extends Exception {
|
public class UnregisteredRecipientException extends Exception {
|
||||||
|
|
||||||
private final RecipientAddress sender;
|
private final RecipientAddress sender;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
|
|
||||||
public class UntrustedIdentityException extends Exception {
|
public class UntrustedIdentityException extends Exception {
|
||||||
|
|
||||||
private final RecipientAddress sender;
|
private final RecipientAddress sender;
|
||||||
|
|
|
@ -85,7 +85,7 @@ public class IdentityHelper {
|
||||||
account.getAciIdentityKeyPair().getPublicKey(),
|
account.getAciIdentityKeyPair().getPublicKey(),
|
||||||
address.getServiceId().equals(serviceId)
|
address.getServiceId().equals(serviceId)
|
||||||
? address
|
? address
|
||||||
: new RecipientAddress(serviceId.uuid(), address.number().orElse(null)),
|
: new RecipientAddress(serviceId, address.number().orElse(null)),
|
||||||
theirIdentityKey);
|
theirIdentityKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,8 @@ public final class IncomingMessageHandler {
|
||||||
} catch (ProtocolUntrustedIdentityException e) {
|
} catch (ProtocolUntrustedIdentityException e) {
|
||||||
final var recipientId = account.getRecipientResolver().resolveRecipient(e.getSender());
|
final var recipientId = account.getRecipientResolver().resolveRecipient(e.getSender());
|
||||||
final var exception = new UntrustedIdentityException(account.getRecipientAddressResolver()
|
final var exception = new UntrustedIdentityException(account.getRecipientAddressResolver()
|
||||||
.resolveRecipientAddress(recipientId), e.getSenderDevice());
|
.resolveRecipientAddress(recipientId)
|
||||||
|
.toApiRecipientAddress(), e.getSenderDevice());
|
||||||
return new Pair<>(List.of(), exception);
|
return new Pair<>(List.of(), exception);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return new Pair<>(List.of(), e);
|
return new Pair<>(List.of(), e);
|
||||||
|
@ -129,7 +130,8 @@ public final class IncomingMessageHandler {
|
||||||
final var recipientId = account.getRecipientResolver().resolveRecipient(e.getSender());
|
final var recipientId = account.getRecipientResolver().resolveRecipient(e.getSender());
|
||||||
actions.add(new RetrieveProfileAction(recipientId));
|
actions.add(new RetrieveProfileAction(recipientId));
|
||||||
exception = new UntrustedIdentityException(account.getRecipientAddressResolver()
|
exception = new UntrustedIdentityException(account.getRecipientAddressResolver()
|
||||||
.resolveRecipientAddress(recipientId), e.getSenderDevice());
|
.resolveRecipientAddress(recipientId)
|
||||||
|
.toApiRecipientAddress(), e.getSenderDevice());
|
||||||
} catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException |
|
} catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException |
|
||||||
ProtocolInvalidMessageException e) {
|
ProtocolInvalidMessageException e) {
|
||||||
logger.debug("Failed to decrypt incoming message", e);
|
logger.debug("Failed to decrypt incoming message", e);
|
||||||
|
|
|
@ -212,7 +212,7 @@ public class ReceiveHelper {
|
||||||
if (exception instanceof UntrustedIdentityException) {
|
if (exception instanceof UntrustedIdentityException) {
|
||||||
logger.debug("Keeping message with untrusted identity in message cache");
|
logger.debug("Keeping message with untrusted identity in message cache");
|
||||||
final var address = ((UntrustedIdentityException) exception).getSender();
|
final var address = ((UntrustedIdentityException) exception).getSender();
|
||||||
final var recipientId = account.getRecipientResolver().resolveRecipient(address);
|
final var recipientId = account.getRecipientResolver().resolveRecipient(address.getServiceId());
|
||||||
if (!envelope.hasSourceUuid()) {
|
if (!envelope.hasSourceUuid()) {
|
||||||
try {
|
try {
|
||||||
cachedMessage[0] = account.getMessageCache().replaceSender(cachedMessage[0], recipientId);
|
cachedMessage[0] = account.getMessageCache().replaceSender(cachedMessage[0], recipientId);
|
||||||
|
@ -260,7 +260,7 @@ public class ReceiveHelper {
|
||||||
}
|
}
|
||||||
if (!envelope.hasSourceUuid()) {
|
if (!envelope.hasSourceUuid()) {
|
||||||
final var identifier = ((UntrustedIdentityException) exception).getSender();
|
final var identifier = ((UntrustedIdentityException) exception).getSender();
|
||||||
final var recipientId = account.getRecipientResolver().resolveRecipient(identifier);
|
final var recipientId = account.getRecipientResolver().resolveRecipient(identifier.getServiceId());
|
||||||
try {
|
try {
|
||||||
account.getMessageCache().replaceSender(cachedMessage, recipientId);
|
account.getMessageCache().replaceSender(cachedMessage, recipientId);
|
||||||
} catch (IOException ioException) {
|
} catch (IOException ioException) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.asamk.signal.manager.api.UnregisteredRecipientException;
|
||||||
import org.asamk.signal.manager.config.ServiceConfig;
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
import org.asamk.signal.manager.storage.SignalAccount;
|
import org.asamk.signal.manager.storage.SignalAccount;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -44,7 +43,7 @@ public class RecipientHelper {
|
||||||
|
|
||||||
public SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) {
|
public SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) {
|
||||||
final var address = account.getRecipientAddressResolver().resolveRecipientAddress(recipientId);
|
final var address = account.getRecipientAddressResolver().resolveRecipientAddress(recipientId);
|
||||||
if (address.number().isEmpty() || address.uuid().isPresent()) {
|
if (address.number().isEmpty() || address.serviceId().isPresent()) {
|
||||||
return address.toSignalServiceAddress();
|
return address.toSignalServiceAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,11 +126,11 @@ public class RecipientHelper {
|
||||||
try {
|
try {
|
||||||
aciMap = getRegisteredUsers(Set.of(number));
|
aciMap = getRegisteredUsers(Set.of(number));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new UnregisteredRecipientException(new RecipientAddress(null, number));
|
throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null, number));
|
||||||
}
|
}
|
||||||
final var uuid = aciMap.get(number);
|
final var uuid = aciMap.get(number);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
throw new UnregisteredRecipientException(new RecipientAddress(null, number));
|
throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null, number));
|
||||||
}
|
}
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,8 +101,7 @@ public class StorageHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
final var contactRecord = record.getContact().get();
|
final var contactRecord = record.getContact().get();
|
||||||
final var address = new RecipientAddress(contactRecord.getServiceId().uuid(),
|
final var address = new RecipientAddress(contactRecord.getServiceId(), contactRecord.getNumber().orElse(null));
|
||||||
contactRecord.getNumber().orElse(null));
|
|
||||||
final var recipientId = account.getRecipientResolver().resolveRecipient(address);
|
final var recipientId = account.getRecipientResolver().resolveRecipient(address);
|
||||||
|
|
||||||
final var contact = account.getContactStore().getContact(recipientId);
|
final var contact = account.getContactStore().getContact(recipientId);
|
||||||
|
|
|
@ -417,8 +417,8 @@ public class SignalAccount implements Closeable {
|
||||||
getRecipientStore().deleteRecipientData(recipientId);
|
getRecipientStore().deleteRecipientData(recipientId);
|
||||||
getMessageCache().deleteMessages(recipientId);
|
getMessageCache().deleteMessages(recipientId);
|
||||||
final var recipientAddress = getRecipientStore().resolveRecipientAddress(recipientId);
|
final var recipientAddress = getRecipientStore().resolveRecipientAddress(recipientId);
|
||||||
if (recipientAddress.uuid().isPresent()) {
|
if (recipientAddress.serviceId().isPresent()) {
|
||||||
final var serviceId = ServiceId.from(recipientAddress.uuid().get());
|
final var serviceId = recipientAddress.serviceId().get();
|
||||||
getAciSessionStore().deleteAllSessions(serviceId);
|
getAciSessionStore().deleteAllSessions(serviceId);
|
||||||
getPniSessionStore().deleteAllSessions(serviceId);
|
getPniSessionStore().deleteAllSessions(serviceId);
|
||||||
getIdentityKeyStore().deleteIdentity(serviceId);
|
getIdentityKeyStore().deleteIdentity(serviceId);
|
||||||
|
@ -791,7 +791,7 @@ public class SignalAccount implements Closeable {
|
||||||
if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) {
|
if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) {
|
||||||
logger.debug("Migrating legacy identity session store.");
|
logger.debug("Migrating legacy identity session store.");
|
||||||
for (var identity : legacySignalProtocolStore.getLegacyIdentityKeyStore().getIdentities()) {
|
for (var identity : legacySignalProtocolStore.getLegacyIdentityKeyStore().getIdentities()) {
|
||||||
if (identity.getAddress().uuid().isEmpty()) {
|
if (identity.getAddress().serviceId().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final var serviceId = identity.getAddress().getServiceId();
|
final var serviceId = identity.getAddress().getServiceId();
|
||||||
|
@ -1324,7 +1324,7 @@ public class SignalAccount implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress getSelfRecipientAddress() {
|
public RecipientAddress getSelfRecipientAddress() {
|
||||||
return new RecipientAddress(aci == null ? null : aci.uuid(), number);
|
return new RecipientAddress(aci, pni, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientId getSelfRecipientId() {
|
public RecipientId getSelfRecipientId() {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ public class Utils {
|
||||||
|
|
||||||
public static RecipientAddress getRecipientAddressFromIdentifier(final String identifier) {
|
public static RecipientAddress getRecipientAddressFromIdentifier(final String identifier) {
|
||||||
if (UuidUtil.isUuid(identifier)) {
|
if (UuidUtil.isUuid(identifier)) {
|
||||||
return new RecipientAddress(UuidUtil.parseOrThrow(identifier));
|
return new RecipientAddress(ServiceId.parseOrThrow(identifier));
|
||||||
} else {
|
} else {
|
||||||
return new RecipientAddress(Optional.empty(), Optional.of(identifier));
|
return new RecipientAddress(Optional.empty(), Optional.of(identifier));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -43,6 +44,6 @@ public class LegacyContactInfo {
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public RecipientAddress getAddress() {
|
public RecipientAddress getAddress() {
|
||||||
return new RecipientAddress(uuid, number);
|
return new RecipientAddress(uuid == null ? null : ServiceId.from(uuid), number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.internal.util.Hex;
|
import org.whispersystems.signalservice.internal.util.Hex;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -45,7 +45,7 @@ public class LegacyGroupStore {
|
||||||
if (g instanceof Storage.GroupV1 g1) {
|
if (g instanceof Storage.GroupV1 g1) {
|
||||||
final var members = g1.members.stream().map(m -> {
|
final var members = g1.members.stream().map(m -> {
|
||||||
if (m.recipientId == null) {
|
if (m.recipientId == null) {
|
||||||
return recipientResolver.resolveRecipient(new RecipientAddress(UuidUtil.parseOrNull(m.uuid),
|
return recipientResolver.resolveRecipient(new RecipientAddress(ServiceId.parseOrNull(m.uuid),
|
||||||
m.number));
|
m.number));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -43,8 +43,8 @@ public class LegacyProfileStore {
|
||||||
if (node.isArray()) {
|
if (node.isArray()) {
|
||||||
for (var entry : node) {
|
for (var entry : node) {
|
||||||
var name = entry.hasNonNull("name") ? entry.get("name").asText() : null;
|
var name = entry.hasNonNull("name") ? entry.get("name").asText() : null;
|
||||||
var uuid = entry.hasNonNull("uuid") ? UuidUtil.parseOrNull(entry.get("uuid").asText()) : null;
|
var serviceId = entry.hasNonNull("uuid") ? ServiceId.parseOrNull(entry.get("uuid").asText()) : null;
|
||||||
final var address = new RecipientAddress(uuid, name);
|
final var address = new RecipientAddress(serviceId, name);
|
||||||
ProfileKey profileKey = null;
|
ProfileKey profileKey = null;
|
||||||
try {
|
try {
|
||||||
profileKey = new ProfileKey(Base64.getDecoder().decode(entry.get("profileKey").asText()));
|
profileKey = new ProfileKey(Base64.getDecoder().decode(entry.get("profileKey").asText()));
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -100,7 +101,7 @@ public class LegacyJsonIdentityKeyStore {
|
||||||
: null;
|
: null;
|
||||||
final var address = uuid == null
|
final var address = uuid == null
|
||||||
? Utils.getRecipientAddressFromIdentifier(trustedKeyName)
|
? Utils.getRecipientAddressFromIdentifier(trustedKeyName)
|
||||||
: new RecipientAddress(uuid, trustedKeyName);
|
: new RecipientAddress(ServiceId.from(uuid), trustedKeyName);
|
||||||
try {
|
try {
|
||||||
var id = new IdentityKey(Base64.getDecoder().decode(trustedKey.get("identityKey").asText()), 0);
|
var id = new IdentityKey(Base64.getDecoder().decode(trustedKey.get("identityKey").asText()), 0);
|
||||||
var trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get(
|
var trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get(
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.Utils;
|
import org.asamk.signal.manager.storage.Utils;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -47,7 +48,7 @@ public class LegacyJsonSessionStore {
|
||||||
var uuid = session.hasNonNull("uuid") ? UuidUtil.parseOrNull(session.get("uuid").asText()) : null;
|
var uuid = session.hasNonNull("uuid") ? UuidUtil.parseOrNull(session.get("uuid").asText()) : null;
|
||||||
final var address = uuid == null
|
final var address = uuid == null
|
||||||
? Utils.getRecipientAddressFromIdentifier(sessionName)
|
? Utils.getRecipientAddressFromIdentifier(sessionName)
|
||||||
: new RecipientAddress(uuid, sessionName);
|
: new RecipientAddress(ServiceId.from(uuid), sessionName);
|
||||||
final var deviceId = session.get("deviceId").asInt();
|
final var deviceId = session.get("deviceId").asInt();
|
||||||
final var record = Base64.getDecoder().decode(session.get("record").asText());
|
final var record = Base64.getDecoder().decode(session.get("record").asText());
|
||||||
var sessionInfo = new LegacySessionInfo(address, deviceId, record);
|
var sessionInfo = new LegacySessionInfo(address, deviceId, record);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -36,8 +36,8 @@ public class LegacyRecipientStore {
|
||||||
if (node.isArray()) {
|
if (node.isArray()) {
|
||||||
for (var recipient : node) {
|
for (var recipient : node) {
|
||||||
var recipientName = recipient.get("name").asText();
|
var recipientName = recipient.get("name").asText();
|
||||||
var uuid = UuidUtil.parseOrThrow(recipient.get("uuid").asText());
|
var serviceId = ServiceId.parseOrThrow(recipient.get("uuid").asText());
|
||||||
addresses.add(new RecipientAddress(uuid, recipientName));
|
addresses.add(new RecipientAddress(serviceId, recipientName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
|
||||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -31,7 +31,7 @@ public class LegacyRecipientStore2 {
|
||||||
|
|
||||||
final var recipients = storage.recipients.stream().map(r -> {
|
final var recipients = storage.recipients.stream().map(r -> {
|
||||||
final var recipientId = new RecipientId(r.id, recipientStore);
|
final var recipientId = new RecipientId(r.id, recipientStore);
|
||||||
final var address = new RecipientAddress(Optional.ofNullable(r.uuid).map(UuidUtil::parseOrThrow),
|
final var address = new RecipientAddress(Optional.ofNullable(r.uuid).map(ServiceId::parseOrThrow),
|
||||||
Optional.ofNullable(r.number));
|
Optional.ofNullable(r.number));
|
||||||
|
|
||||||
Contact contact = null;
|
Contact contact = null;
|
||||||
|
|
|
@ -1,47 +1,61 @@
|
||||||
package org.asamk.signal.manager.storage.recipients;
|
package org.asamk.signal.manager.storage.recipients;
|
||||||
|
|
||||||
|
import org.whispersystems.signalservice.api.push.PNI;
|
||||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
public record RecipientAddress(Optional<ServiceId> serviceId, Optional<PNI> pni, Optional<String> number) {
|
||||||
|
|
||||||
public static final UUID UNKNOWN_UUID = ServiceId.UNKNOWN.uuid();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a RecipientAddress.
|
* Construct a RecipientAddress.
|
||||||
*
|
*
|
||||||
* @param uuid The UUID of the user, if available.
|
* @param serviceId The ACI or PNI of the user, if available.
|
||||||
* @param number The phone number of the user, if available.
|
* @param number The phone number of the user, if available.
|
||||||
*/
|
*/
|
||||||
public RecipientAddress {
|
public RecipientAddress {
|
||||||
uuid = uuid.isPresent() && uuid.get().equals(UNKNOWN_UUID) ? Optional.empty() : uuid;
|
if (serviceId.isPresent() && serviceId.get().equals(ServiceId.UNKNOWN)) {
|
||||||
if (uuid.isEmpty() && number.isEmpty()) {
|
serviceId = Optional.empty();
|
||||||
throw new AssertionError("Must have either a UUID or E164 number!");
|
}
|
||||||
|
if (pni.isPresent() && pni.get().equals(ServiceId.UNKNOWN)) {
|
||||||
|
pni = Optional.empty();
|
||||||
|
}
|
||||||
|
if (serviceId.isEmpty() && pni.isPresent()) {
|
||||||
|
serviceId = Optional.of(pni.get());
|
||||||
|
}
|
||||||
|
if (serviceId.isEmpty() && number.isEmpty()) {
|
||||||
|
throw new AssertionError("Must have either a ServiceId or E164 number!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(UUID uuid, String e164) {
|
public RecipientAddress(Optional<ServiceId> serviceId, Optional<String> number) {
|
||||||
this(Optional.ofNullable(uuid), Optional.ofNullable(e164));
|
this(serviceId, Optional.empty(), number);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientAddress(ServiceId serviceId, String e164) {
|
||||||
|
this(Optional.ofNullable(serviceId), Optional.empty(), Optional.ofNullable(e164));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecipientAddress(ServiceId serviceId, PNI pni, String e164) {
|
||||||
|
this(Optional.ofNullable(serviceId), Optional.ofNullable(pni), Optional.ofNullable(e164));
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(SignalServiceAddress address) {
|
public RecipientAddress(SignalServiceAddress address) {
|
||||||
this(Optional.of(address.getServiceId().uuid()), address.getNumber());
|
this(Optional.of(address.getServiceId()), Optional.empty(), address.getNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(UUID uuid) {
|
public RecipientAddress(ServiceId serviceId) {
|
||||||
this(Optional.of(uuid), Optional.empty());
|
this(Optional.of(serviceId), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceId getServiceId() {
|
public ServiceId getServiceId() {
|
||||||
return ServiceId.from(uuid.orElse(UNKNOWN_UUID));
|
return serviceId.orElse(ServiceId.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
if (uuid.isPresent()) {
|
if (serviceId.isPresent()) {
|
||||||
return uuid.get().toString();
|
return serviceId.get().toString();
|
||||||
} else if (number.isPresent()) {
|
} else if (number.isPresent()) {
|
||||||
return number.get();
|
return number.get();
|
||||||
} else {
|
} else {
|
||||||
|
@ -52,15 +66,25 @@ public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
||||||
public String getLegacyIdentifier() {
|
public String getLegacyIdentifier() {
|
||||||
if (number.isPresent()) {
|
if (number.isPresent()) {
|
||||||
return number.get();
|
return number.get();
|
||||||
} else if (uuid.isPresent()) {
|
} else if (serviceId.isPresent()) {
|
||||||
return uuid.get().toString();
|
return serviceId.get().toString();
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError("Given the checks in the constructor, this should not be possible.");
|
throw new AssertionError("Given the checks in the constructor, this should not be possible.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(RecipientAddress other) {
|
public boolean matches(RecipientAddress other) {
|
||||||
return (uuid.isPresent() && other.uuid.isPresent() && uuid.get().equals(other.uuid.get())) || (
|
return (serviceId.isPresent() && other.serviceId.isPresent() && serviceId.get().equals(other.serviceId.get()))
|
||||||
|
|| (
|
||||||
|
pni.isPresent() && other.serviceId.isPresent() && pni.get().equals(other.serviceId.get())
|
||||||
|
)
|
||||||
|
|| (
|
||||||
|
serviceId.isPresent() && other.pni.isPresent() && serviceId.get().equals(other.pni.get())
|
||||||
|
)
|
||||||
|
|| (
|
||||||
|
pni.isPresent() && other.pni.isPresent() && pni.get().equals(other.pni.get())
|
||||||
|
)
|
||||||
|
|| (
|
||||||
number.isPresent() && other.number.isPresent() && number.get().equals(other.number.get())
|
number.isPresent() && other.number.isPresent() && number.get().equals(other.number.get())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -68,4 +92,8 @@ public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
||||||
public SignalServiceAddress toSignalServiceAddress() {
|
public SignalServiceAddress toSignalServiceAddress() {
|
||||||
return new SignalServiceAddress(getServiceId(), number);
|
return new SignalServiceAddress(getServiceId(), number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public org.asamk.signal.manager.api.RecipientAddress toApiRecipientAddress() {
|
||||||
|
return new org.asamk.signal.manager.api.RecipientAddress(serviceId().map(ServiceId::uuid), number());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,6 @@ public interface RecipientResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
default RecipientId resolveRecipient(ServiceId serviceId) {
|
default RecipientId resolveRecipient(ServiceId serviceId) {
|
||||||
return resolveRecipient(new RecipientAddress(serviceId.uuid()));
|
return resolveRecipient(new RecipientAddress(serviceId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -163,13 +162,13 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException("Failed read from recipient store", e);
|
throw new RuntimeException("Failed read from recipient store", e);
|
||||||
}
|
}
|
||||||
if (byNumber.isEmpty() || byNumber.get().address().uuid().isEmpty()) {
|
if (byNumber.isEmpty() || byNumber.get().address().serviceId().isEmpty()) {
|
||||||
final var aci = aciSupplier.get();
|
final var aci = aciSupplier.get();
|
||||||
if (aci == null) {
|
if (aci == null) {
|
||||||
throw new UnregisteredRecipientException(new RecipientAddress(null, number));
|
throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null, number));
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveRecipient(new RecipientAddress(aci.uuid(), number), false, false);
|
return resolveRecipient(new RecipientAddress(aci, number), false, false);
|
||||||
}
|
}
|
||||||
return byNumber.get().id();
|
return byNumber.get().id();
|
||||||
}
|
}
|
||||||
|
@ -399,7 +398,12 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
for (final var recipient : recipients.values()) {
|
for (final var recipient : recipients.values()) {
|
||||||
statement.setLong(1, recipient.getRecipientId().id());
|
statement.setLong(1, recipient.getRecipientId().id());
|
||||||
statement.setString(2, recipient.getAddress().number().orElse(null));
|
statement.setString(2, recipient.getAddress().number().orElse(null));
|
||||||
statement.setBytes(3, recipient.getAddress().uuid().map(UuidUtil::toByteArray).orElse(null));
|
statement.setBytes(3,
|
||||||
|
recipient.getAddress()
|
||||||
|
.serviceId()
|
||||||
|
.map(ServiceId::uuid)
|
||||||
|
.map(UuidUtil::toByteArray)
|
||||||
|
.orElse(null));
|
||||||
statement.executeUpdate();
|
statement.executeUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,22 +580,22 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
final var byNumber = address.number().isEmpty()
|
final var byNumber = address.number().isEmpty()
|
||||||
? Optional.<RecipientWithAddress>empty()
|
? Optional.<RecipientWithAddress>empty()
|
||||||
: findByNumber(connection, address.number().get());
|
: findByNumber(connection, address.number().get());
|
||||||
final var byUuid = address.uuid().isEmpty()
|
final var byUuid = address.serviceId().isEmpty()
|
||||||
? Optional.<RecipientWithAddress>empty()
|
? Optional.<RecipientWithAddress>empty()
|
||||||
: findByUuid(connection, address.uuid().get());
|
: findByServiceId(connection, address.serviceId().get());
|
||||||
|
|
||||||
if (byNumber.isEmpty() && byUuid.isEmpty()) {
|
if (byNumber.isEmpty() && byUuid.isEmpty()) {
|
||||||
logger.debug("Got new recipient, both uuid and number are unknown");
|
logger.debug("Got new recipient, both uuid and number are unknown");
|
||||||
|
|
||||||
if (isHighTrust || address.uuid().isEmpty() || address.number().isEmpty()) {
|
if (isHighTrust || address.serviceId().isEmpty() || address.number().isEmpty()) {
|
||||||
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
|
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pair<>(addNewRecipient(connection, new RecipientAddress(address.uuid().get())),
|
return new Pair<>(addNewRecipient(connection, new RecipientAddress(address.serviceId().get())),
|
||||||
Optional.empty());
|
Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isHighTrust || address.uuid().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) {
|
if (!isHighTrust || address.serviceId().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) {
|
||||||
return new Pair<>(byUuid.or(() -> byNumber).map(RecipientWithAddress::id).get(), Optional.empty());
|
return new Pair<>(byUuid.or(() -> byNumber).map(RecipientWithAddress::id).get(), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,14 +608,14 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
final var byNumberRecipient = byNumber.get();
|
final var byNumberRecipient = byNumber.get();
|
||||||
|
|
||||||
if (byUuid.isEmpty()) {
|
if (byUuid.isEmpty()) {
|
||||||
if (byNumberRecipient.address().uuid().isPresent()) {
|
if (byNumberRecipient.address().serviceId().isPresent()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Got recipient {} existing with number, but different uuid, so stripping its number and adding new recipient",
|
"Got recipient {} existing with number, but different uuid, so stripping its number and adding new recipient",
|
||||||
byNumberRecipient.id());
|
byNumberRecipient.id());
|
||||||
|
|
||||||
updateRecipientAddress(connection,
|
updateRecipientAddress(connection,
|
||||||
byNumberRecipient.id(),
|
byNumberRecipient.id(),
|
||||||
new RecipientAddress(byNumberRecipient.address().uuid().get()));
|
new RecipientAddress(byNumberRecipient.address().serviceId().get()));
|
||||||
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
|
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,7 +627,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
|
|
||||||
final var byUuidRecipient = byUuid.get();
|
final var byUuidRecipient = byUuid.get();
|
||||||
|
|
||||||
if (byNumberRecipient.address().uuid().isPresent()) {
|
if (byNumberRecipient.address().serviceId().isPresent()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Got separate recipients for high trust number {} and uuid {}, recipient for number has different uuid, so stripping its number",
|
"Got separate recipients for high trust number {} and uuid {}, recipient for number has different uuid, so stripping its number",
|
||||||
byNumberRecipient.id(),
|
byNumberRecipient.id(),
|
||||||
|
@ -631,7 +635,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
|
|
||||||
updateRecipientAddress(connection,
|
updateRecipientAddress(connection,
|
||||||
byNumberRecipient.id(),
|
byNumberRecipient.id(),
|
||||||
new RecipientAddress(byNumberRecipient.address().uuid().get()));
|
new RecipientAddress(byNumberRecipient.address().serviceId().get()));
|
||||||
updateRecipientAddress(connection, byUuidRecipient.id(), address);
|
updateRecipientAddress(connection, byUuidRecipient.id(), address);
|
||||||
return new Pair<>(byUuidRecipient.id(), Optional.empty());
|
return new Pair<>(byUuidRecipient.id(), Optional.empty());
|
||||||
}
|
}
|
||||||
|
@ -658,7 +662,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
).formatted(TABLE_RECIPIENT);
|
).formatted(TABLE_RECIPIENT);
|
||||||
try (final var statement = connection.prepareStatement(sql)) {
|
try (final var statement = connection.prepareStatement(sql)) {
|
||||||
statement.setString(1, address.number().orElse(null));
|
statement.setString(1, address.number().orElse(null));
|
||||||
statement.setBytes(2, address.uuid().map(UuidUtil::toByteArray).orElse(null));
|
statement.setBytes(2, address.serviceId().map(ServiceId::uuid).map(UuidUtil::toByteArray).orElse(null));
|
||||||
statement.executeUpdate();
|
statement.executeUpdate();
|
||||||
final var generatedKeys = statement.getGeneratedKeys();
|
final var generatedKeys = statement.getGeneratedKeys();
|
||||||
if (generatedKeys.next()) {
|
if (generatedKeys.next()) {
|
||||||
|
@ -697,7 +701,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
).formatted(TABLE_RECIPIENT);
|
).formatted(TABLE_RECIPIENT);
|
||||||
try (final var statement = connection.prepareStatement(sql)) {
|
try (final var statement = connection.prepareStatement(sql)) {
|
||||||
statement.setString(1, address.number().orElse(null));
|
statement.setString(1, address.number().orElse(null));
|
||||||
statement.setBytes(2, address.uuid().map(UuidUtil::toByteArray).orElse(null));
|
statement.setBytes(2, address.serviceId().map(ServiceId::uuid).map(UuidUtil::toByteArray).orElse(null));
|
||||||
statement.setLong(3, recipientId.id());
|
statement.setLong(3, recipientId.id());
|
||||||
statement.executeUpdate();
|
statement.executeUpdate();
|
||||||
}
|
}
|
||||||
|
@ -761,8 +765,8 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<RecipientWithAddress> findByUuid(
|
private Optional<RecipientWithAddress> findByServiceId(
|
||||||
final Connection connection, final UUID uuid
|
final Connection connection, final ServiceId serviceId
|
||||||
) throws SQLException {
|
) throws SQLException {
|
||||||
final var sql = """
|
final var sql = """
|
||||||
SELECT r._id, r.number, r.uuid
|
SELECT r._id, r.number, r.uuid
|
||||||
|
@ -770,7 +774,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
WHERE r.uuid = ?
|
WHERE r.uuid = ?
|
||||||
""".formatted(TABLE_RECIPIENT);
|
""".formatted(TABLE_RECIPIENT);
|
||||||
try (final var statement = connection.prepareStatement(sql)) {
|
try (final var statement = connection.prepareStatement(sql)) {
|
||||||
statement.setBytes(1, UuidUtil.toByteArray(uuid));
|
statement.setBytes(1, UuidUtil.toByteArray(serviceId.uuid()));
|
||||||
return Utils.executeQueryForOptional(statement, this::getRecipientWithAddressFromResultSet);
|
return Utils.executeQueryForOptional(statement, this::getRecipientWithAddressFromResultSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,9 +839,9 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
}
|
}
|
||||||
|
|
||||||
private RecipientAddress getRecipientAddressFromResultSet(ResultSet resultSet) throws SQLException {
|
private RecipientAddress getRecipientAddressFromResultSet(ResultSet resultSet) throws SQLException {
|
||||||
final var uuid = Optional.ofNullable(resultSet.getBytes("uuid")).map(UuidUtil::parseOrNull);
|
final var serviceId = Optional.ofNullable(resultSet.getBytes("uuid")).map(ServiceId::parseOrNull);
|
||||||
final var number = Optional.ofNullable(resultSet.getString("number"));
|
final var number = Optional.ofNullable(resultSet.getString("number"));
|
||||||
return new RecipientAddress(uuid, number);
|
return new RecipientAddress(serviceId, Optional.empty(), number);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RecipientId getRecipientIdFromResultSet(ResultSet resultSet) throws SQLException {
|
private RecipientId getRecipientIdFromResultSet(ResultSet resultSet) throws SQLException {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import org.signal.libsignal.protocol.InvalidMessageException;
|
||||||
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord;
|
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -38,13 +37,11 @@ public class LegacySenderKeyRecordStore {
|
||||||
|
|
||||||
final var senderKeys = parseFileNames(files, resolver).stream().map(key -> {
|
final var senderKeys = parseFileNames(files, resolver).stream().map(key -> {
|
||||||
final var record = loadSenderKeyLocked(key, senderKeysPath);
|
final var record = loadSenderKeyLocked(key, senderKeysPath);
|
||||||
final var uuid = addressResolver.resolveRecipientAddress(key.recipientId).uuid();
|
final var serviceId = addressResolver.resolveRecipientAddress(key.recipientId).serviceId();
|
||||||
if (record == null || uuid.isEmpty()) {
|
if (record == null || serviceId.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Pair<>(new SenderKeyRecordStore.Key(ServiceId.from(uuid.get()),
|
return new Pair<>(new SenderKeyRecordStore.Key(serviceId.get(), key.deviceId, key.distributionId), record);
|
||||||
key.deviceId,
|
|
||||||
key.distributionId), record);
|
|
||||||
}).filter(Objects::nonNull).toList();
|
}).filter(Objects::nonNull).toList();
|
||||||
|
|
||||||
senderKeyStore.addLegacySenderKeys(senderKeys);
|
senderKeyStore.addLegacySenderKeys(senderKeys);
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.asamk.signal.manager.storage.senderKeys.SenderKeySharedStore.SenderKe
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -37,11 +36,11 @@ public class LegacySenderKeySharedStore {
|
||||||
if (recipientId == null) {
|
if (recipientId == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final var uuid = addressResolver.resolveRecipientAddress(recipientId).uuid();
|
final var serviceId = addressResolver.resolveRecipientAddress(recipientId).serviceId();
|
||||||
if (uuid.isEmpty()) {
|
if (serviceId.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final var entry = new SenderKeySharedEntry(ServiceId.from(uuid.get()), senderKey.deviceId);
|
final var entry = new SenderKeySharedEntry(serviceId.get(), senderKey.deviceId);
|
||||||
final var distributionId = DistributionId.from(senderKey.distributionId);
|
final var distributionId = DistributionId.from(senderKey.distributionId);
|
||||||
var entries = sharedSenderKeys.get(distributionId);
|
var entries = sharedSenderKeys.get(distributionId);
|
||||||
if (entries == null) {
|
if (entries == null) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import org.asamk.signal.manager.util.IOUtils;
|
||||||
import org.signal.libsignal.protocol.state.SessionRecord;
|
import org.signal.libsignal.protocol.state.SessionRecord;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -34,11 +33,11 @@ public class LegacySessionStore {
|
||||||
final var keys = getKeysLocked(sessionsPath, resolver);
|
final var keys = getKeysLocked(sessionsPath, resolver);
|
||||||
final var sessions = keys.stream().map(key -> {
|
final var sessions = keys.stream().map(key -> {
|
||||||
final var record = loadSessionLocked(key, sessionsPath);
|
final var record = loadSessionLocked(key, sessionsPath);
|
||||||
final var uuid = addressResolver.resolveRecipientAddress(key.recipientId).uuid();
|
final var serviceId = addressResolver.resolveRecipientAddress(key.recipientId).serviceId();
|
||||||
if (record == null || uuid.isEmpty()) {
|
if (record == null || serviceId.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Pair<>(new SessionStore.Key(ServiceId.from(uuid.get()), key.deviceId()), record);
|
return new Pair<>(new SessionStore.Key(serviceId.get(), key.deviceId()), record);
|
||||||
}).filter(Objects::nonNull).toList();
|
}).filter(Objects::nonNull).toList();
|
||||||
sessionStore.addLegacySessions(sessions);
|
sessionStore.addLegacySessions(sessions);
|
||||||
deleteAllSessions(sessionsPath);
|
deleteAllSessions(sessionsPath);
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class Utils {
|
||||||
version = 1;
|
version = 1;
|
||||||
ownId = ownAddress.number().get().getBytes();
|
ownId = ownAddress.number().get().getBytes();
|
||||||
theirId = theirAddress.number().get().getBytes();
|
theirId = theirAddress.number().get().getBytes();
|
||||||
} else if (isUuidCapable && theirAddress.uuid().isPresent()) {
|
} else if (isUuidCapable && theirAddress.serviceId().isPresent()) {
|
||||||
// Version 2: UUID user
|
// Version 2: UUID user
|
||||||
version = 2;
|
version = 2;
|
||||||
ownId = ownAddress.getServiceId().toByteArray();
|
ownId = ownAddress.getServiceId().toByteArray();
|
||||||
|
|
|
@ -2,10 +2,10 @@ package org.asamk.signal;
|
||||||
|
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.api.MessageEnvelope;
|
import org.asamk.signal.manager.api.MessageEnvelope;
|
||||||
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.UntrustedIdentityException;
|
import org.asamk.signal.manager.api.UntrustedIdentityException;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.asamk.signal.output.PlainTextWriter;
|
import org.asamk.signal.output.PlainTextWriter;
|
||||||
import org.asamk.signal.util.DateUtils;
|
import org.asamk.signal.util.DateUtils;
|
||||||
import org.asamk.signal.util.Hex;
|
import org.asamk.signal.util.Hex;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
import org.asamk.signal.commands.exceptions.CommandException;
|
import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.api.Group;
|
import org.asamk.signal.manager.api.Group;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.output.JsonWriter;
|
import org.asamk.signal.output.JsonWriter;
|
||||||
import org.asamk.signal.output.OutputWriter;
|
import org.asamk.signal.output.OutputWriter;
|
||||||
import org.asamk.signal.output.PlainTextWriter;
|
import org.asamk.signal.output.PlainTextWriter;
|
||||||
|
|
|
@ -15,6 +15,8 @@ import org.asamk.signal.manager.api.MessageEnvelope;
|
||||||
import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.ReceiveConfig;
|
import org.asamk.signal.manager.api.ReceiveConfig;
|
||||||
|
import org.asamk.signal.manager.api.Recipient;
|
||||||
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
||||||
import org.asamk.signal.manager.api.SendMessageResults;
|
import org.asamk.signal.manager.api.SendMessageResults;
|
||||||
|
@ -34,8 +36,6 @@ import org.asamk.signal.manager.groups.LastGroupAdminException;
|
||||||
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
||||||
import org.asamk.signal.manager.storage.recipients.Contact;
|
import org.asamk.signal.manager.storage.recipients.Contact;
|
||||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||||
import org.asamk.signal.manager.storage.recipients.Recipient;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.freedesktop.dbus.DBusMap;
|
import org.freedesktop.dbus.DBusMap;
|
||||||
import org.freedesktop.dbus.DBusPath;
|
import org.freedesktop.dbus.DBusPath;
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
|
|
|
@ -3,8 +3,8 @@ package org.asamk.signal.dbus;
|
||||||
import org.asamk.Signal;
|
import org.asamk.Signal;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.api.MessageEnvelope;
|
import org.asamk.signal.manager.api.MessageEnvelope;
|
||||||
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
import org.freedesktop.dbus.types.Variant;
|
import org.freedesktop.dbus.types.Variant;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.asamk.signal.manager.api.InvalidStickerException;
|
||||||
import org.asamk.signal.manager.api.Message;
|
import org.asamk.signal.manager.api.Message;
|
||||||
import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
||||||
import org.asamk.signal.manager.api.PendingAdminApprovalException;
|
import org.asamk.signal.manager.api.PendingAdminApprovalException;
|
||||||
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.SendMessageResult;
|
import org.asamk.signal.manager.api.SendMessageResult;
|
||||||
import org.asamk.signal.manager.api.SendMessageResults;
|
import org.asamk.signal.manager.api.SendMessageResults;
|
||||||
|
@ -28,7 +29,6 @@ import org.asamk.signal.manager.groups.GroupPermission;
|
||||||
import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
|
import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
|
||||||
import org.asamk.signal.manager.groups.LastGroupAdminException;
|
import org.asamk.signal.manager.groups.LastGroupAdminException;
|
||||||
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
import org.asamk.signal.util.SendMessageResultUtils;
|
import org.asamk.signal.util.SendMessageResultUtils;
|
||||||
import org.freedesktop.dbus.DBusPath;
|
import org.freedesktop.dbus.DBusPath;
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
|
|
|
@ -4,9 +4,9 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.api.MessageEnvelope;
|
import org.asamk.signal.manager.api.MessageEnvelope;
|
||||||
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.UntrustedIdentityException;
|
import org.asamk.signal.manager.api.UntrustedIdentityException;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.asamk.signal.json;
|
package org.asamk.signal.json;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ package org.asamk.signal.json;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
import org.asamk.signal.manager.api.MessageEnvelope;
|
import org.asamk.signal.manager.api.MessageEnvelope;
|
||||||
|
import org.asamk.signal.manager.api.RecipientAddress;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue