]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/Manager.java
Refactor pre key store
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / Manager.java
index caedf2f1589e8f6c548cbb8c00e7106f6f4f34c7..c1189df30477fcf512678383c34c76e99fbadff6 100644 (file)
@@ -156,6 +156,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
@@ -262,7 +263,7 @@ public class Manager implements Closeable {
     }
 
     private IdentityKeyPair getIdentityKeyPair() {
-        return account.getSignalProtocolStore().getIdentityKeyPair();
+        return account.getIdentityKeyPair();
     }
 
     public int getDeviceId() {
@@ -335,7 +336,7 @@ public class Manager implements Closeable {
 
     public void updateAccountAttributes() throws IOException {
         accountManager.setAccountAttributes(null,
-                account.getSignalProtocolStore().getLocalRegistrationId(),
+                account.getLocalRegistrationId(),
                 true,
                 // set legacy pin only if no KBS master key is set
                 account.getPinMasterKey() == null ? account.getRegistrationLockPin() : null,
@@ -481,7 +482,6 @@ public class Manager implements Closeable {
 
         var records = KeyUtils.generatePreKeyRecords(offset, ServiceConfig.PREKEY_BATCH_SIZE);
         account.addPreKeys(records);
-        account.save();
 
         return records;
     }
@@ -491,7 +491,6 @@ public class Manager implements Closeable {
 
         var record = KeyUtils.generateSignedPreKeyRecord(identityKeyPair, signedPreKeyId);
         account.addSignedPreKey(record);
-        account.save();
 
         return record;
     }
@@ -528,7 +527,7 @@ public class Manager implements Closeable {
                 ServiceConfig.AUTOMATIC_NETWORK_RETRY);
     }
 
-    private SignalProfile getRecipientProfile(
+    public SignalProfile getRecipientProfile(
             SignalServiceAddress address
     ) {
         return getRecipientProfile(address, false);
@@ -991,6 +990,22 @@ public class Manager implements Closeable {
         return sendSelfMessage(messageBuilder);
     }
 
+    public Pair<Long, List<SendMessageResult>> sendRemoteDeleteMessage(
+            long targetSentTimestamp, List<String> recipients
+    ) throws IOException, InvalidNumberException {
+        var delete = new SignalServiceDataMessage.RemoteDelete(targetSentTimestamp);
+        final var messageBuilder = SignalServiceDataMessage.newBuilder().withRemoteDelete(delete);
+        return sendMessage(messageBuilder, getSignalServiceAddresses(recipients));
+    }
+
+    public Pair<Long, List<SendMessageResult>> sendGroupRemoteDeleteMessage(
+            long targetSentTimestamp, GroupId groupId
+    ) throws IOException, NotAGroupMemberException, GroupNotFoundException {
+        var delete = new SignalServiceDataMessage.RemoteDelete(targetSentTimestamp);
+        final var messageBuilder = SignalServiceDataMessage.newBuilder().withRemoteDelete(delete);
+        return sendGroupMessage(messageBuilder, groupId);
+    }
+
     public Pair<Long, List<SendMessageResult>> sendMessageReaction(
             String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List<String> recipients
     ) throws IOException, InvalidNumberException {
@@ -1211,10 +1226,12 @@ public class Manager implements Closeable {
         try {
             messageSender.sendMessage(message, unidentifiedAccessHelper.getAccessForSync());
         } catch (UntrustedIdentityException e) {
-            account.getSignalProtocolStore()
-                    .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
-                            e.getIdentityKey(),
-                            TrustLevel.UNTRUSTED);
+            if (e.getIdentityKey() != null) {
+                account.getSignalProtocolStore()
+                        .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
+                                e.getIdentityKey(),
+                                TrustLevel.UNTRUSTED);
+            }
             throw e;
         }
     }
@@ -1296,10 +1313,12 @@ public class Manager implements Closeable {
                     }
                     return new Pair<>(timestamp, result);
                 } catch (UntrustedIdentityException e) {
-                    account.getSignalProtocolStore()
-                            .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
-                                    e.getIdentityKey(),
-                                    TrustLevel.UNTRUSTED);
+                    if (e.getIdentityKey() != null) {
+                        account.getSignalProtocolStore()
+                                .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
+                                        e.getIdentityKey(),
+                                        TrustLevel.UNTRUSTED);
+                    }
                     return new Pair<>(timestamp, List.of());
                 }
             } else {
@@ -1369,10 +1388,12 @@ public class Manager implements Closeable {
                     false,
                     System.currentTimeMillis() - startTime);
         } catch (UntrustedIdentityException e) {
-            account.getSignalProtocolStore()
-                    .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
-                            e.getIdentityKey(),
-                            TrustLevel.UNTRUSTED);
+            if (e.getIdentityKey() != null) {
+                account.getSignalProtocolStore()
+                        .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
+                                e.getIdentityKey(),
+                                TrustLevel.UNTRUSTED);
+            }
             return SendMessageResult.identityFailure(recipient, e.getIdentityKey());
         }
     }
@@ -1385,10 +1406,12 @@ public class Manager implements Closeable {
         try {
             return messageSender.sendMessage(address, unidentifiedAccessHelper.getAccessFor(address), message);
         } catch (UntrustedIdentityException e) {
-            account.getSignalProtocolStore()
-                    .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
-                            e.getIdentityKey(),
-                            TrustLevel.UNTRUSTED);
+            if (e.getIdentityKey() != null) {
+                account.getSignalProtocolStore()
+                        .saveIdentity(resolveSignalServiceAddress(e.getIdentifier()),
+                                e.getIdentityKey(),
+                                TrustLevel.UNTRUSTED);
+            }
             return SendMessageResult.identityFailure(address, e.getIdentityKey());
         }
     }
@@ -1416,7 +1439,7 @@ public class Manager implements Closeable {
     }
 
     private void handleEndSession(SignalServiceAddress source) {
-        account.getSignalProtocolStore().deleteAllSessions(source);
+        account.getSessionStore().deleteAllSessions(source.getIdentifier());
     }
 
     private List<HandleAction> handleSignalServiceDataMessage(
@@ -2356,9 +2379,8 @@ public class Manager implements Closeable {
 
         final var profileEntry = account.getProfileStore().getProfileEntry(address);
         if (profileEntry != null && profileEntry.getProfile() != null) {
-            return profileEntry.getProfile().getName();
+            return profileEntry.getProfile().getDisplayName();
         }
-
         return null;
     }
 
@@ -2388,26 +2410,7 @@ public class Manager implements Closeable {
      */
     public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException {
         var address = canonicalizeAndResolveSignalServiceAddress(name);
-        var ids = account.getSignalProtocolStore().getIdentities(address);
-        if (ids == null) {
-            return false;
-        }
-        for (var id : ids) {
-            if (!Arrays.equals(id.getIdentityKey().serialize(), fingerprint)) {
-                continue;
-            }
-
-            account.getSignalProtocolStore()
-                    .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
-            try {
-                sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
-            } catch (IOException | UntrustedIdentityException e) {
-                logger.warn("Failed to send verification sync message: {}", e.getMessage());
-            }
-            account.save();
-            return true;
-        }
-        return false;
+        return trustIdentity(address, (identityKey) -> Arrays.equals(identityKey.serialize(), fingerprint));
     }
 
     /**
@@ -2418,26 +2421,46 @@ public class Manager implements Closeable {
      */
     public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) throws InvalidNumberException {
         var address = canonicalizeAndResolveSignalServiceAddress(name);
+        return trustIdentity(address, (identityKey) -> safetyNumber.equals(computeSafetyNumber(address, identityKey)));
+    }
+
+    private boolean trustIdentity(SignalServiceAddress address, Function<IdentityKey, Boolean> verifier) {
         var ids = account.getSignalProtocolStore().getIdentities(address);
         if (ids == null) {
             return false;
         }
+
+        IdentityInfo foundIdentity = null;
+
         for (var id : ids) {
-            if (!safetyNumber.equals(computeSafetyNumber(address, id.getIdentityKey()))) {
-                continue;
+            if (verifier.apply(id.getIdentityKey())) {
+                foundIdentity = id;
+                break;
             }
+        }
 
-            account.getSignalProtocolStore()
-                    .setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
-            try {
-                sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
-            } catch (IOException | UntrustedIdentityException e) {
-                logger.warn("Failed to send verification sync message: {}", e.getMessage());
+        if (foundIdentity == null) {
+            return false;
+        }
+
+        account.getSignalProtocolStore()
+                .setIdentityTrustLevel(address, foundIdentity.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
+        try {
+            sendVerifiedMessage(address, foundIdentity.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
+        } catch (IOException | UntrustedIdentityException e) {
+            logger.warn("Failed to send verification sync message: {}", e.getMessage());
+        }
+
+        // Successfully trusted the new identity, now remove all other identities for that number
+        for (var id : ids) {
+            if (id == foundIdentity) {
+                continue;
             }
-            account.save();
-            return true;
+            account.getSignalProtocolStore().removeIdentity(address, id.getIdentityKey());
         }
-        return false;
+
+        account.save();
+        return true;
     }
 
     /**