From: AsamK Date: Thu, 11 Nov 2021 12:29:32 +0000 (+0100) Subject: Add MultiAccountManager X-Git-Tag: v0.10.0~54 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/4a1af0786c938f887a109a17dcc879da21704a8b?ds=sidebyside Add MultiAccountManager --- 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 d7245d56..69ae9269 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -403,6 +403,8 @@ public class ManagerImpl implements Manager { @Override public void submitRateLimitRecaptchaChallenge(String challenge, String captcha) throws IOException { + captcha = captcha == null ? null : captcha.replace("signalcaptcha://", ""); + dependencies.getAccountManager().submitRateLimitRecaptchaChallenge(challenge, captcha); } diff --git a/src/main/java/org/asamk/signal/commands/SignalCreator.java b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManager.java similarity index 60% rename from src/main/java/org/asamk/signal/commands/SignalCreator.java rename to lib/src/main/java/org/asamk/signal/manager/MultiAccountManager.java index 46bbbfc0..e7205276 100644 --- a/src/main/java/org/asamk/signal/commands/SignalCreator.java +++ b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManager.java @@ -1,24 +1,23 @@ -package org.asamk.signal.commands; - -import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.ProvisioningManager; -import org.asamk.signal.manager.RegistrationManager; +package org.asamk.signal.manager; import java.io.IOException; import java.util.List; import java.util.function.Consumer; -public interface SignalCreator { +public interface MultiAccountManager extends AutoCloseable { List getAccountNumbers(); - void addManager(Manager m); - void addOnManagerAddedHandler(Consumer handler); + void addOnManagerRemovedHandler(Consumer handler); + Manager getManager(String phoneNumber); ProvisioningManager getNewProvisioningManager(); RegistrationManager getNewRegistrationManager(String username) throws IOException; + + @Override + void close(); } diff --git a/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java new file mode 100644 index 00000000..df74cf42 --- /dev/null +++ b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java @@ -0,0 +1,104 @@ +package org.asamk.signal.manager; + +import org.asamk.signal.manager.config.ServiceEnvironment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class MultiAccountManagerImpl implements MultiAccountManager { + + private final static Logger logger = LoggerFactory.getLogger(MultiAccountManagerImpl.class); + + private final Set> onManagerAddedHandlers = new HashSet<>(); + private final Set> onManagerRemovedHandlers = new HashSet<>(); + private final Set managers = new HashSet<>(); + private final File dataPath; + private final ServiceEnvironment serviceEnvironment; + private final String userAgent; + + public MultiAccountManagerImpl( + final Collection managers, + final File dataPath, + final ServiceEnvironment serviceEnvironment, + final String userAgent + ) { + this.managers.addAll(managers); + this.dataPath = dataPath; + this.serviceEnvironment = serviceEnvironment; + this.userAgent = userAgent; + } + + @Override + public List getAccountNumbers() { + synchronized (managers) { + return managers.stream().map(Manager::getSelfNumber).collect(Collectors.toList()); + } + } + + void addManager(final Manager m) { + synchronized (managers) { + if (managers.contains(m)) { + return; + } + managers.add(m); + } + synchronized (onManagerAddedHandlers) { + for (final var handler : onManagerAddedHandlers) { + handler.accept(m); + } + } + } + + @Override + public void addOnManagerAddedHandler(final Consumer handler) { + synchronized (onManagerAddedHandlers) { + onManagerAddedHandlers.add(handler); + } + } + + @Override + public void addOnManagerRemovedHandler(final Consumer handler) { + synchronized (onManagerRemovedHandlers) { + onManagerRemovedHandlers.add(handler); + } + } + + @Override + public Manager getManager(final String account) { + synchronized (managers) { + return managers.stream().filter(m -> m.getSelfNumber().equals(account)).findFirst().orElse(null); + } + } + + @Override + public ProvisioningManager getNewProvisioningManager() { + return ProvisioningManager.init(dataPath, serviceEnvironment, userAgent, this::addManager); + } + + @Override + public RegistrationManager getNewRegistrationManager(String account) throws IOException { + return RegistrationManager.init(account, dataPath, serviceEnvironment, userAgent, this::addManager); + } + + @Override + public void close() { + synchronized (managers) { + for (var m : managers) { + try { + m.close(); + } catch (IOException e) { + logger.warn("Cleanup failed", e); + } + } + managers.clear(); + } + } +} diff --git a/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java b/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java index bd9385a9..6445e511 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java +++ b/lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java @@ -38,6 +38,7 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; public class ProvisioningManager { @@ -46,16 +47,23 @@ public class ProvisioningManager { private final PathConfig pathConfig; private final ServiceEnvironmentConfig serviceEnvironmentConfig; private final String userAgent; + private final Consumer newManagerListener; private final SignalServiceAccountManager accountManager; private final IdentityKeyPair tempIdentityKey; private final int registrationId; private final String password; - ProvisioningManager(PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, String userAgent) { + ProvisioningManager( + PathConfig pathConfig, + ServiceEnvironmentConfig serviceEnvironmentConfig, + String userAgent, + final Consumer newManagerListener + ) { this.pathConfig = pathConfig; this.serviceEnvironmentConfig = serviceEnvironmentConfig; this.userAgent = userAgent; + this.newManagerListener = newManagerListener; tempIdentityKey = KeyUtils.generateIdentityKeyPair(); registrationId = KeyHelper.generateRegistrationId(false); @@ -75,12 +83,21 @@ public class ProvisioningManager { public static ProvisioningManager init( File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent + ) { + return init(settingsPath, serviceEnvironment, userAgent, null); + } + + public static ProvisioningManager init( + File settingsPath, + ServiceEnvironment serviceEnvironment, + String userAgent, + Consumer newManagerListener ) { var pathConfig = PathConfig.createDefault(settingsPath); final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent); - return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent); + return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent, newManagerListener); } public URI getDeviceLinkUri() throws TimeoutException, IOException { @@ -89,7 +106,7 @@ public class ProvisioningManager { return new DeviceLinkInfo(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri(); } - public Manager finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists { + public String finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists { var ret = accountManager.getNewDeviceRegistration(tempIdentityKey); var number = ret.getNumber(); @@ -145,11 +162,11 @@ public class ProvisioningManager { "Failed to request sync messages from linked device, data can be requested again with `sendSyncRequest`."); } - final var result = m; - account = null; - m = null; - - return result; + if (newManagerListener != null) { + newManagerListener.accept(m); + m = null; + } + return number; } finally { if (m != null) { m.close(); diff --git a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java index 789173af..669034d1 100644 --- a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java +++ b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java @@ -49,6 +49,7 @@ import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.util.function.Consumer; public class RegistrationManager implements Closeable { @@ -58,6 +59,7 @@ public class RegistrationManager implements Closeable { private final PathConfig pathConfig; private final ServiceEnvironmentConfig serviceEnvironmentConfig; private final String userAgent; + private final Consumer newManagerListener; private final SignalServiceAccountManager accountManager; private final PinHelper pinHelper; @@ -66,12 +68,14 @@ public class RegistrationManager implements Closeable { SignalAccount account, PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, - String userAgent + String userAgent, + Consumer newManagerListener ) { this.account = account; this.pathConfig = pathConfig; this.serviceEnvironmentConfig = serviceEnvironmentConfig; this.userAgent = userAgent; + this.newManagerListener = newManagerListener; GroupsV2Operations groupsV2Operations; try { @@ -96,6 +100,16 @@ public class RegistrationManager implements Closeable { public static RegistrationManager init( String number, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent + ) throws IOException { + return init(number, settingsPath, serviceEnvironment, userAgent, null); + } + + public static RegistrationManager init( + String number, + File settingsPath, + ServiceEnvironment serviceEnvironment, + String userAgent, + Consumer newManagerListener ) throws IOException { var pathConfig = PathConfig.createDefault(settingsPath); @@ -112,15 +126,16 @@ public class RegistrationManager implements Closeable { profileKey, TrustNewIdentity.ON_FIRST_USE); - return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent); + return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent, newManagerListener); } var account = SignalAccount.load(pathConfig.dataPath(), number, true, TrustNewIdentity.ON_FIRST_USE); - return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent); + return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent, newManagerListener); } public void register(boolean voiceVerification, String captcha) throws IOException, CaptchaRequiredException { + captcha = captcha == null ? null : captcha.replace("signalcaptcha://", ""); final ServiceResponse response; if (voiceVerification) { response = accountManager.requestVoiceVerificationCode(Utils.getDefaultLocale(), @@ -140,7 +155,7 @@ public class RegistrationManager implements Closeable { } } - public Manager verifyAccount( + public void verifyAccount( String verificationCode, String pin ) throws IOException, PinLockedException, IncorrectPinException { verificationCode = verificationCode.replace("-", ""); @@ -196,10 +211,10 @@ public class RegistrationManager implements Closeable { logger.warn("Failed to set default profile: {}", e.getMessage()); } - final var result = m; - m = null; - - return result; + if (newManagerListener != null) { + newManagerListener.accept(m); + m = null; + } } finally { if (m != null) { m.close(); diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 060572aa..0a8c7b41 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -12,13 +12,13 @@ import org.asamk.signal.commands.LocalCommand; import org.asamk.signal.commands.MultiLocalCommand; import org.asamk.signal.commands.ProvisioningCommand; import org.asamk.signal.commands.RegistrationCommand; -import org.asamk.signal.commands.SignalCreator; import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.dbus.DbusManagerImpl; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManagerImpl; import org.asamk.signal.manager.NotRegisteredException; import org.asamk.signal.manager.ProvisioningManager; import org.asamk.signal.manager.RegistrationManager; @@ -39,8 +39,6 @@ import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; -import java.util.stream.Collectors; import static net.sourceforge.argparse4j.DefaultSettings.VERSION_0_9_0_DEFAULT_SETTINGS; @@ -186,7 +184,7 @@ public class App { throw new UserErrorException("No local users found, you first need to register or link an account"); } else if (accounts.size() > 1) { throw new UserErrorException( - "Multiple users found, you need to specify a account (phone number) with -u"); + "Multiple users found, you need to specify an account (phone number) with -a"); } account = accounts.get(0); @@ -237,8 +235,8 @@ public class App { + e.getClass().getSimpleName() + ")", e); } - try (var m = manager) { - command.handleCommand(ns, m); + try (manager) { + command.handleCommand(ns, manager); } catch (IOException e) { logger.warn("Cleanup failed", e); } @@ -268,73 +266,19 @@ public class App { final TrustNewIdentity trustNewIdentity ) throws CommandException { final var managers = new ArrayList(); - try { - for (String u : accounts) { - try { - managers.add(loadManager(u, dataPath, serviceEnvironment, trustNewIdentity)); - } catch (CommandException e) { - logger.warn("Ignoring {}: {}", u, e.getMessage()); - } + for (String a : accounts) { + try { + managers.add(loadManager(a, dataPath, serviceEnvironment, trustNewIdentity)); + } catch (CommandException e) { + logger.warn("Ignoring {}: {}", a, e.getMessage()); } + } - command.handleCommand(ns, new SignalCreator() { - private final List> onManagerAddedHandlers = new ArrayList<>(); - - @Override - public List getAccountNumbers() { - synchronized (managers) { - return managers.stream().map(Manager::getSelfNumber).collect(Collectors.toList()); - } - } - - @Override - public void addManager(final Manager m) { - synchronized (managers) { - if (!managers.contains(m)) { - managers.add(m); - for (final var handler : onManagerAddedHandlers) { - handler.accept(m); - } - } - } - } - - @Override - public void addOnManagerAddedHandler(final Consumer handler) { - onManagerAddedHandlers.add(handler); - } - - @Override - public Manager getManager(final String phoneNumber) { - synchronized (managers) { - return managers.stream() - .filter(m -> m.getSelfNumber().equals(phoneNumber)) - .findFirst() - .orElse(null); - } - } - - @Override - public ProvisioningManager getNewProvisioningManager() { - return ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT); - } - - @Override - public RegistrationManager getNewRegistrationManager(String account) throws IOException { - return RegistrationManager.init(account, dataPath, serviceEnvironment, BaseConfig.USER_AGENT); - } - }, outputWriter); - } finally { - synchronized (managers) { - for (var m : managers) { - try { - m.close(); - } catch (IOException e) { - logger.warn("Cleanup failed", e); - } - } - managers.clear(); - } + try (var multiAccountManager = new MultiAccountManagerImpl(managers, + dataPath, + serviceEnvironment, + BaseConfig.USER_AGENT)) { + command.handleCommand(ns, multiAccountManager, outputWriter); } } diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 5e715647..605182ae 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -19,6 +19,7 @@ import org.asamk.signal.dbus.DbusSignalControlImpl; import org.asamk.signal.dbus.DbusSignalImpl; import org.asamk.signal.jsonrpc.SignalJsonRpcDispatcherHandler; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManager; import org.asamk.signal.util.IOUtils; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.exceptions.DBusException; @@ -141,7 +142,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand { @Override public void handleCommand( - final Namespace ns, final SignalCreator c, final OutputWriter outputWriter + final Namespace ns, final MultiAccountManager c, final OutputWriter outputWriter ) throws CommandException { logger.info("Starting daemon in multi-account mode"); final var noReceiveStdOut = Boolean.TRUE.equals(ns.getBoolean("no-receive-stdout")); @@ -220,7 +221,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand { } private void runSocketMultiAccount( - final SignalCreator c, final ServerSocketChannel serverChannel, final boolean noReceiveOnStart + final MultiAccountManager c, final ServerSocketChannel serverChannel, final boolean noReceiveOnStart ) { runSocket(serverChannel, channel -> { final var handler = getSignalJsonRpcDispatcherHandler(channel, noReceiveOnStart); @@ -276,7 +277,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand { } private void runDbusMultiAccount( - final SignalCreator c, final boolean noReceiveOnStart, final boolean isDbusSystem + final MultiAccountManager c, final boolean noReceiveOnStart, final boolean isDbusSystem ) throws UnexpectedErrorException { runDbus(isDbusSystem, (connection, objectPath) -> { final var signalControl = new DbusSignalControlImpl(c, objectPath); diff --git a/src/main/java/org/asamk/signal/commands/JsonRpcMultiCommand.java b/src/main/java/org/asamk/signal/commands/JsonRpcMultiCommand.java index 3f5b04a0..5ac5e4df 100644 --- a/src/main/java/org/asamk/signal/commands/JsonRpcMultiCommand.java +++ b/src/main/java/org/asamk/signal/commands/JsonRpcMultiCommand.java @@ -2,8 +2,9 @@ package org.asamk.signal.commands; import org.asamk.signal.JsonWriter; import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.manager.MultiAccountManager; public interface JsonRpcMultiCommand extends JsonRpcCommand { - void handleCommand(T request, SignalCreator c, JsonWriter jsonWriter) throws CommandException; + void handleCommand(T request, MultiAccountManager c, JsonWriter jsonWriter) throws CommandException; } diff --git a/src/main/java/org/asamk/signal/commands/JsonRpcMultiLocalCommand.java b/src/main/java/org/asamk/signal/commands/JsonRpcMultiLocalCommand.java index 1701ac8c..57bbe801 100644 --- a/src/main/java/org/asamk/signal/commands/JsonRpcMultiLocalCommand.java +++ b/src/main/java/org/asamk/signal/commands/JsonRpcMultiLocalCommand.java @@ -7,6 +7,7 @@ import net.sourceforge.argparse4j.inf.Namespace; import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputType; import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.manager.MultiAccountManager; import java.util.List; import java.util.Map; @@ -18,7 +19,7 @@ public interface JsonRpcMultiLocalCommand extends JsonRpcMultiCommand request, SignalCreator c, JsonWriter jsonWriter + Map request, MultiAccountManager c, JsonWriter jsonWriter ) throws CommandException { Namespace commandNamespace = new JsonRpcNamespace(request == null ? Map.of() : request); handleCommand(commandNamespace, c, jsonWriter); diff --git a/src/main/java/org/asamk/signal/commands/LinkCommand.java b/src/main/java/org/asamk/signal/commands/LinkCommand.java index 1d697299..c8830db2 100644 --- a/src/main/java/org/asamk/signal/commands/LinkCommand.java +++ b/src/main/java/org/asamk/signal/commands/LinkCommand.java @@ -43,9 +43,8 @@ public class LinkCommand implements ProvisioningCommand { } try { writer.println("{}", m.getDeviceLinkUri()); - try (var manager = m.finishDeviceLink(deviceName)) { - writer.println("Associated with: {}", manager.getSelfNumber()); - } + var number = m.finishDeviceLink(deviceName); + writer.println("Associated with: {}", number); } catch (TimeoutException e) { throw new UserErrorException("Link request timed out, please try again."); } catch (IOException e) { diff --git a/src/main/java/org/asamk/signal/commands/ListAccountsCommand.java b/src/main/java/org/asamk/signal/commands/ListAccountsCommand.java index 3a04fb35..4ad8fc2d 100644 --- a/src/main/java/org/asamk/signal/commands/ListAccountsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListAccountsCommand.java @@ -7,6 +7,7 @@ import org.asamk.signal.JsonWriter; import org.asamk.signal.OutputWriter; import org.asamk.signal.PlainTextWriter; import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.manager.MultiAccountManager; import java.util.stream.Collectors; @@ -24,7 +25,7 @@ public class ListAccountsCommand implements JsonRpcMultiLocalCommand { @Override public void handleCommand( - final Namespace ns, final SignalCreator c, final OutputWriter outputWriter + final Namespace ns, final MultiAccountManager c, final OutputWriter outputWriter ) throws CommandException { final var accountNumbers = c.getAccountNumbers(); if (outputWriter instanceof JsonWriter jsonWriter) { diff --git a/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java b/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java index 9cc6846c..da37c7a7 100644 --- a/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java +++ b/src/main/java/org/asamk/signal/commands/MultiLocalCommand.java @@ -4,8 +4,9 @@ import net.sourceforge.argparse4j.inf.Namespace; import org.asamk.signal.OutputWriter; import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.manager.MultiAccountManager; public interface MultiLocalCommand extends CliCommand { - void handleCommand(Namespace ns, SignalCreator c, OutputWriter outputWriter) throws CommandException; + void handleCommand(Namespace ns, MultiAccountManager c, OutputWriter outputWriter) throws CommandException; } diff --git a/src/main/java/org/asamk/signal/commands/SubmitRateLimitChallengeCommand.java b/src/main/java/org/asamk/signal/commands/SubmitRateLimitChallengeCommand.java index 46f69896..07583392 100644 --- a/src/main/java/org/asamk/signal/commands/SubmitRateLimitChallengeCommand.java +++ b/src/main/java/org/asamk/signal/commands/SubmitRateLimitChallengeCommand.java @@ -32,8 +32,7 @@ public class SubmitRateLimitChallengeCommand implements JsonRpcLocalCommand { @Override public void handleCommand(final Namespace ns, final Manager m, OutputWriter outputWriter) throws CommandException { final var challenge = ns.getString("challenge"); - final var captchaString = ns.getString("captcha"); - final var captcha = captchaString == null ? null : captchaString.replace("signalcaptcha://", ""); + final var captcha = ns.getString("captcha"); try { m.submitRateLimitRecaptchaChallenge(challenge, captcha); diff --git a/src/main/java/org/asamk/signal/commands/VerifyCommand.java b/src/main/java/org/asamk/signal/commands/VerifyCommand.java index 91799887..155cdb09 100644 --- a/src/main/java/org/asamk/signal/commands/VerifyCommand.java +++ b/src/main/java/org/asamk/signal/commands/VerifyCommand.java @@ -32,8 +32,7 @@ public class VerifyCommand implements RegistrationCommand { var pin = ns.getString("pin"); try { - final var manager = m.verifyAccount(verificationCode, pin); - manager.close(); + m.verifyAccount(verificationCode, pin); } catch (PinLockedException e) { throw new UserErrorException( "Verification failed! This number is locked with a pin. Hours remaining until reset: " diff --git a/src/main/java/org/asamk/signal/commands/VersionCommand.java b/src/main/java/org/asamk/signal/commands/VersionCommand.java index 7263efac..b8fb1fe9 100644 --- a/src/main/java/org/asamk/signal/commands/VersionCommand.java +++ b/src/main/java/org/asamk/signal/commands/VersionCommand.java @@ -4,6 +4,7 @@ import org.asamk.signal.BaseConfig; import org.asamk.signal.JsonWriter; import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManager; import java.util.Map; @@ -23,7 +24,7 @@ public class VersionCommand implements JsonRpcSingleCommand, JsonRpcMultiC @Override public void handleCommand( - final Void request, final SignalCreator c, final JsonWriter jsonWriter + final Void request, final MultiAccountManager c, final JsonWriter jsonWriter ) throws CommandException { outputVersion(jsonWriter); } diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java index e178ca15..18d966ae 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java @@ -3,8 +3,8 @@ package org.asamk.signal.dbus; import org.asamk.SignalControl; import org.asamk.signal.BaseConfig; import org.asamk.signal.DbusConfig; -import org.asamk.signal.commands.SignalCreator; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManager; import org.asamk.signal.manager.ProvisioningManager; import org.asamk.signal.manager.RegistrationManager; import org.asamk.signal.manager.UserAlreadyExists; @@ -21,11 +21,11 @@ import java.util.stream.Collectors; public class DbusSignalControlImpl implements org.asamk.SignalControl { - private final SignalCreator c; + private final MultiAccountManager c; private final String objectPath; - public DbusSignalControlImpl(final SignalCreator c, final String objectPath) { + public DbusSignalControlImpl(final MultiAccountManager c, final String objectPath) { this.c = c; this.objectPath = objectPath; } @@ -75,8 +75,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { final String number, final String verificationCode, final String pin ) throws Error.Failure, Error.InvalidNumber { try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) { - final Manager manager = registrationManager.verifyAccount(verificationCode, pin); - c.addManager(manager); + registrationManager.verifyAccount(verificationCode, pin); } catch (IOException | PinLockedException | IncorrectPinException e) { throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); } @@ -89,8 +88,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { final URI deviceLinkUri = provisioningManager.getDeviceLinkUri(); new Thread(() -> { try { - final Manager manager = provisioningManager.finishDeviceLink(newDeviceName); - c.addManager(manager); + provisioningManager.finishDeviceLink(newDeviceName); } catch (IOException | TimeoutException | UserAlreadyExists e) { e.printStackTrace(); } diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index c9099c0b..2983b293 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -129,9 +129,7 @@ public class DbusSignalImpl implements Signal { } @Override - public void submitRateLimitChallenge(String challenge, String captchaString) { - final var captcha = captchaString == null ? null : captchaString.replace("signalcaptcha://", ""); - + public void submitRateLimitChallenge(String challenge, String captcha) { try { m.submitRateLimitRecaptchaChallenge(challenge, captcha); } catch (IOException e) { diff --git a/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java b/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java index d2debfe0..112bc5a9 100644 --- a/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java +++ b/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ContainerNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.asamk.signal.JsonReceiveMessageHandler; import org.asamk.signal.JsonWriter; @@ -13,12 +14,12 @@ import org.asamk.signal.commands.Command; import org.asamk.signal.commands.Commands; import org.asamk.signal.commands.JsonRpcMultiCommand; import org.asamk.signal.commands.JsonRpcSingleCommand; -import org.asamk.signal.commands.SignalCreator; import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManager; import org.asamk.signal.util.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,7 +43,7 @@ public class SignalJsonRpcDispatcherHandler { private final JsonRpcReader jsonRpcReader; private final boolean noReceiveOnStart; - private SignalCreator c; + private MultiAccountManager c; private final Map receiveHandlers = new HashMap<>(); private Manager m; @@ -56,7 +57,7 @@ public class SignalJsonRpcDispatcherHandler { this.jsonRpcReader = new JsonRpcReader(jsonRpcSender, lineSupplier); } - public void handleConnection(final SignalCreator c) { + public void handleConnection(final MultiAccountManager c) { this.c = c; if (!noReceiveOnStart) { @@ -120,19 +121,19 @@ public class SignalJsonRpcDispatcherHandler { ) throws JsonRpcException { var command = getCommand(method); // TODO implement register, verify, link - if (c != null && command instanceof JsonRpcMultiCommand jsonRpcCommand) { - return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand)); + if (c != null) { + if (command instanceof JsonRpcMultiCommand jsonRpcCommand) { + return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand)); + } } if (command instanceof JsonRpcSingleCommand jsonRpcCommand) { if (m != null) { return runCommand(objectMapper, params, new CommandRunnerImpl<>(m, jsonRpcCommand)); } - if (params.has("account")) { - Manager manager = c.getManager(params.get("account").asText()); - if (manager != null) { - return runCommand(objectMapper, params, new CommandRunnerImpl<>(manager, jsonRpcCommand)); - } + final var manager = getManagerFromParams(params); + if (manager != null) { + return runCommand(objectMapper, params, new CommandRunnerImpl<>(manager, jsonRpcCommand)); } else { throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.INVALID_PARAMS, "Method requires valid account parameter", @@ -145,6 +146,15 @@ public class SignalJsonRpcDispatcherHandler { null)); } + private Manager getManagerFromParams(final ContainerNode params) { + if (params.has("account")) { + final var manager = c.getManager(params.get("account").asText()); + ((ObjectNode) params).remove("account"); + return manager; + } + return null; + } + private Command getCommand(final String method) { if ("subscribeReceive".equals(method)) { return new SubscribeReceiveCommand(); @@ -169,7 +179,7 @@ public class SignalJsonRpcDispatcherHandler { } private record MultiCommandRunnerImpl( - SignalCreator c, JsonRpcMultiCommand command + MultiAccountManager c, JsonRpcMultiCommand command ) implements CommandRunner { @Override