]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java
Implement SignalServiceAccountDataStore for PNI
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / SignalAccountFiles.java
index f1d37e81acbd9f2fd640d11fdca5047e74ff8ada..95fd453d1c270aa782d9f82ab93864bb162f7f4e 100644 (file)
@@ -9,9 +9,9 @@ import org.asamk.signal.manager.storage.SignalAccount;
 import org.asamk.signal.manager.storage.accounts.AccountsStore;
 import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
 import org.asamk.signal.manager.util.KeyUtils;
+import org.signal.libsignal.protocol.util.KeyHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.whispersystems.libsignal.util.KeyHelper;
 
 import java.io.File;
 import java.io.IOException;
@@ -24,6 +24,7 @@ public class SignalAccountFiles {
     private static final Logger logger = LoggerFactory.getLogger(MultiAccountManager.class);
 
     private final PathConfig pathConfig;
+    private final ServiceEnvironment serviceEnvironment;
     private final ServiceEnvironmentConfig serviceEnvironmentConfig;
     private final String userAgent;
     private final TrustNewIdentity trustNewIdentity;
@@ -34,24 +35,35 @@ public class SignalAccountFiles {
             final ServiceEnvironment serviceEnvironment,
             final String userAgent,
             final TrustNewIdentity trustNewIdentity
-    ) {
+    ) throws IOException {
         this.pathConfig = PathConfig.createDefault(settingsPath);
-        this.serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
+        this.serviceEnvironment = serviceEnvironment;
+        this.serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(this.serviceEnvironment, userAgent);
         this.userAgent = userAgent;
         this.trustNewIdentity = trustNewIdentity;
-        this.accountsStore = new AccountsStore(pathConfig.dataPath());
+        this.accountsStore = new AccountsStore(pathConfig.dataPath(), serviceEnvironment, accountPath -> {
+            if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
+                return null;
+            }
+
+            try {
+                return SignalAccount.load(pathConfig.dataPath(), accountPath, false, trustNewIdentity);
+            } catch (Exception e) {
+                return null;
+            }
+        });
     }
 
-    public Set<String> getAllLocalAccountNumbers() {
+    public Set<String> getAllLocalAccountNumbers() throws IOException {
         return accountsStore.getAllNumbers();
     }
 
-    public MultiAccountManager initMultiAccountManager() {
-        final var managers = getAllLocalAccountNumbers().stream().map(a -> {
+    public MultiAccountManager initMultiAccountManager() throws IOException {
+        final var managers = accountsStore.getAllAccounts().parallelStream().map(a -> {
             try {
-                return initManager(a);
+                return initManager(a.number(), a.path());
             } catch (NotRegisteredException | IOException | AccountCheckException e) {
-                logger.warn("Ignoring {}: {} ({})", a, e.getMessage(), e.getClass().getSimpleName());
+                logger.warn("Ignoring {}: {} ({})", a.number(), e.getMessage(), e.getClass().getSimpleName());
                 return null;
             }
         }).filter(Objects::nonNull).toList();
@@ -61,7 +73,16 @@ public class SignalAccountFiles {
 
     public Manager initManager(String number) throws IOException, NotRegisteredException, AccountCheckException {
         final var accountPath = accountsStore.getPathByNumber(number);
-        if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
+        return this.initManager(number, accountPath);
+    }
+
+    private Manager initManager(
+            String number, String accountPath
+    ) throws IOException, NotRegisteredException, AccountCheckException {
+        if (accountPath == null) {
+            throw new NotRegisteredException();
+        }
+        if (!SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
             throw new NotRegisteredException();
         }
 
@@ -76,11 +97,15 @@ public class SignalAccountFiles {
             throw new NotRegisteredException();
         }
 
+        if (account.getServiceEnvironment() != null && account.getServiceEnvironment() != serviceEnvironment) {
+            throw new IOException("Account is registered in another environment: " + account.getServiceEnvironment());
+        }
+
         account.initDatabase();
 
         final var manager = new ManagerImpl(account,
                 pathConfig,
-                (newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci),
+                new AccountFileUpdaterImpl(accountsStore, accountPath),
                 serviceEnvironmentConfig,
                 userAgent);
 
@@ -91,6 +116,11 @@ public class SignalAccountFiles {
             throw new AccountCheckException("Error while checking account " + number + ": " + e.getMessage(), e);
         }
 
+        if (account.getServiceEnvironment() == null) {
+            account.setServiceEnvironment(serviceEnvironment);
+            accountsStore.updateAccount(accountPath, account.getNumber(), account.getAci());
+        }
+
         return manager;
     }
 
@@ -116,15 +146,20 @@ public class SignalAccountFiles {
         final var accountPath = accountsStore.getPathByNumber(number);
         if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
             final var newAccountPath = accountPath == null ? accountsStore.addAccount(number, null) : accountPath;
-            var identityKey = KeyUtils.generateIdentityKeyPair();
+            var aciIdentityKey = KeyUtils.generateIdentityKeyPair();
+            var pniIdentityKey = KeyUtils.generateIdentityKeyPair();
             var registrationId = KeyHelper.generateRegistrationId(false);
+            var pniRegistrationId = KeyHelper.generateRegistrationId(false);
 
             var profileKey = KeyUtils.createProfileKey();
             var account = SignalAccount.create(pathConfig.dataPath(),
                     newAccountPath,
                     number,
-                    identityKey,
+                    serviceEnvironment,
+                    aciIdentityKey,
+                    pniIdentityKey,
                     registrationId,
+                    pniRegistrationId,
                     profileKey,
                     trustNewIdentity);
 
@@ -133,7 +168,7 @@ public class SignalAccountFiles {
                     serviceEnvironmentConfig,
                     userAgent,
                     newManagerListener,
-                    (newNumber, newAci) -> accountsStore.updateAccount(newAccountPath, newNumber, newAci));
+                    new AccountFileUpdaterImpl(accountsStore, newAccountPath));
         }
 
         var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, trustNewIdentity);
@@ -147,6 +182,6 @@ public class SignalAccountFiles {
                 serviceEnvironmentConfig,
                 userAgent,
                 newManagerListener,
-                (newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci));
+                new AccountFileUpdaterImpl(accountsStore, accountPath));
     }
 }