mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Refactor resolve recipient
This commit is contained in:
parent
7ab013cee9
commit
51fef48016
4 changed files with 181 additions and 59 deletions
|
@ -1179,38 +1179,11 @@ public class SignalAccount implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientResolver getRecipientResolver() {
|
public RecipientResolver getRecipientResolver() {
|
||||||
return new RecipientResolver() {
|
return new RecipientResolver.RecipientResolverWrapper(this::getRecipientStore);
|
||||||
@Override
|
|
||||||
public RecipientId resolveRecipient(final RecipientAddress address) {
|
|
||||||
return getRecipientStore().resolveRecipient(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RecipientId resolveRecipient(final long recipientId) {
|
|
||||||
return getRecipientStore().resolveRecipient(recipientId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientTrustedResolver getRecipientTrustedResolver() {
|
public RecipientTrustedResolver getRecipientTrustedResolver() {
|
||||||
return new RecipientTrustedResolver() {
|
return new RecipientTrustedResolver.RecipientTrustedResolverWrapper(this::getRecipientStore);
|
||||||
@Override
|
|
||||||
public RecipientId resolveSelfRecipientTrusted(final RecipientAddress address) {
|
|
||||||
return getRecipientStore().resolveSelfRecipientTrusted(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RecipientId resolveRecipientTrusted(final SignalServiceAddress address) {
|
|
||||||
return getRecipientStore().resolveRecipientTrusted(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RecipientId resolveRecipientTrusted(
|
|
||||||
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
|
|
||||||
) {
|
|
||||||
return getRecipientStore().resolveRecipientTrusted(aci, pni, number);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddressResolver getRecipientAddressResolver() {
|
public RecipientAddressResolver getRecipientAddressResolver() {
|
||||||
|
|
|
@ -1,24 +1,50 @@
|
||||||
package org.asamk.signal.manager.storage.recipients;
|
package org.asamk.signal.manager.storage.recipients;
|
||||||
|
|
||||||
import org.asamk.signal.manager.storage.Utils;
|
|
||||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public interface RecipientResolver {
|
public interface RecipientResolver {
|
||||||
|
|
||||||
RecipientId resolveRecipient(RecipientAddress address);
|
RecipientId resolveRecipient(RecipientAddress address);
|
||||||
|
|
||||||
RecipientId resolveRecipient(long recipientId);
|
RecipientId resolveRecipient(long recipientId);
|
||||||
|
|
||||||
default RecipientId resolveRecipient(String identifier) {
|
RecipientId resolveRecipient(String identifier);
|
||||||
return resolveRecipient(Utils.getRecipientAddressFromIdentifier(identifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
default RecipientId resolveRecipient(SignalServiceAddress address) {
|
default RecipientId resolveRecipient(SignalServiceAddress address) {
|
||||||
return resolveRecipient(new RecipientAddress(address));
|
return resolveRecipient(new RecipientAddress(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
default RecipientId resolveRecipient(ServiceId serviceId) {
|
RecipientId resolveRecipient(ServiceId serviceId);
|
||||||
return resolveRecipient(new RecipientAddress(serviceId));
|
|
||||||
|
class RecipientResolverWrapper implements RecipientResolver {
|
||||||
|
|
||||||
|
private final Supplier<RecipientResolver> recipientResolverSupplier;
|
||||||
|
|
||||||
|
public RecipientResolverWrapper(final Supplier<RecipientResolver> recipientResolverSupplier) {
|
||||||
|
this.recipientResolverSupplier = recipientResolverSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipient(final RecipientAddress address) {
|
||||||
|
return recipientResolverSupplier.get().resolveRecipient(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipient(final long recipientId) {
|
||||||
|
return recipientResolverSupplier.get().resolveRecipient(recipientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipient(final String identifier) {
|
||||||
|
return recipientResolverSupplier.get().resolveRecipient(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipient(final ServiceId serviceId) {
|
||||||
|
return recipientResolverSupplier.get().resolveRecipient(serviceId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,44 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipient(final String identifier) {
|
||||||
|
if (UuidUtil.isUuid(identifier)) {
|
||||||
|
return resolveRecipient(ServiceId.parseOrThrow(identifier));
|
||||||
|
} else {
|
||||||
|
return resolveRecipientByNumber(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecipientId resolveRecipientByNumber(final String number) {
|
||||||
|
synchronized (recipientsLock) {
|
||||||
|
final RecipientId recipientId;
|
||||||
|
try (final var connection = database.getConnection()) {
|
||||||
|
connection.setAutoCommit(false);
|
||||||
|
recipientId = resolveRecipientLocked(connection, number);
|
||||||
|
connection.commit();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("Failed read recipient store", e);
|
||||||
|
}
|
||||||
|
return recipientId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipient(final ServiceId serviceId) {
|
||||||
|
synchronized (recipientsLock) {
|
||||||
|
final RecipientId recipientId;
|
||||||
|
try (final var connection = database.getConnection()) {
|
||||||
|
connection.setAutoCommit(false);
|
||||||
|
recipientId = resolveRecipientLocked(connection, serviceId);
|
||||||
|
connection.commit();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("Failed read recipient store", e);
|
||||||
|
}
|
||||||
|
return recipientId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should only be used for recipientIds from the database.
|
* Should only be used for recipientIds from the database.
|
||||||
* Where the foreign key relations ensure a valid recipientId.
|
* Where the foreign key relations ensure a valid recipientId.
|
||||||
|
@ -170,27 +208,37 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
number));
|
number));
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveRecipient(new RecipientAddress(serviceId, number), false, false);
|
return resolveRecipient(serviceId);
|
||||||
}
|
}
|
||||||
return byNumber.get().id();
|
return byNumber.get().id();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientId resolveRecipient(RecipientAddress address) {
|
public RecipientId resolveRecipient(RecipientAddress address) {
|
||||||
return resolveRecipient(address, false, false);
|
synchronized (recipientsLock) {
|
||||||
|
final RecipientId recipientId;
|
||||||
|
try (final var connection = database.getConnection()) {
|
||||||
|
connection.setAutoCommit(false);
|
||||||
|
recipientId = resolveRecipientLocked(connection, address);
|
||||||
|
connection.commit();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("Failed read recipient store", e);
|
||||||
|
}
|
||||||
|
return recipientId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecipientId resolveSelfRecipientTrusted(RecipientAddress address) {
|
public RecipientId resolveSelfRecipientTrusted(RecipientAddress address) {
|
||||||
return resolveRecipient(address, true, true);
|
return resolveRecipientTrusted(address, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientId resolveRecipientTrusted(RecipientAddress address) {
|
public RecipientId resolveRecipientTrusted(RecipientAddress address) {
|
||||||
return resolveRecipient(address, true, false);
|
return resolveRecipientTrusted(address, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecipientId resolveRecipientTrusted(SignalServiceAddress address) {
|
public RecipientId resolveRecipientTrusted(SignalServiceAddress address) {
|
||||||
return resolveRecipient(new RecipientAddress(address), true, false);
|
return resolveRecipientTrusted(new RecipientAddress(address), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -198,7 +246,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
|
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
|
||||||
) {
|
) {
|
||||||
final var serviceId = aci.map(a -> (ServiceId) a).or(() -> pni);
|
final var serviceId = aci.map(a -> (ServiceId) a).or(() -> pni);
|
||||||
return resolveRecipient(new RecipientAddress(serviceId, number), true, false);
|
return resolveRecipientTrusted(new RecipientAddress(serviceId, number), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -552,16 +600,12 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private RecipientId resolveRecipientTrusted(RecipientAddress address, boolean isSelf) {
|
||||||
* @param isHighTrust true, if the number/uuid connection was obtained from a trusted source.
|
|
||||||
* Has no effect, if the address contains only a number or a uuid.
|
|
||||||
*/
|
|
||||||
private RecipientId resolveRecipient(RecipientAddress address, boolean isHighTrust, boolean isSelf) {
|
|
||||||
final Pair<RecipientId, Optional<RecipientId>> pair;
|
final Pair<RecipientId, Optional<RecipientId>> pair;
|
||||||
synchronized (recipientsLock) {
|
synchronized (recipientsLock) {
|
||||||
try (final var connection = database.getConnection()) {
|
try (final var connection = database.getConnection()) {
|
||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
pair = resolveRecipientLocked(connection, address, isHighTrust, isSelf);
|
pair = resolveRecipientTrustedLocked(connection, address, isSelf);
|
||||||
connection.commit();
|
connection.commit();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException("Failed update recipient store", e);
|
throw new RuntimeException("Failed update recipient store", e);
|
||||||
|
@ -579,12 +623,12 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
return pair.first();
|
return pair.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<RecipientId, Optional<RecipientId>> resolveRecipientLocked(
|
private Pair<RecipientId, Optional<RecipientId>> resolveRecipientTrustedLocked(
|
||||||
Connection connection, RecipientAddress address, boolean isHighTrust, boolean isSelf
|
Connection connection, RecipientAddress address, boolean isSelf
|
||||||
) throws SQLException {
|
) throws SQLException {
|
||||||
if (isHighTrust && !isSelf) {
|
if (!isSelf) {
|
||||||
if (selfAddressProvider.getSelfAddress().matches(address)) {
|
if (selfAddressProvider.getSelfAddress().matches(address)) {
|
||||||
isHighTrust = false;
|
return new Pair<>(resolveRecipientLocked(connection, address), Optional.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final var byNumber = address.number().isEmpty()
|
final var byNumber = address.number().isEmpty()
|
||||||
|
@ -596,16 +640,10 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
|
|
||||||
if (byNumber.isEmpty() && byUuid.isEmpty()) {
|
if (byNumber.isEmpty() && byUuid.isEmpty()) {
|
||||||
logger.debug("Got new recipient, both uuid and number are unknown");
|
logger.debug("Got new recipient, both uuid and number are unknown");
|
||||||
|
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
|
||||||
if (isHighTrust || address.serviceId().isEmpty() || address.number().isEmpty()) {
|
|
||||||
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Pair<>(addNewRecipient(connection, new RecipientAddress(address.serviceId().get())),
|
|
||||||
Optional.empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isHighTrust || address.serviceId().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) {
|
if (address.serviceId().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) {
|
||||||
return new Pair<>(byUuid.or(() -> byNumber).map(RecipientWithAddress::id).get(), Optional.empty());
|
return new Pair<>(byUuid.or(() -> byNumber).map(RecipientWithAddress::id).get(), Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,6 +699,64 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
||||||
return new Pair<>(byUuidRecipient.id(), Optional.of(toBeMergedRecipientId));
|
return new Pair<>(byUuidRecipient.id(), Optional.of(toBeMergedRecipientId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RecipientId resolveRecipientLocked(
|
||||||
|
Connection connection, RecipientAddress address
|
||||||
|
) throws SQLException {
|
||||||
|
final var byServiceId = address.serviceId().isEmpty()
|
||||||
|
? Optional.<RecipientWithAddress>empty()
|
||||||
|
: findByServiceId(connection, address.serviceId().get());
|
||||||
|
|
||||||
|
if (byServiceId.isPresent()) {
|
||||||
|
return byServiceId.get().id();
|
||||||
|
}
|
||||||
|
|
||||||
|
final var byPni = address.pni().isEmpty()
|
||||||
|
? Optional.<RecipientWithAddress>empty()
|
||||||
|
: findByServiceId(connection, address.pni().get());
|
||||||
|
|
||||||
|
if (byPni.isPresent()) {
|
||||||
|
return byPni.get().id();
|
||||||
|
}
|
||||||
|
|
||||||
|
final var byNumber = address.number().isEmpty()
|
||||||
|
? Optional.<RecipientWithAddress>empty()
|
||||||
|
: findByNumber(connection, address.number().get());
|
||||||
|
|
||||||
|
if (byNumber.isPresent()) {
|
||||||
|
return byNumber.get().id();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Got new recipient, both serviceId and number are unknown");
|
||||||
|
|
||||||
|
if (address.serviceId().isEmpty()) {
|
||||||
|
return addNewRecipient(connection, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return addNewRecipient(connection, new RecipientAddress(address.serviceId().get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecipientId resolveRecipientLocked(Connection connection, ServiceId serviceId) throws SQLException {
|
||||||
|
final var recipient = findByServiceId(connection, serviceId);
|
||||||
|
|
||||||
|
if (recipient.isEmpty()) {
|
||||||
|
logger.debug("Got new recipient, serviceId is unknown");
|
||||||
|
return addNewRecipient(connection, new RecipientAddress(serviceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipient.get().id();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecipientId resolveRecipientLocked(Connection connection, String number) throws SQLException {
|
||||||
|
final var recipient = findByNumber(connection, number);
|
||||||
|
|
||||||
|
if (recipient.isEmpty()) {
|
||||||
|
logger.debug("Got new recipient, number is unknown");
|
||||||
|
return addNewRecipient(connection, new RecipientAddress(null, number));
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipient.get().id();
|
||||||
|
}
|
||||||
|
|
||||||
private RecipientId addNewRecipient(
|
private RecipientId addNewRecipient(
|
||||||
final Connection connection, final RecipientAddress address
|
final Connection connection, final RecipientAddress address
|
||||||
) throws SQLException {
|
) throws SQLException {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.whispersystems.signalservice.api.push.PNI;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public interface RecipientTrustedResolver {
|
public interface RecipientTrustedResolver {
|
||||||
|
|
||||||
|
@ -13,4 +14,30 @@ public interface RecipientTrustedResolver {
|
||||||
RecipientId resolveRecipientTrusted(SignalServiceAddress address);
|
RecipientId resolveRecipientTrusted(SignalServiceAddress address);
|
||||||
|
|
||||||
RecipientId resolveRecipientTrusted(Optional<ACI> aci, Optional<PNI> pni, Optional<String> number);
|
RecipientId resolveRecipientTrusted(Optional<ACI> aci, Optional<PNI> pni, Optional<String> number);
|
||||||
|
|
||||||
|
class RecipientTrustedResolverWrapper implements RecipientTrustedResolver {
|
||||||
|
|
||||||
|
private final Supplier<RecipientTrustedResolver> recipientTrustedResolverSupplier;
|
||||||
|
|
||||||
|
public RecipientTrustedResolverWrapper(final Supplier<RecipientTrustedResolver> recipientTrustedResolverSupplier) {
|
||||||
|
this.recipientTrustedResolverSupplier = recipientTrustedResolverSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveSelfRecipientTrusted(final RecipientAddress address) {
|
||||||
|
return recipientTrustedResolverSupplier.get().resolveSelfRecipientTrusted(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipientTrusted(final SignalServiceAddress address) {
|
||||||
|
return recipientTrustedResolverSupplier.get().resolveRecipientTrusted(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientId resolveRecipientTrusted(
|
||||||
|
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
|
||||||
|
) {
|
||||||
|
return recipientTrustedResolverSupplier.get().resolveRecipientTrusted(aci, pni, number);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue