Add support for resending badly-encrypted stories.
This commit is contained in:
parent
7873ec2b67
commit
c6be427883
11 changed files with 288 additions and 71 deletions
|
@ -320,7 +320,19 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
|||
}
|
||||
|
||||
fun getList(listId: DistributionListId): DistributionListRecord? {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, null, "${ListTable.ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(listId), null, null, null).use { cursor ->
|
||||
return getListByQuery("${ListTable.ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(listId))
|
||||
}
|
||||
|
||||
fun getList(recipientId: RecipientId): DistributionListRecord? {
|
||||
return getListByQuery("${ListTable.RECIPIENT_ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(recipientId))
|
||||
}
|
||||
|
||||
fun getListByDistributionId(distributionId: DistributionId): DistributionListRecord? {
|
||||
return getListByQuery("${ListTable.DISTRIBUTION_ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(distributionId))
|
||||
}
|
||||
|
||||
private fun getListByQuery(query: String, args: Array<String>): DistributionListRecord? {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, null, query, args, null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
val id: DistributionListId = DistributionListId.from(cursor.requireLong(ListTable.ID))
|
||||
val privacyMode: DistributionListPrivacyMode = cursor.requireObject(ListTable.PRIVACY_MODE, DistributionListPrivacyMode.Serializer)
|
||||
|
@ -393,6 +405,16 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
|||
}
|
||||
}
|
||||
|
||||
fun getDistributionId(recipientId: RecipientId): DistributionId? {
|
||||
readableDatabase.query(ListTable.TABLE_NAME, arrayOf(ListTable.DISTRIBUTION_ID), "${ListTable.RECIPIENT_ID} = ? AND ${ListTable.IS_NOT_DELETED}", SqlUtil.buildArgs(recipientId), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
DistributionId.from(cursor.requireString(ListTable.DISTRIBUTION_ID))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMembers(listId: DistributionListId): List<RecipientId> {
|
||||
lateinit var privacyMode: DistributionListPrivacyMode
|
||||
lateinit var rawMembers: List<RecipientId>
|
||||
|
|
|
@ -44,7 +44,7 @@ public class JobManager implements ConstraintObserver.Notifier {
|
|||
|
||||
private static final String TAG = Log.tag(JobManager.class);
|
||||
|
||||
public static final int CURRENT_VERSION = 8;
|
||||
public static final int CURRENT_VERSION = 9;
|
||||
|
||||
private final Application application;
|
||||
private final Configuration configuration;
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package org.thoughtcrime.securesms.jobmanager.migrations;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobMigration;
|
||||
import org.thoughtcrime.securesms.jobs.FailingJob;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* We removed the messageId property from the job data and replaced it with a serialized envelope,
|
||||
* so we need to take jobs that referenced an ID and replace it with the envelope instead.
|
||||
*/
|
||||
public class SenderKeyDistributionSendJobRecipientMigration extends JobMigration {
|
||||
|
||||
private static final String TAG = Log.tag(SenderKeyDistributionSendJobRecipientMigration.class);
|
||||
|
||||
private final GroupDatabase groupDatabase;
|
||||
|
||||
public SenderKeyDistributionSendJobRecipientMigration() {
|
||||
this(SignalDatabase.groups());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
SenderKeyDistributionSendJobRecipientMigration(GroupDatabase groupDatabase) {
|
||||
super(9);
|
||||
this.groupDatabase = groupDatabase;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull JobData migrate(@NonNull JobData jobData) {
|
||||
if ("SenderKeyDistributionSendJob".equals(jobData.getFactoryKey())) {
|
||||
return migrateJob(jobData, groupDatabase);
|
||||
} else {
|
||||
return jobData;
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull JobData migrateJob(@NonNull JobData jobData, @NonNull GroupDatabase groupDatabase) {
|
||||
Data data = jobData.getData();
|
||||
|
||||
if (data.hasString("group_id")) {
|
||||
GroupId groupId = GroupId.pushOrThrow(data.getStringAsBlob("group_id"));
|
||||
Optional<GroupRecord> group = groupDatabase.getGroup(groupId);
|
||||
|
||||
if (group.isPresent()) {
|
||||
return jobData.withData(data.buildUpon()
|
||||
.putString("thread_recipient_id", group.get().getRecipientId().serialize())
|
||||
.build());
|
||||
|
||||
} else {
|
||||
return jobData.withFactoryKey(FailingJob.KEY);
|
||||
}
|
||||
} else if (!data.hasString("thread_recipient_id")) {
|
||||
return jobData.withFactoryKey(FailingJob.KEY);
|
||||
} else {
|
||||
return jobData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdFollowUpJobMi
|
|||
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdJobMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.RetrieveProfileJobMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.SendReadReceiptsJobMigration;
|
||||
import org.thoughtcrime.securesms.jobmanager.migrations.SenderKeyDistributionSendJobRecipientMigration;
|
||||
import org.thoughtcrime.securesms.migrations.AccountRecordMigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.ApplyUnknownFieldsToSelfMigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.AttachmentCleanupMigrationJob;
|
||||
|
@ -272,6 +273,7 @@ public final class JobManagerFactories {
|
|||
new SendReadReceiptsJobMigration(SignalDatabase.mmsSms()),
|
||||
new PushProcessMessageQueueJobMigration(application),
|
||||
new RetrieveProfileJobMigration(),
|
||||
new PushDecryptMessageJobEnvelopeMigration(application));
|
||||
new PushDecryptMessageJobEnvelopeMigration(application),
|
||||
new SenderKeyDistributionSendJobRecipientMigration());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage;
|
|||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
|
@ -143,14 +144,28 @@ public class ResendMessageJob extends BaseJob {
|
|||
Content contentToSend = content;
|
||||
|
||||
if (distributionId != null) {
|
||||
Optional<GroupRecord> groupRecord = SignalDatabase.groups().getGroupByDistributionId(distributionId);
|
||||
if (groupId != null) {
|
||||
Log.d(TAG, "GroupId is present. Assuming this is a group message.");
|
||||
Optional<GroupRecord> groupRecord = SignalDatabase.groups().getGroupByDistributionId(distributionId);
|
||||
|
||||
if (!groupRecord.isPresent()) {
|
||||
Log.w(TAG, "Could not find a matching group for the distributionId! Skipping message send.");
|
||||
return;
|
||||
} else if (!groupRecord.get().getMembers().contains(recipientId)) {
|
||||
Log.w(TAG, "The target user is no longer in the group! Skipping message send.");
|
||||
return;
|
||||
if (!groupRecord.isPresent()) {
|
||||
Log.w(TAG, "Could not find a matching group for the distributionId! Skipping message send.");
|
||||
return;
|
||||
} else if (!groupRecord.get().getMembers().contains(recipientId)) {
|
||||
Log.w(TAG, "The target user is no longer in the group! Skipping message send.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "GroupId is not present. Assuming this is a message for a distribution list.");
|
||||
DistributionListRecord listRecord = SignalDatabase.distributionLists().getListByDistributionId(distributionId);
|
||||
|
||||
if (listRecord == null) {
|
||||
Log.w(TAG, "Could not find a matching distribution list for the distributionId! Skipping message send.");
|
||||
return;
|
||||
} else if (!listRecord.getMembers().contains(recipientId)) {
|
||||
Log.w(TAG, "The target user is no longer in the distribution list! Skipping message send.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SenderKeyDistributionMessage senderKeyDistributionMessage = messageSender.getOrCreateNewGroupSession(distributionId);
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.signal.core.util.logging.Log;
|
|||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
|
@ -39,33 +39,33 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
|||
|
||||
public static final String KEY = "SenderKeyDistributionSendJob";
|
||||
|
||||
private static final String KEY_RECIPIENT_ID = "recipient_id";
|
||||
private static final String KEY_GROUP_ID = "group_id";
|
||||
private static final String KEY_TARGET_RECIPIENT_ID = "recipient_id";
|
||||
private static final String KEY_THREAD_RECIPIENT_ID = "thread_recipient_id";
|
||||
|
||||
private final RecipientId recipientId;
|
||||
private final GroupId.V2 groupId;
|
||||
private final RecipientId targetRecipientId;
|
||||
private final RecipientId threadRecipientId;
|
||||
|
||||
public SenderKeyDistributionSendJob(@NonNull RecipientId recipientId, @NonNull GroupId.V2 groupId) {
|
||||
this(recipientId, groupId, new Parameters.Builder()
|
||||
.setQueue(recipientId.toQueueKey())
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(Parameters.UNLIMITED)
|
||||
.setMaxInstancesForQueue(1)
|
||||
.build());
|
||||
public SenderKeyDistributionSendJob(@NonNull RecipientId targetRecipientId, RecipientId threadRecipientId) {
|
||||
this(targetRecipientId, threadRecipientId, new Parameters.Builder()
|
||||
.setQueue(targetRecipientId.toQueueKey())
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(Parameters.UNLIMITED)
|
||||
.setMaxInstancesForQueue(1)
|
||||
.build());
|
||||
}
|
||||
|
||||
private SenderKeyDistributionSendJob(@NonNull RecipientId recipientId, @NonNull GroupId.V2 groupId, @NonNull Parameters parameters) {
|
||||
private SenderKeyDistributionSendJob(@NonNull RecipientId targetRecipientId, @NonNull RecipientId threadRecipientId, @NonNull Parameters parameters) {
|
||||
super(parameters);
|
||||
|
||||
this.recipientId = recipientId;
|
||||
this.groupId = groupId;
|
||||
this.targetRecipientId = targetRecipientId;
|
||||
this.threadRecipientId = threadRecipientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Data serialize() {
|
||||
return new Data.Builder().putString(KEY_RECIPIENT_ID, recipientId.serialize())
|
||||
.putBlobAsString(KEY_GROUP_ID, groupId.getDecodedId())
|
||||
return new Data.Builder().putString(KEY_TARGET_RECIPIENT_ID, targetRecipientId.serialize())
|
||||
.putString(KEY_THREAD_RECIPIENT_ID, threadRecipientId.serialize())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -76,38 +76,62 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
|||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
GroupDatabase groupDatabase = SignalDatabase.groups();
|
||||
Recipient targetRecipient = Recipient.resolved(targetRecipientId);
|
||||
Recipient threadRecipient = Recipient.resolved(threadRecipientId);
|
||||
|
||||
if (!groupDatabase.isCurrentMember(groupId, recipientId)) {
|
||||
Log.w(TAG, recipientId + " is no longer a member of " + groupId + "! Not sending.");
|
||||
if (targetRecipient.getSenderKeyCapability() != Recipient.Capability.SUPPORTED) {
|
||||
Log.w(TAG, targetRecipientId + " does not support sender key! Not sending.");
|
||||
return;
|
||||
}
|
||||
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
|
||||
if (recipient.getSenderKeyCapability() != Recipient.Capability.SUPPORTED) {
|
||||
Log.w(TAG, recipientId + " does not support sender key! Not sending.");
|
||||
if (targetRecipient.isUnregistered()) {
|
||||
Log.w(TAG, threadRecipient.getId() + " not registered!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (recipient.isUnregistered()) {
|
||||
Log.w(TAG, recipient.getId() + " not registered!");
|
||||
GroupId.V2 groupId;
|
||||
DistributionId distributionId;
|
||||
|
||||
if (threadRecipient.isPushV2Group()) {
|
||||
groupId = threadRecipient.requireGroupId().requireV2();
|
||||
distributionId = SignalDatabase.groups().getOrCreateDistributionId(groupId);
|
||||
} else if (threadRecipient.isDistributionList()) {
|
||||
groupId = null;
|
||||
distributionId = SignalDatabase.distributionLists().getDistributionId(threadRecipientId);
|
||||
} else {
|
||||
warn(TAG, "Recipient is not a group or distribution list! Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (distributionId == null) {
|
||||
warn(TAG, "Failed to find a distributionId! Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (groupId != null && !SignalDatabase.groups().isCurrentMember(groupId, targetRecipientId)) {
|
||||
Log.w(TAG, targetRecipientId + " is no longer a member of " + groupId + "! Not sending.");
|
||||
return;
|
||||
} else if (groupId == null) {
|
||||
DistributionListRecord listRecord = SignalDatabase.distributionLists().getList(threadRecipientId);
|
||||
|
||||
if (listRecord == null || !listRecord.getMembers().contains(targetRecipientId)) {
|
||||
Log.w(TAG, targetRecipientId + " is no longer a member of the distribution list! Not sending.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
||||
List<SignalServiceAddress> address = Collections.singletonList(RecipientUtil.toSignalServiceAddress(context, recipient));
|
||||
DistributionId distributionId = groupDatabase.getOrCreateDistributionId(groupId);
|
||||
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
|
||||
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
|
||||
List<SignalServiceAddress> address = Collections.singletonList(RecipientUtil.toSignalServiceAddress(context, targetRecipient));
|
||||
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
|
||||
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(targetRecipient));
|
||||
|
||||
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId()), false).get(0);
|
||||
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.ofNullable(groupId).map(GroupId::getDecodedId), false).get(0);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||
.getDevices()
|
||||
.stream()
|
||||
.map(device -> recipient.requireServiceId().toProtocolAddress(device))
|
||||
.map(device -> targetRecipient.requireServiceId().toProtocolAddress(device))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
|
||||
|
@ -128,8 +152,8 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
|||
|
||||
@Override
|
||||
public @NonNull SenderKeyDistributionSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||
return new SenderKeyDistributionSendJob(RecipientId.from(data.getString(KEY_RECIPIENT_ID)),
|
||||
GroupId.pushOrThrow(data.getStringAsBlob(KEY_GROUP_ID)).requireV2(),
|
||||
return new SenderKeyDistributionSendJob(RecipientId.from(data.getString(KEY_TARGET_RECIPIENT_ID)),
|
||||
RecipientId.from(data.getString(KEY_THREAD_RECIPIENT_ID)),
|
||||
parameters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -673,7 +673,7 @@ public final class GroupSendUtil {
|
|||
|
||||
@Override
|
||||
public @NonNull ContentHint getContentHint() {
|
||||
return ContentHint.RESENDABLE;
|
||||
return ContentHint.IMPLICIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.database.SentStorySyncManifest;
|
|||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.StickerDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.database.model.MessageId;
|
||||
import org.thoughtcrime.securesms.database.model.MessageLogEntry;
|
||||
|
@ -2683,13 +2684,27 @@ public final class MessageContentProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!threadRecipient.isPushV2Group()) {
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] Thread recipient is not a v2 group! Skipping.");
|
||||
if (!threadRecipient.isPushV2Group() && !threadRecipient.isDistributionList()) {
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] Thread recipient is not a V2 group or distribution list! Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
DistributionId distributionId;
|
||||
GroupId.V2 groupId;
|
||||
|
||||
if (threadRecipient.isGroup()) {
|
||||
groupId = threadRecipient.requireGroupId().requireV2();
|
||||
distributionId = SignalDatabase.groups().getOrCreateDistributionId(groupId);
|
||||
} else {
|
||||
groupId = null;
|
||||
distributionId = SignalDatabase.distributionLists().getDistributionId(threadRecipient.getId());
|
||||
}
|
||||
|
||||
if (distributionId == null) {
|
||||
Log.w(TAG, "[RetryReceipt-SK] Failed to find a distributionId! Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
GroupId.V2 groupId = threadRecipient.requireGroupId().requireV2();
|
||||
DistributionId distributionId = SignalDatabase.groups().getOrCreateDistributionId(groupId);
|
||||
SignalProtocolAddress requesterAddress = new SignalProtocolAddress(requester.requireServiceId().toString(), content.getSenderDevice());
|
||||
|
||||
SignalDatabase.senderKeyShared().delete(distributionId, Collections.singleton(requesterAddress));
|
||||
|
@ -2705,22 +2720,8 @@ public final class MessageContentProcessor {
|
|||
groupId,
|
||||
distributionId));
|
||||
} else {
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] Unable to find MSL entry for " + requester.getId() + " (" + requesterAddress + ") with timestamp " + sentTimestamp + ".");
|
||||
|
||||
Optional<GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupId);
|
||||
|
||||
if (!groupRecord.isPresent()) {
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] Could not find a record for the group!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!groupRecord.get().getMembers().contains(requester.getId())) {
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] The requester is not in the group, so we cannot send them a SenderKeyDistributionMessage.");
|
||||
return;
|
||||
}
|
||||
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] The requester is in the group, so we'll send them a SenderKeyDistributionMessage.");
|
||||
ApplicationDependencies.getJobManager().add(new SenderKeyDistributionSendJob(requester.getId(), groupRecord.get().getId().requireV2()));
|
||||
warn(content.getTimestamp(), "[RetryReceipt-SK] Unable to find MSL entry for " + requester.getId() + " (" + requesterAddress + ") with timestamp " + sentTimestamp + " for " + (groupId != null ? "group " + groupId : "distribution list") + ". Scheduling a job to send them the SenderKeyDistributionMessage. Membership will be checked there.");
|
||||
ApplicationDependencies.getJobManager().add(new SenderKeyDistributionSendJob(requester.getId(), threadRecipient.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package org.thoughtcrime.securesms.jobmanager.migrations;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobMigration;
|
||||
import org.thoughtcrime.securesms.jobs.FailingJob;
|
||||
import org.thoughtcrime.securesms.jobs.SendReadReceiptJob;
|
||||
import org.thoughtcrime.securesms.jobs.SenderKeyDistributionSendJob;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SenderKeyDistributionSendJobRecipientMigrationTest {
|
||||
|
||||
private final GroupDatabase mockDatabase = mock(GroupDatabase.class);
|
||||
private final SenderKeyDistributionSendJobRecipientMigration testSubject = new SenderKeyDistributionSendJobRecipientMigration(mockDatabase);
|
||||
|
||||
private static final GroupId GROUP_ID = GroupId.pushOrThrow(Util.getSecretBytes(32));
|
||||
|
||||
@Test
|
||||
public void normalMigration() {
|
||||
// GIVEN
|
||||
JobMigration.JobData jobData = new JobMigration.JobData(SenderKeyDistributionSendJob.KEY,
|
||||
"asdf",
|
||||
new Data.Builder()
|
||||
.putString("recipient_id", RecipientId.from(1).serialize())
|
||||
.putBlobAsString("group_id", GROUP_ID.getDecodedId())
|
||||
.build());
|
||||
|
||||
GroupDatabase.GroupRecord mockGroup = mock(GroupDatabase.GroupRecord.class);
|
||||
when(mockGroup.getRecipientId()).thenReturn(RecipientId.from(2));
|
||||
when(mockDatabase.getGroup(GROUP_ID)).thenReturn(Optional.of(mockGroup));
|
||||
|
||||
// WHEN
|
||||
JobMigration.JobData result = testSubject.migrate(jobData);
|
||||
|
||||
// THEN
|
||||
assertEquals(RecipientId.from(1).serialize(), result.getData().getString("recipient_id"));
|
||||
assertEquals(RecipientId.from(2).serialize(), result.getData().getString("thread_recipient_id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotFindGroup() {
|
||||
// GIVEN
|
||||
JobMigration.JobData jobData = new JobMigration.JobData(SenderKeyDistributionSendJob.KEY,
|
||||
"asdf",
|
||||
new Data.Builder()
|
||||
.putString("recipient_id", RecipientId.from(1).serialize())
|
||||
.putBlobAsString("group_id", GROUP_ID.getDecodedId())
|
||||
.build());
|
||||
|
||||
// WHEN
|
||||
JobMigration.JobData result = testSubject.migrate(jobData);
|
||||
|
||||
// THEN
|
||||
assertEquals(FailingJob.KEY, result.getFactoryKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingGroupId() {
|
||||
// GIVEN
|
||||
JobMigration.JobData jobData = new JobMigration.JobData(SenderKeyDistributionSendJob.KEY,
|
||||
"asdf",
|
||||
new Data.Builder()
|
||||
.putString("recipient_id", RecipientId.from(1).serialize())
|
||||
.build());
|
||||
|
||||
// WHEN
|
||||
JobMigration.JobData result = testSubject.migrate(jobData);
|
||||
|
||||
// THEN
|
||||
assertEquals(FailingJob.KEY, result.getFactoryKey());
|
||||
}
|
||||
}
|
|
@ -1745,7 +1745,7 @@ public class SignalServiceMessageSender {
|
|||
if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
|
||||
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
|
||||
} else if (content.getContent().isPresent() && content.getContent().get().hasSenderKeyDistributionMessage()) {
|
||||
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a SKDM to " + messages.getDestination() + " for devices: " + messages.getDevices());
|
||||
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a SKDM to " + messages.getDestination() + " for devices: " + messages.getDevices() + (content.getContent().get().getDataMessage() != null ? " (it's piggy-backing on a DataMessage)" : ""));
|
||||
}
|
||||
|
||||
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
|
||||
|
|
|
@ -560,8 +560,8 @@ public final class SignalServiceContent {
|
|||
metadata.getGroupId(),
|
||||
metadata.getDestinationUuid(),
|
||||
serviceContentProto);
|
||||
} else if (senderKeyDistributionMessage.isPresent()) {
|
||||
return new SignalServiceContent(senderKeyDistributionMessage.get(),
|
||||
} else if (message.hasStoryMessage()) {
|
||||
return new SignalServiceContent(createStoryMessage(message.getStoryMessage()),
|
||||
metadata.getSender(),
|
||||
metadata.getSenderDevice(),
|
||||
metadata.getTimestamp(),
|
||||
|
@ -572,8 +572,9 @@ public final class SignalServiceContent {
|
|||
metadata.getGroupId(),
|
||||
metadata.getDestinationUuid(),
|
||||
serviceContentProto);
|
||||
} else if (message.hasStoryMessage()) {
|
||||
return new SignalServiceContent(createStoryMessage(message.getStoryMessage()),
|
||||
} else if (senderKeyDistributionMessage.isPresent()) {
|
||||
// IMPORTANT: This block should always be last, since you can pair SKDM's with other content
|
||||
return new SignalServiceContent(senderKeyDistributionMessage.get(),
|
||||
metadata.getSender(),
|
||||
metadata.getSenderDevice(),
|
||||
metadata.getTimestamp(),
|
||||
|
|
Loading…
Add table
Reference in a new issue