Include unregistered users in blocked sync message.

This commit is contained in:
Greyson Parrelli
2024-11-14 11:31:30 -05:00
parent 0f4caa3dc1
commit b4472833b8
8 changed files with 110 additions and 159 deletions

View File

@@ -9,6 +9,7 @@ import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.RecipientRecord;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.recipients.Recipient;
@@ -19,6 +20,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
class BlockedUsersRepository {
@@ -32,19 +34,11 @@ class BlockedUsersRepository {
void getBlocked(@NonNull Consumer<List<Recipient>> blockedUsers) {
SignalExecutors.BOUNDED.execute(() -> {
RecipientTable db = SignalDatabase.recipients();
try (RecipientTable.RecipientReader reader = db.readerForBlocked(db.getBlocked())) {
int count = reader.getCount();
if (count == 0) {
blockedUsers.accept(Collections.emptyList());
} else {
List<Recipient> recipients = new ArrayList<>();
while (reader.getNext() != null) {
recipients.add(reader.getCurrent());
}
blockedUsers.accept(recipients);
}
}
List<RecipientRecord> records = SignalDatabase.recipients().getBlocked();
List<Recipient> recipients = records.stream()
.map((record) -> Recipient.resolved(record.getId()))
.collect(Collectors.toList());
blockedUsers.accept(recipients);
});
}

View File

@@ -18,7 +18,7 @@ class PrivacySettingsRepository {
SignalExecutors.BOUNDED.execute {
val recipientDatabase = SignalDatabase.recipients
consumer(recipientDatabase.getBlocked().count)
consumer(recipientDatabase.getBlocked().size)
}
}

View File

@@ -709,8 +709,13 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
}
fun getBlocked(): Cursor {
return readableDatabase.query(TABLE_NAME, ID_PROJECTION, "$BLOCKED = 1", null, null, null, null)
fun getBlocked(): List<RecipientRecord> {
return readableDatabase
.select()
.from(TABLE_NAME)
.where("$BLOCKED = 1")
.run()
.readToList { RecipientTableCursorUtil.getRecord(context, it) }
}
fun readerForBlocked(cursor: Cursor): RecipientReader {

View File

@@ -1,113 +0,0 @@
package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.RecipientTable.RecipientReader;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MultiDeviceBlockedUpdateJob extends BaseJob {
public static final String KEY = "MultiDeviceBlockedUpdateJob";
@SuppressWarnings("unused")
private static final String TAG = Log.tag(MultiDeviceBlockedUpdateJob.class);
public MultiDeviceBlockedUpdateJob() {
this(new Job.Parameters.Builder()
.addConstraint(NetworkConstraint.KEY)
.setQueue("MultiDeviceBlockedUpdateJob")
.setLifespan(TimeUnit.DAYS.toMillis(1))
.setMaxAttempts(Parameters.UNLIMITED)
.build());
}
private MultiDeviceBlockedUpdateJob(@NonNull Job.Parameters parameters) {
super(parameters);
}
@Override
public @Nullable byte[] serialize() {
return null;
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onRun()
throws IOException, UntrustedIdentityException
{
if (!Recipient.self().isRegistered()) {
throw new NotPushRegisteredException();
}
if (!SignalStore.account().hasLinkedDevices()) {
Log.i(TAG, "Not multi device, aborting...");
return;
}
RecipientTable database = SignalDatabase.recipients();
try (RecipientReader reader = database.readerForBlocked(database.getBlocked())) {
List<SignalServiceAddress> blockedIndividuals = new LinkedList<>();
List<byte[]> blockedGroups = new LinkedList<>();
Recipient recipient;
while ((recipient = reader.getNext()) != null) {
if (recipient.isPushGroup()) {
blockedGroups.add(recipient.requireGroupId().getDecodedId());
} else if (recipient.isMaybeRegistered() && (recipient.getHasServiceId() || recipient.getHasE164())) {
blockedIndividuals.add(RecipientUtil.toSignalServiceAddress(context, recipient));
}
}
SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender();
messageSender.sendSyncMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blockedIndividuals, blockedGroups))
);
}
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
if (exception instanceof ServerRejectedException) return false;
if (exception instanceof PushNetworkException) return true;
return false;
}
@Override
public void onFailure() {
}
public static final class Factory implements Job.Factory<MultiDeviceBlockedUpdateJob> {
@Override
public @NonNull MultiDeviceBlockedUpdateJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {
return new MultiDeviceBlockedUpdateJob(parameters);
}
}
}

View File

@@ -0,0 +1,75 @@
package org.thoughtcrime.securesms.jobs
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.RecipientRecord
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.net.NotPushRegisteredException
import org.thoughtcrime.securesms.recipients.Recipient
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException
import java.io.IOException
import java.util.concurrent.TimeUnit
class MultiDeviceBlockedUpdateJob private constructor(parameters: Parameters) : BaseJob(parameters) {
companion object {
const val KEY: String = "MultiDeviceBlockedUpdateJob"
private val TAG = Log.tag(MultiDeviceBlockedUpdateJob::class.java)
}
constructor() : this(
Parameters.Builder()
.addConstraint(NetworkConstraint.KEY)
.setQueue("MultiDeviceBlockedUpdateJob")
.setLifespan(TimeUnit.DAYS.toMillis(1))
.setMaxAttempts(Parameters.UNLIMITED)
.build()
)
override fun serialize(): ByteArray? = null
override fun getFactoryKey(): String = KEY
@Throws(IOException::class, UntrustedIdentityException::class)
public override fun onRun() {
if (!Recipient.self().isRegistered) {
throw NotPushRegisteredException()
}
if (!SignalStore.account.hasLinkedDevices) {
Log.i(TAG, "Not multi device, aborting...")
return
}
val blocked: List<RecipientRecord> = SignalDatabase.recipients.getBlocked()
val blockedGroups = blocked.mapNotNull { it.groupId?.decodedId }
val blockedIndividuals = blocked
.filter { it.aci != null || it.e164 != null }
.map { BlockedListMessage.Individual(it.aci, it.e164) }
AppDependencies.signalServiceMessageSender.sendSyncMessage(
SignalServiceSyncMessage.forBlocked(BlockedListMessage(blockedIndividuals, blockedGroups))
)
}
public override fun onShouldRetry(exception: Exception): Boolean {
if (exception is ServerRejectedException) return false
if (exception is PushNetworkException) return true
return false
}
override fun onFailure() = Unit
class Factory : Job.Factory<MultiDeviceBlockedUpdateJob?> {
override fun create(parameters: Parameters, serializedData: ByteArray?): MultiDeviceBlockedUpdateJob {
return MultiDeviceBlockedUpdateJob(parameters)
}
}
}