Add command to delete local account data

Fixes #912
This commit is contained in:
AsamK 2022-05-16 12:20:23 +02:00
parent 55dde93811
commit 22add1cbee
13 changed files with 170 additions and 9 deletions

View file

@ -0,0 +1,26 @@
package org.asamk.signal.manager;
import org.asamk.signal.manager.helper.AccountFileUpdater;
import org.asamk.signal.manager.storage.accounts.AccountsStore;
import org.whispersystems.signalservice.api.push.ACI;
class AccountFileUpdaterImpl implements AccountFileUpdater {
private final AccountsStore accountsStore;
private final String accountPath;
public AccountFileUpdaterImpl(final AccountsStore accountsStore, final String accountPath) {
this.accountsStore = accountsStore;
this.accountPath = accountPath;
}
@Override
public void updateAccountIdentifiers(final String newNumber, final ACI newAci) {
accountsStore.updateAccount(accountPath, newNumber, newAci);
}
@Override
public void removeAccount() {
accountsStore.removeAccount(accountPath);
}
}

View file

@ -66,6 +66,7 @@ import org.whispersystems.signalservice.api.SignalSessionLock;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
@ -99,6 +100,7 @@ class ManagerImpl implements Manager {
private final static Logger logger = LoggerFactory.getLogger(ManagerImpl.class);
private SignalAccount account;
private AccountFileUpdater accountFileUpdater;
private final SignalDependencies dependencies;
private final Context context;
@ -120,6 +122,7 @@ class ManagerImpl implements Manager {
String userAgent
) {
this.account = account;
this.accountFileUpdater = accountFileUpdater;
final var sessionLock = new SignalSessionLock() {
private final ReentrantLock LEGACY_LOCK = new ReentrantLock();
@ -140,10 +143,18 @@ class ManagerImpl implements Manager {
final var attachmentStore = new AttachmentStore(pathConfig.attachmentsPath());
final var stickerPackStore = new StickerPackStore(pathConfig.stickerPacksPath());
this.context = new Context(account, (number, aci) -> {
accountFileUpdater.updateAccountIdentifiers(number, aci);
synchronized (addressChangedListeners) {
addressChangedListeners.forEach(Runnable::run);
this.context = new Context(account, new AccountFileUpdater() {
@Override
public void updateAccountIdentifiers(final String number, final ACI aci) {
accountFileUpdater.updateAccountIdentifiers(number, aci);
synchronized (addressChangedListeners) {
addressChangedListeners.forEach(Runnable::run);
}
}
@Override
public void removeAccount() {
accountFileUpdater.removeAccount();
}
}, dependencies, avatarStore, attachmentStore, stickerPackStore);
this.context.getAccountHelper().setUnregisteredListener(this::close);

View file

@ -153,7 +153,7 @@ class ProvisioningManagerImpl implements ProvisioningManager {
final var accountPathFinal = accountPath;
m = new ManagerImpl(account,
pathConfig,
(newNumber, newAci) -> accountsStore.updateAccount(accountPathFinal, newNumber, newAci),
new AccountFileUpdaterImpl(accountsStore, accountPathFinal),
serviceEnvironmentConfig,
userAgent);
account = null;
@ -220,7 +220,7 @@ class ProvisioningManagerImpl implements ProvisioningManager {
final var m = new ManagerImpl(signalAccount,
pathConfig,
(newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci),
new AccountFileUpdaterImpl(accountsStore, accountPath),
serviceEnvironmentConfig,
userAgent);
try (m) {

View file

@ -14,4 +14,8 @@ public interface RegistrationManager extends Closeable {
void verifyAccount(
String verificationCode, String pin
) throws IOException, PinLockedException, IncorrectPinException;
void deleteLocalAccountData() throws IOException;
boolean isRegistered();
}

View file

@ -155,6 +155,18 @@ class RegistrationManagerImpl implements RegistrationManager {
}
}
@Override
public void deleteLocalAccountData() throws IOException {
account.deleteAccountData();
accountFileUpdater.removeAccount();
account = null;
}
@Override
public boolean isRegistered() {
return account.isRegistered();
}
private boolean attemptReactivateAccount() {
try {
final var accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),

View file

@ -95,7 +95,7 @@ public class SignalAccountFiles {
final var manager = new ManagerImpl(account,
pathConfig,
(newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci),
new AccountFileUpdaterImpl(accountsStore, accountPath),
serviceEnvironmentConfig,
userAgent);
@ -155,7 +155,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);
@ -169,6 +169,6 @@ public class SignalAccountFiles {
serviceEnvironmentConfig,
userAgent,
newManagerListener,
(newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci));
new AccountFileUpdaterImpl(accountsStore, accountPath));
}
}

View file

@ -5,4 +5,6 @@ import org.whispersystems.signalservice.api.push.ACI;
public interface AccountFileUpdater {
void updateAccountIdentifiers(String number, ACI aci);
void removeAccount();
}

View file

@ -70,9 +70,11 @@ import java.nio.channels.Channels;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Files;
import java.security.SecureRandom;
import java.sql.SQLException;
import java.util.Base64;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@ -1330,6 +1332,17 @@ public class SignalAccount implements Closeable {
getIdentityKeyStore().setIdentityTrustLevel(recipientId, publicKey, TrustLevel.TRUSTED_VERIFIED);
}
public void deleteAccountData() throws IOException {
close();
try (final var files = Files.walk(getUserPath(dataPath, accountPath).toPath())
.sorted(Comparator.reverseOrder())) {
for (final var file = files.iterator(); file.hasNext(); ) {
Files.delete(file.next());
}
}
Files.delete(getFileName(dataPath, accountPath).toPath());
}
@Override
public void close() {
synchronized (fileChannel) {

View file

@ -104,6 +104,10 @@ public class AccountsStore {
return accountPath;
}
public void removeAccount(final String accountPath) {
updateAccounts(accounts -> accounts.stream().filter(a -> !a.path().equals(accountPath)).toList());
}
private String generateNewAccountPath() {
return new Random().ints(100000, 1000000)
.mapToObj(String::valueOf)