]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java
Implement message expiration timer version
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / ProvisioningManager.java
index 8855e0626ea29b45d04000d2662b1165f307936e..09a329f56f50d03746f38c8443741ee6296fb3ee 100644 (file)
-/*
-  Copyright (C) 2015-2021 AsamK and contributors
-
-  This program is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
 package org.asamk.signal.manager;
 
-import org.asamk.signal.manager.config.ServiceConfig;
-import org.asamk.signal.manager.config.ServiceEnvironment;
-import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
-import org.asamk.signal.manager.storage.SignalAccount;
-import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
-import org.asamk.signal.manager.util.KeyUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.whispersystems.libsignal.IdentityKeyPair;
-import org.whispersystems.libsignal.util.KeyHelper;
-import org.whispersystems.signalservice.api.SignalServiceAccountManager;
-import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
-import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
-import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
-import org.whispersystems.signalservice.api.util.DeviceNameUtil;
-import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
+import org.asamk.signal.manager.api.UserAlreadyExistsException;
 
-import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.util.concurrent.TimeoutException;
 
-public class ProvisioningManager {
-
-    private final static Logger logger = LoggerFactory.getLogger(ProvisioningManager.class);
-
-    private final PathConfig pathConfig;
-    private final ServiceEnvironmentConfig serviceEnvironmentConfig;
-    private final String userAgent;
-
-    private final SignalServiceAccountManager accountManager;
-    private final IdentityKeyPair tempIdentityKey;
-    private final int registrationId;
-    private final String password;
-
-    ProvisioningManager(PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, String userAgent) {
-        this.pathConfig = pathConfig;
-        this.serviceEnvironmentConfig = serviceEnvironmentConfig;
-        this.userAgent = userAgent;
-
-        tempIdentityKey = KeyUtils.generateIdentityKeyPair();
-        registrationId = KeyHelper.generateRegistrationId(false);
-        password = KeyUtils.createPassword();
-        GroupsV2Operations groupsV2Operations;
-        try {
-            groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()));
-        } catch (Throwable ignored) {
-            groupsV2Operations = null;
-        }
-        accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
-                new DynamicCredentialsProvider(null, null, password, SignalServiceAddress.DEFAULT_DEVICE_ID),
-                userAgent,
-                groupsV2Operations,
-                ServiceConfig.AUTOMATIC_NETWORK_RETRY);
-    }
-
-    public static ProvisioningManager init(
-            File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
-    ) {
-        var pathConfig = PathConfig.createDefault(settingsPath);
-
-        final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
-
-        return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent);
-    }
-
-    public URI getDeviceLinkUri() throws TimeoutException, IOException {
-        var deviceUuid = accountManager.getNewDeviceUuid();
-
-        return new DeviceLinkInfo(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri();
-    }
-
-    public Manager finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists {
-        var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
-        var number = ret.getNumber();
-
-        logger.info("Received link information from {}, linking in progress ...", number);
-
-        if (SignalAccount.userExists(pathConfig.dataPath(), number) && !canRelinkExistingAccount(number)) {
-            throw new UserAlreadyExists(number, SignalAccount.getFileName(pathConfig.dataPath(), number));
-        }
-
-        var encryptedDeviceName = deviceName == null
-                ? null
-                : DeviceNameUtil.encryptDeviceName(deviceName, ret.getIdentity().getPrivateKey());
-
-        logger.debug("Finishing new device registration");
-        var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
-                false,
-                true,
-                registrationId,
-                encryptedDeviceName);
-
-        // Create new account with the synced identity
-        var profileKey = ret.getProfileKey() == null ? KeyUtils.createProfileKey() : ret.getProfileKey();
-
-        SignalAccount account = null;
-        try {
-            account = SignalAccount.createOrUpdateLinkedAccount(pathConfig.dataPath(),
-                    number,
-                    ret.getUuid(),
-                    password,
-                    encryptedDeviceName,
-                    deviceId,
-                    ret.getIdentity(),
-                    registrationId,
-                    profileKey,
-                    TrustNewIdentity.ON_FIRST_USE);
-
-            ManagerImpl m = null;
-            try {
-                m = new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
-
-                logger.debug("Refreshing pre keys");
-                try {
-                    m.refreshPreKeys();
-                } catch (Exception e) {
-                    logger.error("Failed to refresh pre keys.");
-                }
-
-                logger.debug("Requesting sync data");
-                try {
-                    m.requestAllSyncData();
-                } catch (Exception e) {
-                    logger.error(
-                            "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;
-            } finally {
-                if (m != null) {
-                    m.close();
-                }
-            }
-        } finally {
-            if (account != null) {
-                account.close();
-            }
-        }
-    }
-
-    private boolean canRelinkExistingAccount(final String number) throws IOException {
-        final SignalAccount signalAccount;
-        try {
-            signalAccount = SignalAccount.load(pathConfig.dataPath(), number, false, TrustNewIdentity.ON_FIRST_USE);
-        } catch (IOException e) {
-            logger.debug("Account in use or failed to load.", e);
-            return false;
-        }
-
-        try (signalAccount) {
-            if (signalAccount.isMasterDevice()) {
-                logger.debug("Account is a master device.");
-                return false;
-            }
+public interface ProvisioningManager {
 
-            final var m = new ManagerImpl(signalAccount, pathConfig, serviceEnvironmentConfig, userAgent);
-            try (m) {
-                m.checkAccountState();
-            } catch (AuthorizationFailedException ignored) {
-                return true;
-            }
+    URI getDeviceLinkUri() throws TimeoutException, IOException;
 
-            logger.debug("Account is still successfully linked.");
-            return false;
-        }
-    }
+    String finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExistsException;
 }