Displace client presence when existing account reregisters
This commit is contained in:
parent
f6c4ba898b
commit
c309afc04b
|
@ -33,11 +33,14 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.LongStream;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.textsecuregcm.redis.ClusterLuaScript;
|
import org.whispersystems.textsecuregcm.redis.ClusterLuaScript;
|
||||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantPubSubConnection;
|
import org.whispersystems.textsecuregcm.redis.FaultTolerantPubSubConnection;
|
||||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||||
|
import org.whispersystems.textsecuregcm.storage.Device;
|
||||||
import org.whispersystems.textsecuregcm.util.Constants;
|
import org.whispersystems.textsecuregcm.util.Constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,6 +201,10 @@ public class ClientPresenceManager extends RedisClusterPubSubAdapter<String, Str
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void disconnectAllPresencesForUuid(final UUID accountUuid) {
|
||||||
|
disconnectAllPresences(accountUuid, Device.ALL_POSSIBLE_DEVICE_IDS);
|
||||||
|
}
|
||||||
|
|
||||||
public void disconnectPresence(final UUID accountUuid, final long deviceId) {
|
public void disconnectPresence(final UUID accountUuid, final long deviceId) {
|
||||||
disconnectAllPresences(accountUuid, List.of(deviceId));
|
disconnectAllPresences(accountUuid, List.of(deviceId));
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,7 @@ public class AccountsManager {
|
||||||
keys.delete(actualUuid);
|
keys.delete(actualUuid);
|
||||||
keys.delete(account.getPhoneNumberIdentifier());
|
keys.delete(account.getPhoneNumberIdentifier());
|
||||||
profilesManager.deleteAll(actualUuid);
|
profilesManager.deleteAll(actualUuid);
|
||||||
|
clientPresenceManager.disconnectAllPresencesForUuid(actualUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Tags tags;
|
final Tags tags;
|
||||||
|
|
|
@ -6,8 +6,11 @@ package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import java.util.List;
|
||||||
import java.util.OptionalInt;
|
import java.util.OptionalInt;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.LongStream;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.whispersystems.textsecuregcm.auth.SaltedTokenHash;
|
import org.whispersystems.textsecuregcm.auth.SaltedTokenHash;
|
||||||
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
|
@ -16,6 +19,8 @@ import org.whispersystems.textsecuregcm.util.Util;
|
||||||
public class Device {
|
public class Device {
|
||||||
|
|
||||||
public static final long MASTER_ID = 1;
|
public static final long MASTER_ID = 1;
|
||||||
|
public static final int MAXIMUM_DEVICE_ID = 256;
|
||||||
|
public static final List<Long> ALL_POSSIBLE_DEVICE_IDS = LongStream.range(1, MAXIMUM_DEVICE_ID).boxed().collect(Collectors.toList());
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private long id;
|
private long id;
|
||||||
|
|
|
@ -332,7 +332,7 @@ public class MessagesCache extends RedisClusterPubSubAdapter<String, String> imp
|
||||||
public void clear(final UUID destinationUuid) {
|
public void clear(final UUID destinationUuid) {
|
||||||
// TODO Remove null check in a fully UUID-based world
|
// TODO Remove null check in a fully UUID-based world
|
||||||
if (destinationUuid != null) {
|
if (destinationUuid != null) {
|
||||||
for (int i = 1; i < 256; i++) {
|
for (int i = 1; i < Device.MAXIMUM_DEVICE_ID; i++) {
|
||||||
clear(destinationUuid, i);
|
clear(destinationUuid, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ class AccountsManagerTest {
|
||||||
private Keys keys;
|
private Keys keys;
|
||||||
private MessagesManager messagesManager;
|
private MessagesManager messagesManager;
|
||||||
private ProfilesManager profilesManager;
|
private ProfilesManager profilesManager;
|
||||||
|
private ClientPresenceManager clientPresenceManager;
|
||||||
private ExperimentEnrollmentManager enrollmentManager;
|
private ExperimentEnrollmentManager enrollmentManager;
|
||||||
|
|
||||||
private Map<String, UUID> phoneNumberIdentifiersByE164;
|
private Map<String, UUID> phoneNumberIdentifiersByE164;
|
||||||
|
@ -95,6 +96,7 @@ class AccountsManagerTest {
|
||||||
keys = mock(Keys.class);
|
keys = mock(Keys.class);
|
||||||
messagesManager = mock(MessagesManager.class);
|
messagesManager = mock(MessagesManager.class);
|
||||||
profilesManager = mock(ProfilesManager.class);
|
profilesManager = mock(ProfilesManager.class);
|
||||||
|
clientPresenceManager = mock(ClientPresenceManager.class);
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
commands = mock(RedisAdvancedClusterCommands.class);
|
commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
|
@ -155,7 +157,7 @@ class AccountsManagerTest {
|
||||||
storageClient,
|
storageClient,
|
||||||
backupClient,
|
backupClient,
|
||||||
svr2Client,
|
svr2Client,
|
||||||
mock(ClientPresenceManager.class),
|
clientPresenceManager,
|
||||||
enrollmentManager,
|
enrollmentManager,
|
||||||
mock(RegistrationRecoveryPasswordsManager.class),
|
mock(RegistrationRecoveryPasswordsManager.class),
|
||||||
mock(Clock.class));
|
mock(Clock.class));
|
||||||
|
@ -560,6 +562,7 @@ class AccountsManagerTest {
|
||||||
verify(keys).delete(phoneNumberIdentifiersByE164.get(e164));
|
verify(keys).delete(phoneNumberIdentifiersByE164.get(e164));
|
||||||
verify(messagesManager).clear(existingUuid);
|
verify(messagesManager).clear(existingUuid);
|
||||||
verify(profilesManager).deleteAll(existingUuid);
|
verify(profilesManager).deleteAll(existingUuid);
|
||||||
|
verify(clientPresenceManager).disconnectAllPresencesForUuid(existingUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue