From 7eb7ee44f2dd85431bf8077965f73cf14d477000 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 8 Oct 2022 12:40:00 +0200 Subject: [PATCH] Refactor RecipientAddress --- .../org/asamk/signal/manager/Manager.java | 2 +- .../org/asamk/signal/manager/ManagerImpl.java | 19 ++- .../org/asamk/signal/manager/api/Group.java | 6 +- .../asamk/signal/manager/api/Identity.java | 1 - .../signal/manager/api/MessageEnvelope.java | 38 +++-- .../asamk/signal/manager/api/Recipient.java | 153 ++++++++++++++++++ .../signal/manager/api/RecipientAddress.java | 71 ++++++++ .../manager/api/RecipientIdentifier.java | 1 - .../signal/manager/api/SendMessageResult.java | 3 +- .../api/UnregisteredRecipientException.java | 2 - .../api/UntrustedIdentityException.java | 2 - .../signal/manager/helper/IdentityHelper.java | 2 +- .../helper/IncomingMessageHandler.java | 6 +- .../signal/manager/helper/ReceiveHelper.java | 4 +- .../manager/helper/RecipientHelper.java | 7 +- .../signal/manager/helper/StorageHelper.java | 3 +- .../signal/manager/storage/SignalAccount.java | 8 +- .../asamk/signal/manager/storage/Utils.java | 3 +- .../storage/contacts/LegacyContactInfo.java | 3 +- .../storage/groups/LegacyGroupStore.java | 4 +- .../storage/profiles/LegacyProfileStore.java | 6 +- .../protocol/LegacyJsonIdentityKeyStore.java | 3 +- .../protocol/LegacyJsonSessionStore.java | 3 +- .../recipients/LegacyRecipientStore.java | 6 +- .../recipients/LegacyRecipientStore2.java | 4 +- .../storage/recipients/RecipientAddress.java | 68 +++++--- .../storage/recipients/RecipientResolver.java | 2 +- .../storage/recipients/RecipientStore.java | 46 +++--- .../LegacySenderKeyRecordStore.java | 9 +- .../LegacySenderKeySharedStore.java | 7 +- .../storage/sessions/LegacySessionStore.java | 7 +- .../org/asamk/signal/manager/util/Utils.java | 2 +- .../asamk/signal/ReceiveMessageHandler.java | 2 +- .../signal/commands/ListGroupsCommand.java | 2 +- .../asamk/signal/dbus/DbusManagerImpl.java | 4 +- .../dbus/DbusReceiveMessageHandler.java | 2 +- .../org/asamk/signal/dbus/DbusSignalImpl.java | 2 +- .../signal/json/JsonMessageEnvelope.java | 2 +- .../signal/json/JsonRecipientAddress.java | 2 +- .../asamk/signal/json/JsonSyncMessage.java | 2 +- 40 files changed, 392 insertions(+), 127 deletions(-) create mode 100644 lib/src/main/java/org/asamk/signal/manager/api/Recipient.java create mode 100644 lib/src/main/java/org/asamk/signal/manager/api/RecipientAddress.java diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index eb62cb60..007a783e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -14,6 +14,7 @@ import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.PendingAdminApprovalException; 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.SendGroupMessageResults; 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.NotAGroupMemberException; import org.asamk.signal.manager.storage.recipients.Profile; -import org.asamk.signal.manager.storage.recipients.Recipient; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.Closeable; diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index afc290b7..fc38c92a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -29,6 +29,7 @@ import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.PendingAdminApprovalException; 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.SendGroupMessageResults; 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.identities.IdentityInfo; 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.stickerPacks.JsonStickerPack; import org.asamk.signal.manager.storage.stickerPacks.StickerPackStore; @@ -707,13 +707,13 @@ class ManagerImpl implements Manager { @Override public void deleteRecipient(final RecipientIdentifier.Single recipient) { - account.removeRecipient(account.getRecipientResolver().resolveRecipient(recipient.toPartialRecipientAddress())); + account.removeRecipient(account.getRecipientResolver().resolveRecipient(recipient.getIdentifier())); } @Override public void deleteContact(final RecipientIdentifier.Single recipient) { account.getContactStore() - .deleteContact(account.getRecipientResolver().resolveRecipient(recipient.toPartialRecipientAddress())); + .deleteContact(account.getRecipientResolver().resolveRecipient(recipient.getIdentifier())); } @Override @@ -1005,7 +1005,16 @@ class ManagerImpl implements Manager { } // refresh profiles of explicitly given recipients 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 @@ -1049,7 +1058,7 @@ class ManagerImpl implements Manager { .resolveRecipientAddress(account.getRecipientResolver().resolveRecipient(identityInfo.getServiceId())); final var scannableFingerprint = context.getIdentityHelper() .computeSafetyNumberForScanning(identityInfo.getServiceId(), identityInfo.getIdentityKey()); - return new Identity(address, + return new Identity(address.toApiRecipientAddress(), identityInfo.getIdentityKey(), context.getIdentityHelper() .computeSafetyNumber(identityInfo.getServiceId(), identityInfo.getIdentityKey()), diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Group.java b/lib/src/main/java/org/asamk/signal/manager/api/Group.java index 9b2d988a..62f39290 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/Group.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/Group.java @@ -5,7 +5,6 @@ import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.manager.groups.GroupPermission; import org.asamk.signal.manager.helper.RecipientAddressResolver; 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 java.util.Set; @@ -40,22 +39,27 @@ public record Group( groupInfo.getMembers() .stream() .map(recipientStore::resolveRecipientAddress) + .map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress) .collect(Collectors.toSet()), groupInfo.getPendingMembers() .stream() .map(recipientStore::resolveRecipientAddress) + .map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress) .collect(Collectors.toSet()), groupInfo.getRequestingMembers() .stream() .map(recipientStore::resolveRecipientAddress) + .map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress) .collect(Collectors.toSet()), groupInfo.getAdminMembers() .stream() .map(recipientStore::resolveRecipientAddress) + .map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress) .collect(Collectors.toSet()), groupInfo.getBannedMembers() .stream() .map(recipientStore::resolveRecipientAddress) + .map(org.asamk.signal.manager.storage.recipients.RecipientAddress::toApiRecipientAddress) .collect(Collectors.toSet()), groupInfo.isBlocked(), groupInfo.getMessageExpirationTimer(), diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Identity.java b/lib/src/main/java/org/asamk/signal/manager/api/Identity.java index c4755576..5d43aacc 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/Identity.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/Identity.java @@ -1,6 +1,5 @@ package org.asamk.signal.manager.api; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; import org.signal.libsignal.protocol.IdentityKey; public record Identity( diff --git a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java index 727e2eed..2140d413 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java @@ -3,7 +3,6 @@ package org.asamk.signal.manager.api; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupUtils; 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.signal.libsignal.metadata.ProtocolException; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; @@ -184,7 +183,7 @@ public record MessageEnvelope( RecipientAddressResolver addressResolver ) { 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 ) { return new Reaction(reaction.getTargetSentTimestamp(), - addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(reaction.getTargetAuthor())), + addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(reaction.getTargetAuthor())) + .toApiRecipientAddress(), reaction.getEmoji(), reaction.isRemove()); } @@ -226,7 +226,8 @@ public record MessageEnvelope( final AttachmentFileProvider fileProvider ) { return new Quote(quote.getId(), - addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())), + addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())) + .toApiRecipientAddress(), Optional.ofNullable(quote.getText()), quote.getMentions() == null ? List.of() @@ -255,9 +256,8 @@ public record MessageEnvelope( RecipientResolver recipientResolver, RecipientAddressResolver addressResolver ) { - return new Mention(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(mention.getServiceId())), - mention.getStart(), - mention.getLength()); + return new Mention(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(mention.getServiceId())) + .toApiRecipientAddress(), mention.getStart(), mention.getLength()); } } @@ -552,10 +552,12 @@ public record MessageEnvelope( return new Sent(sentMessage.getTimestamp(), sentMessage.getExpirationStartTimestamp(), sentMessage.getDestination() - .map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))), + .map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)) + .toApiRecipientAddress()), sentMessage.getRecipients() .stream() - .map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))) + .map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)) + .toApiRecipientAddress()) .collect(Collectors.toSet()), sentMessage.getDataMessage() .map(message -> Data.from(message, recipientResolver, addressResolver, fileProvider)), @@ -572,7 +574,8 @@ public record MessageEnvelope( ) { return new Blocked(blockedListMessage.getAddresses() .stream() - .map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))) + .map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)) + .toApiRecipientAddress()) .toList(), blockedListMessage.getGroupIds().stream().map(GroupId::unknownVersion).toList()); } } @@ -584,8 +587,8 @@ public record MessageEnvelope( RecipientResolver recipientResolver, RecipientAddressResolver addressResolver ) { - return new Read(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender())), - readMessage.getTimestamp()); + return new Read(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender())) + .toApiRecipientAddress(), readMessage.getTimestamp()); } } @@ -596,8 +599,8 @@ public record MessageEnvelope( RecipientResolver recipientResolver, RecipientAddressResolver addressResolver ) { - return new Viewed(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender())), - readMessage.getTimestamp()); + return new Viewed(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(readMessage.getSender())) + .toApiRecipientAddress(), readMessage.getTimestamp()); } } @@ -609,7 +612,7 @@ public record MessageEnvelope( RecipientAddressResolver addressResolver ) { 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()), messageRequestResponse.getGroupId().map(GroupId::unknownVersion), messageRequestResponse.getPerson() - .map(p -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(p)))); + .map(p -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(p)) + .toApiRecipientAddress())); } public enum Type { @@ -898,7 +902,7 @@ public record MessageEnvelope( return new MessageEnvelope(source == null ? Optional.empty() - : Optional.of(addressResolver.resolveRecipientAddress(source)), + : Optional.of(addressResolver.resolveRecipientAddress(source).toApiRecipientAddress()), sourceDevice, envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Recipient.java b/lib/src/main/java/org/asamk/signal/manager/api/Recipient.java new file mode 100644 index 00000000..1aea3c45 --- /dev/null +++ b/lib/src/main/java/org/asamk/signal/manager/api/Recipient.java @@ -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); + } + } +} diff --git a/lib/src/main/java/org/asamk/signal/manager/api/RecipientAddress.java b/lib/src/main/java/org/asamk/signal/manager/api/RecipientAddress.java new file mode 100644 index 00000000..f477b9e9 --- /dev/null +++ b/lib/src/main/java/org/asamk/signal/manager/api/RecipientAddress.java @@ -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, Optional 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); + } +} diff --git a/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java b/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java index 242d0f47..70a60d47 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java @@ -1,7 +1,6 @@ package org.asamk.signal.manager.api; import org.asamk.signal.manager.groups.GroupId; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; diff --git a/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java b/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java index be5bf801..1507390b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java @@ -1,7 +1,6 @@ package org.asamk.signal.manager.api; 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.signal.libsignal.protocol.IdentityKey; @@ -43,7 +42,7 @@ public record SendMessageResult( RecipientAddressResolver addressResolver ) { return new SendMessageResult(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient( - sendMessageResult.getAddress())), + sendMessageResult.getAddress())).toApiRecipientAddress(), sendMessageResult.isSuccess(), sendMessageResult.isNetworkFailure(), sendMessageResult.isUnregisteredFailure(), diff --git a/lib/src/main/java/org/asamk/signal/manager/api/UnregisteredRecipientException.java b/lib/src/main/java/org/asamk/signal/manager/api/UnregisteredRecipientException.java index d37c7dc7..ef7d5b74 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/UnregisteredRecipientException.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/UnregisteredRecipientException.java @@ -1,7 +1,5 @@ package org.asamk.signal.manager.api; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; - public class UnregisteredRecipientException extends Exception { private final RecipientAddress sender; diff --git a/lib/src/main/java/org/asamk/signal/manager/api/UntrustedIdentityException.java b/lib/src/main/java/org/asamk/signal/manager/api/UntrustedIdentityException.java index 7328cf64..e91903a5 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/UntrustedIdentityException.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/UntrustedIdentityException.java @@ -1,7 +1,5 @@ package org.asamk.signal.manager.api; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; - public class UntrustedIdentityException extends Exception { private final RecipientAddress sender; diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java index 0adeaf60..0efe90a4 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java @@ -85,7 +85,7 @@ public class IdentityHelper { account.getAciIdentityKeyPair().getPublicKey(), address.getServiceId().equals(serviceId) ? address - : new RecipientAddress(serviceId.uuid(), address.number().orElse(null)), + : new RecipientAddress(serviceId, address.number().orElse(null)), theirIdentityKey); } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java index 569168de..a9c8fdae 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java @@ -97,7 +97,8 @@ public final class IncomingMessageHandler { } catch (ProtocolUntrustedIdentityException e) { final var recipientId = account.getRecipientResolver().resolveRecipient(e.getSender()); final var exception = new UntrustedIdentityException(account.getRecipientAddressResolver() - .resolveRecipientAddress(recipientId), e.getSenderDevice()); + .resolveRecipientAddress(recipientId) + .toApiRecipientAddress(), e.getSenderDevice()); return new Pair<>(List.of(), exception); } catch (Exception e) { return new Pair<>(List.of(), e); @@ -129,7 +130,8 @@ public final class IncomingMessageHandler { final var recipientId = account.getRecipientResolver().resolveRecipient(e.getSender()); actions.add(new RetrieveProfileAction(recipientId)); exception = new UntrustedIdentityException(account.getRecipientAddressResolver() - .resolveRecipientAddress(recipientId), e.getSenderDevice()); + .resolveRecipientAddress(recipientId) + .toApiRecipientAddress(), e.getSenderDevice()); } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException | ProtocolInvalidMessageException e) { logger.debug("Failed to decrypt incoming message", e); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java index d3c1ef56..09ca1a40 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java @@ -212,7 +212,7 @@ public class ReceiveHelper { if (exception instanceof UntrustedIdentityException) { logger.debug("Keeping message with untrusted identity in message cache"); final var address = ((UntrustedIdentityException) exception).getSender(); - final var recipientId = account.getRecipientResolver().resolveRecipient(address); + final var recipientId = account.getRecipientResolver().resolveRecipient(address.getServiceId()); if (!envelope.hasSourceUuid()) { try { cachedMessage[0] = account.getMessageCache().replaceSender(cachedMessage[0], recipientId); @@ -260,7 +260,7 @@ public class ReceiveHelper { } if (!envelope.hasSourceUuid()) { final var identifier = ((UntrustedIdentityException) exception).getSender(); - final var recipientId = account.getRecipientResolver().resolveRecipient(identifier); + final var recipientId = account.getRecipientResolver().resolveRecipient(identifier.getServiceId()); try { account.getMessageCache().replaceSender(cachedMessage, recipientId); } catch (IOException ioException) { diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java index c8e5859a..d87b2c53 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java @@ -6,7 +6,6 @@ import org.asamk.signal.manager.api.UnregisteredRecipientException; import org.asamk.signal.manager.config.ServiceConfig; import org.asamk.signal.manager.config.ServiceEnvironmentConfig; 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.signal.libsignal.protocol.InvalidKeyException; import org.slf4j.Logger; @@ -44,7 +43,7 @@ public class RecipientHelper { public SignalServiceAddress resolveSignalServiceAddress(RecipientId 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(); } @@ -127,11 +126,11 @@ public class RecipientHelper { try { aciMap = getRegisteredUsers(Set.of(number)); } 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); if (uuid == null) { - throw new UnregisteredRecipientException(new RecipientAddress(null, number)); + throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null, number)); } return uuid; } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/StorageHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/StorageHelper.java index 15684da5..257cea83 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/StorageHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/StorageHelper.java @@ -101,8 +101,7 @@ public class StorageHelper { } final var contactRecord = record.getContact().get(); - final var address = new RecipientAddress(contactRecord.getServiceId().uuid(), - contactRecord.getNumber().orElse(null)); + final var address = new RecipientAddress(contactRecord.getServiceId(), contactRecord.getNumber().orElse(null)); final var recipientId = account.getRecipientResolver().resolveRecipient(address); final var contact = account.getContactStore().getContact(recipientId); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index 335aece5..6c179b6d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -417,8 +417,8 @@ public class SignalAccount implements Closeable { getRecipientStore().deleteRecipientData(recipientId); getMessageCache().deleteMessages(recipientId); final var recipientAddress = getRecipientStore().resolveRecipientAddress(recipientId); - if (recipientAddress.uuid().isPresent()) { - final var serviceId = ServiceId.from(recipientAddress.uuid().get()); + if (recipientAddress.serviceId().isPresent()) { + final var serviceId = recipientAddress.serviceId().get(); getAciSessionStore().deleteAllSessions(serviceId); getPniSessionStore().deleteAllSessions(serviceId); getIdentityKeyStore().deleteIdentity(serviceId); @@ -791,7 +791,7 @@ public class SignalAccount implements Closeable { if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) { logger.debug("Migrating legacy identity session store."); for (var identity : legacySignalProtocolStore.getLegacyIdentityKeyStore().getIdentities()) { - if (identity.getAddress().uuid().isEmpty()) { + if (identity.getAddress().serviceId().isEmpty()) { continue; } final var serviceId = identity.getAddress().getServiceId(); @@ -1324,7 +1324,7 @@ public class SignalAccount implements Closeable { } public RecipientAddress getSelfRecipientAddress() { - return new RecipientAddress(aci == null ? null : aci.uuid(), number); + return new RecipientAddress(aci, pni, number); } public RecipientId getSelfRecipientId() { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java b/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java index 10a45051..1c75d9cc 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/Utils.java @@ -12,6 +12,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import org.asamk.signal.manager.storage.recipients.RecipientAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -57,7 +58,7 @@ public class Utils { public static RecipientAddress getRecipientAddressFromIdentifier(final String identifier) { if (UuidUtil.isUuid(identifier)) { - return new RecipientAddress(UuidUtil.parseOrThrow(identifier)); + return new RecipientAddress(ServiceId.parseOrThrow(identifier)); } else { return new RecipientAddress(Optional.empty(), Optional.of(identifier)); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/contacts/LegacyContactInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/contacts/LegacyContactInfo.java index 6c6bd7ea..0d297e7f 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/contacts/LegacyContactInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/contacts/LegacyContactInfo.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import org.asamk.signal.manager.storage.recipients.RecipientAddress; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.UUID; @@ -43,6 +44,6 @@ public class LegacyContactInfo { @JsonIgnore public RecipientAddress getAddress() { - return new RecipientAddress(uuid, number); + return new RecipientAddress(uuid == null ? null : ServiceId.from(uuid), number); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/LegacyGroupStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/LegacyGroupStore.java index 0b5a7d4b..ad42984f 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/LegacyGroupStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/LegacyGroupStore.java @@ -18,7 +18,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 java.io.File; @@ -45,7 +45,7 @@ public class LegacyGroupStore { if (g instanceof Storage.GroupV1 g1) { final var members = g1.members.stream().map(m -> { if (m.recipientId == null) { - return recipientResolver.resolveRecipient(new RecipientAddress(UuidUtil.parseOrNull(m.uuid), + return recipientResolver.resolveRecipient(new RecipientAddress(ServiceId.parseOrNull(m.uuid), m.number)); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/LegacyProfileStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/LegacyProfileStore.java index 99e2980e..cf100257 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/LegacyProfileStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/LegacyProfileStore.java @@ -11,7 +11,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.asamk.signal.manager.storage.recipients.RecipientAddress; import org.signal.libsignal.zkgroup.InvalidInputException; 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.util.ArrayList; @@ -43,8 +43,8 @@ public class LegacyProfileStore { if (node.isArray()) { for (var entry : node) { var name = entry.hasNonNull("name") ? entry.get("name").asText() : null; - var uuid = entry.hasNonNull("uuid") ? UuidUtil.parseOrNull(entry.get("uuid").asText()) : null; - final var address = new RecipientAddress(uuid, name); + var serviceId = entry.hasNonNull("uuid") ? ServiceId.parseOrNull(entry.get("uuid").asText()) : null; + final var address = new RecipientAddress(serviceId, name); ProfileKey profileKey = null; try { profileKey = new ProfileKey(Base64.getDecoder().decode(entry.get("profileKey").asText())); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java index de5062e4..4d94b455 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonIdentityKeyStore.java @@ -13,6 +13,7 @@ import org.signal.libsignal.protocol.IdentityKeyPair; import org.signal.libsignal.protocol.InvalidKeyException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.IOException; @@ -100,7 +101,7 @@ public class LegacyJsonIdentityKeyStore { : null; final var address = uuid == null ? Utils.getRecipientAddressFromIdentifier(trustedKeyName) - : new RecipientAddress(uuid, trustedKeyName); + : new RecipientAddress(ServiceId.from(uuid), trustedKeyName); try { var id = new IdentityKey(Base64.getDecoder().decode(trustedKey.get("identityKey").asText()), 0); var trustLevel = trustedKey.hasNonNull("trustLevel") ? TrustLevel.fromInt(trustedKey.get( diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java index 9ee0cf87..df8f5cda 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyJsonSessionStore.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.JsonNode; import org.asamk.signal.manager.storage.Utils; import org.asamk.signal.manager.storage.recipients.RecipientAddress; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.IOException; @@ -47,7 +48,7 @@ public class LegacyJsonSessionStore { var uuid = session.hasNonNull("uuid") ? UuidUtil.parseOrNull(session.get("uuid").asText()) : null; final var address = uuid == null ? Utils.getRecipientAddressFromIdentifier(sessionName) - : new RecipientAddress(uuid, sessionName); + : new RecipientAddress(ServiceId.from(uuid), sessionName); final var deviceId = session.get("deviceId").asInt(); final var record = Base64.getDecoder().decode(session.get("record").asText()); var sessionInfo = new LegacySessionInfo(address, deviceId, record); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore.java index 2aeb349f..039e8471 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; 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.util.ArrayList; @@ -36,8 +36,8 @@ public class LegacyRecipientStore { if (node.isArray()) { for (var recipient : node) { var recipientName = recipient.get("name").asText(); - var uuid = UuidUtil.parseOrThrow(recipient.get("uuid").asText()); - addresses.add(new RecipientAddress(uuid, recipientName)); + var serviceId = ServiceId.parseOrThrow(recipient.get("uuid").asText()); + addresses.add(new RecipientAddress(serviceId, recipientName)); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore2.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore2.java index 0c05e0c0..57a60674 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore2.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore2.java @@ -6,7 +6,7 @@ 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.util.UuidUtil; +import org.whispersystems.signalservice.api.push.ServiceId; import java.io.File; import java.io.FileInputStream; @@ -31,7 +31,7 @@ public class LegacyRecipientStore2 { final var recipients = storage.recipients.stream().map(r -> { 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)); Contact contact = null; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java index c5f0ccbc..c3b18299 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java @@ -1,47 +1,61 @@ 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.SignalServiceAddress; import java.util.Optional; -import java.util.UUID; -public record RecipientAddress(Optional uuid, Optional number) { - - public static final UUID UNKNOWN_UUID = ServiceId.UNKNOWN.uuid(); +public record RecipientAddress(Optional serviceId, Optional pni, Optional number) { /** * Construct a RecipientAddress. * - * @param uuid The UUID of the user, if available. - * @param number The phone number 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. */ 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!"); + if (serviceId.isPresent() && serviceId.get().equals(ServiceId.UNKNOWN)) { + serviceId = Optional.empty(); + } + 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(Optional serviceId, Optional number) { + this(serviceId, Optional.empty(), number); + } + + public RecipientAddress(ServiceId serviceId, String e164) { + this(Optional.ofNullable(serviceId), Optional.empty(), Optional.ofNullable(e164)); } - public RecipientAddress(UUID uuid, String e164) { - this(Optional.ofNullable(uuid), 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) { - this(Optional.of(address.getServiceId().uuid()), address.getNumber()); + this(Optional.of(address.getServiceId()), Optional.empty(), address.getNumber()); } - public RecipientAddress(UUID uuid) { - this(Optional.of(uuid), Optional.empty()); + public RecipientAddress(ServiceId serviceId) { + this(Optional.of(serviceId), Optional.empty()); } public ServiceId getServiceId() { - return ServiceId.from(uuid.orElse(UNKNOWN_UUID)); + return serviceId.orElse(ServiceId.UNKNOWN); } public String getIdentifier() { - if (uuid.isPresent()) { - return uuid.get().toString(); + if (serviceId.isPresent()) { + return serviceId.get().toString(); } else if (number.isPresent()) { return number.get(); } else { @@ -52,15 +66,25 @@ public record RecipientAddress(Optional uuid, Optional number) { public String getLegacyIdentifier() { if (number.isPresent()) { return number.get(); - } else if (uuid.isPresent()) { - return uuid.get().toString(); + } else if (serviceId.isPresent()) { + return serviceId.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())) || ( + 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()) ); } @@ -68,4 +92,8 @@ public record RecipientAddress(Optional uuid, Optional number) { public SignalServiceAddress toSignalServiceAddress() { 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()); + } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java index f20e4bbb..85ece822 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java @@ -19,6 +19,6 @@ public interface RecipientResolver { } default RecipientId resolveRecipient(ServiceId serviceId) { - return resolveRecipient(new RecipientAddress(serviceId.uuid())); + return resolveRecipient(new RecipientAddress(serviceId)); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 1a428467..7b57f2c9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -28,7 +28,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.UUID; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -163,13 +162,13 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re } catch (SQLException 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(); 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(); } @@ -399,7 +398,12 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re for (final var recipient : recipients.values()) { statement.setLong(1, recipient.getRecipientId().id()); 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(); } } @@ -576,22 +580,22 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re final var byNumber = address.number().isEmpty() ? Optional.empty() : findByNumber(connection, address.number().get()); - final var byUuid = address.uuid().isEmpty() + final var byUuid = address.serviceId().isEmpty() ? Optional.empty() - : findByUuid(connection, address.uuid().get()); + : findByServiceId(connection, address.serviceId().get()); if (byNumber.isEmpty() && byUuid.isEmpty()) { 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, new RecipientAddress(address.uuid().get())), + return new Pair<>(addNewRecipient(connection, new RecipientAddress(address.serviceId().get())), 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()); } @@ -604,14 +608,14 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re final var byNumberRecipient = byNumber.get(); if (byUuid.isEmpty()) { - if (byNumberRecipient.address().uuid().isPresent()) { + if (byNumberRecipient.address().serviceId().isPresent()) { logger.debug( "Got recipient {} existing with number, but different uuid, so stripping its number and adding new recipient", byNumberRecipient.id()); updateRecipientAddress(connection, byNumberRecipient.id(), - new RecipientAddress(byNumberRecipient.address().uuid().get())); + new RecipientAddress(byNumberRecipient.address().serviceId().get())); return new Pair<>(addNewRecipient(connection, address), Optional.empty()); } @@ -623,7 +627,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re final var byUuidRecipient = byUuid.get(); - if (byNumberRecipient.address().uuid().isPresent()) { + if (byNumberRecipient.address().serviceId().isPresent()) { logger.debug( "Got separate recipients for high trust number {} and uuid {}, recipient for number has different uuid, so stripping its number", byNumberRecipient.id(), @@ -631,7 +635,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re updateRecipientAddress(connection, byNumberRecipient.id(), - new RecipientAddress(byNumberRecipient.address().uuid().get())); + new RecipientAddress(byNumberRecipient.address().serviceId().get())); updateRecipientAddress(connection, byUuidRecipient.id(), address); return new Pair<>(byUuidRecipient.id(), Optional.empty()); } @@ -658,7 +662,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re ).formatted(TABLE_RECIPIENT); try (final var statement = connection.prepareStatement(sql)) { 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(); final var generatedKeys = statement.getGeneratedKeys(); if (generatedKeys.next()) { @@ -697,7 +701,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re ).formatted(TABLE_RECIPIENT); try (final var statement = connection.prepareStatement(sql)) { 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.executeUpdate(); } @@ -761,8 +765,8 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re } } - private Optional findByUuid( - final Connection connection, final UUID uuid + private Optional findByServiceId( + final Connection connection, final ServiceId serviceId ) throws SQLException { final var sql = """ SELECT r._id, r.number, r.uuid @@ -770,7 +774,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re WHERE r.uuid = ? """.formatted(TABLE_RECIPIENT); 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); } } @@ -835,9 +839,9 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re } 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")); - return new RecipientAddress(uuid, number); + return new RecipientAddress(serviceId, Optional.empty(), number); } private RecipientId getRecipientIdFromResultSet(ResultSet resultSet) throws SQLException { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java index f5a1fc53..d1794156 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeyRecordStore.java @@ -8,7 +8,6 @@ import org.signal.libsignal.protocol.InvalidMessageException; import org.signal.libsignal.protocol.groups.state.SenderKeyRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.whispersystems.signalservice.api.push.ServiceId; import java.io.File; import java.io.FileInputStream; @@ -38,13 +37,11 @@ public class LegacySenderKeyRecordStore { final var senderKeys = parseFileNames(files, resolver).stream().map(key -> { final var record = loadSenderKeyLocked(key, senderKeysPath); - final var uuid = addressResolver.resolveRecipientAddress(key.recipientId).uuid(); - if (record == null || uuid.isEmpty()) { + final var serviceId = addressResolver.resolveRecipientAddress(key.recipientId).serviceId(); + if (record == null || serviceId.isEmpty()) { return null; } - return new Pair<>(new SenderKeyRecordStore.Key(ServiceId.from(uuid.get()), - key.deviceId, - key.distributionId), record); + return new Pair<>(new SenderKeyRecordStore.Key(serviceId.get(), key.deviceId, key.distributionId), record); }).filter(Objects::nonNull).toList(); senderKeyStore.addLegacySenderKeys(senderKeys); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java index dfbc2ff9..cfc36539 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/LegacySenderKeySharedStore.java @@ -7,7 +7,6 @@ import org.asamk.signal.manager.storage.senderKeys.SenderKeySharedStore.SenderKe import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.push.DistributionId; -import org.whispersystems.signalservice.api.push.ServiceId; import java.io.File; import java.io.FileInputStream; @@ -37,11 +36,11 @@ public class LegacySenderKeySharedStore { if (recipientId == null) { continue; } - final var uuid = addressResolver.resolveRecipientAddress(recipientId).uuid(); - if (uuid.isEmpty()) { + final var serviceId = addressResolver.resolveRecipientAddress(recipientId).serviceId(); + if (serviceId.isEmpty()) { 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); var entries = sharedSenderKeys.get(distributionId); if (entries == null) { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java index 1682b714..71cd9231 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/LegacySessionStore.java @@ -8,7 +8,6 @@ import org.asamk.signal.manager.util.IOUtils; import org.signal.libsignal.protocol.state.SessionRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.whispersystems.signalservice.api.push.ServiceId; import java.io.File; import java.io.FileInputStream; @@ -34,11 +33,11 @@ public class LegacySessionStore { final var keys = getKeysLocked(sessionsPath, resolver); final var sessions = keys.stream().map(key -> { final var record = loadSessionLocked(key, sessionsPath); - final var uuid = addressResolver.resolveRecipientAddress(key.recipientId).uuid(); - if (record == null || uuid.isEmpty()) { + final var serviceId = addressResolver.resolveRecipientAddress(key.recipientId).serviceId(); + if (record == null || serviceId.isEmpty()) { 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(); sessionStore.addLegacySessions(sessions); deleteAllSessions(sessionsPath); diff --git a/lib/src/main/java/org/asamk/signal/manager/util/Utils.java b/lib/src/main/java/org/asamk/signal/manager/util/Utils.java index 97adb69d..c50988a1 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/Utils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/Utils.java @@ -87,7 +87,7 @@ public class Utils { version = 1; ownId = ownAddress.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; ownId = ownAddress.getServiceId().toByteArray(); diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 10f73706..f46a76f2 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -2,10 +2,10 @@ package org.asamk.signal; import org.asamk.signal.manager.Manager; 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.UntrustedIdentityException; 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.util.DateUtils; import org.asamk.signal.util.Hex; diff --git a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java index c08571f7..91272da5 100644 --- a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java @@ -7,7 +7,7 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.Manager; 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.OutputWriter; import org.asamk.signal.output.PlainTextWriter; diff --git a/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java b/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java index b78f8022..bbfa4f1c 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java @@ -15,6 +15,8 @@ import org.asamk.signal.manager.api.MessageEnvelope; import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.manager.api.Pair; 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.SendGroupMessageResults; 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.storage.recipients.Contact; 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.DBusPath; import org.freedesktop.dbus.connections.impl.DBusConnection; diff --git a/src/main/java/org/asamk/signal/dbus/DbusReceiveMessageHandler.java b/src/main/java/org/asamk/signal/dbus/DbusReceiveMessageHandler.java index dcea2bf1..66c1fd65 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/dbus/DbusReceiveMessageHandler.java @@ -3,8 +3,8 @@ package org.asamk.signal.dbus; import org.asamk.Signal; import org.asamk.signal.manager.Manager; 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.storage.recipients.RecipientAddress; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.exceptions.DBusException; import org.freedesktop.dbus.types.Variant; diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 4b5b3ba8..92e92157 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -11,6 +11,7 @@ import org.asamk.signal.manager.api.InvalidStickerException; import org.asamk.signal.manager.api.Message; import org.asamk.signal.manager.api.NotPrimaryDeviceException; 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.SendMessageResult; 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.LastGroupAdminException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; import org.asamk.signal.util.SendMessageResultUtils; import org.freedesktop.dbus.DBusPath; import org.freedesktop.dbus.connections.impl.DBusConnection; diff --git a/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java b/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java index adc7a251..c32de61a 100644 --- a/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java +++ b/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java @@ -4,9 +4,9 @@ import com.fasterxml.jackson.annotation.JsonInclude; import org.asamk.signal.manager.Manager; 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.UntrustedIdentityException; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; import java.util.UUID; diff --git a/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java b/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java index 1bd09e83..e25385b6 100644 --- a/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java +++ b/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java @@ -1,6 +1,6 @@ package org.asamk.signal.json; -import org.asamk.signal.manager.storage.recipients.RecipientAddress; +import org.asamk.signal.manager.api.RecipientAddress; import java.util.UUID; diff --git a/src/main/java/org/asamk/signal/json/JsonSyncMessage.java b/src/main/java/org/asamk/signal/json/JsonSyncMessage.java index a251d007..802c07d5 100644 --- a/src/main/java/org/asamk/signal/json/JsonSyncMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonSyncMessage.java @@ -3,8 +3,8 @@ package org.asamk.signal.json; import com.fasterxml.jackson.annotation.JsonInclude; 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.storage.recipients.RecipientAddress; import java.util.List; -- 2.50.1