Add migration to cleanup some inconsistent DB state.

This commit is contained in:
Greyson Parrelli
2023-07-12 13:49:16 -04:00
committed by Clark Chen
parent 1b63bdec12
commit 6ca9cb6da1
9 changed files with 107 additions and 19 deletions

View File

@@ -276,6 +276,7 @@ class ChangeNumberRepository(
pniProtocolStore.identities().saveIdentityWithoutSideEffects(
Recipient.self().id,
pni,
pniProtocolStore.identityKeyPair.publicKey,
IdentityTable.VerifiedStatus.VERIFIED,
true,

View File

@@ -112,18 +112,14 @@ public class SignalBaseIdentityKeyStore {
}
public void saveIdentityWithoutSideEffects(@NonNull RecipientId recipientId,
@NonNull ServiceId serviceId,
IdentityKey identityKey,
VerifiedStatus verifiedStatus,
boolean firstUse,
long timestamp,
boolean nonBlockingApproval)
{
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.hasServiceId()) {
cache.save(recipient.requireServiceId().toString(), recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval);
} else {
Log.w(TAG, "[saveIdentity] No serviceId for " + recipient.getId(), new Throwable());
}
cache.save(serviceId.toString(), recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval);
}
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, IdentityKeyStore.Direction direction) {

View File

@@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.database.identity.IdentityRecordList;
import org.thoughtcrime.securesms.database.model.IdentityRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.push.ServiceId;
import java.util.List;
import java.util.Optional;
@@ -50,13 +51,14 @@ public class SignalIdentityKeyStore implements IdentityKeyStore {
}
public void saveIdentityWithoutSideEffects(@NonNull RecipientId recipientId,
@NonNull ServiceId serviceId,
IdentityKey identityKey,
VerifiedStatus verifiedStatus,
boolean firstUse,
long timestamp,
boolean nonBlockingApproval)
{
baseStore.saveIdentityWithoutSideEffects(recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval);
baseStore.saveIdentityWithoutSideEffects(recipientId, serviceId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval);
}
@Override

View File

@@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.migrations.DeleteDeprecatedLogsMigrationJob;
import org.thoughtcrime.securesms.migrations.DirectoryRefreshMigrationJob;
import org.thoughtcrime.securesms.migrations.EmojiDownloadMigrationJob;
import org.thoughtcrime.securesms.migrations.EmojiSearchIndexCheckMigrationJob;
import org.thoughtcrime.securesms.migrations.IdentityTableCleanupMigrationJob;
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
import org.thoughtcrime.securesms.migrations.MigrationCompleteJob;
import org.thoughtcrime.securesms.migrations.OptimizeMessageSearchIndexMigrationJob;
@@ -236,6 +237,7 @@ public final class JobManagerFactories {
put(DirectoryRefreshMigrationJob.KEY, new DirectoryRefreshMigrationJob.Factory());
put(EmojiDownloadMigrationJob.KEY, new EmojiDownloadMigrationJob.Factory());
put(EmojiSearchIndexCheckMigrationJob.KEY, new EmojiSearchIndexCheckMigrationJob.Factory());
put(IdentityTableCleanupMigrationJob.KEY, new IdentityTableCleanupMigrationJob.Factory());
put(LegacyMigrationJob.KEY, new LegacyMigrationJob.Factory());
put(MigrationCompleteJob.KEY, new MigrationCompleteJob.Factory());
put(OptimizeMessageSearchIndexMigrationJob.KEY,new OptimizeMessageSearchIndexMigrationJob.Factory());

View File

@@ -103,14 +103,19 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo
else -> VerifiedStatus.DEFAULT
}
ApplicationDependencies.getProtocolStore().aci().identities().saveIdentityWithoutSideEffects(
recipient.id,
contact.verified.get().identityKey,
verifiedStatus,
false,
contact.verified.get().timestamp,
true
)
if (recipient.serviceId.isPresent) {
ApplicationDependencies.getProtocolStore().aci().identities().saveIdentityWithoutSideEffects(
recipient.id,
recipient.serviceId.get(),
contact.verified.get().identityKey,
verifiedStatus,
false,
contact.verified.get().timestamp,
true
)
} else {
Log.w(TAG, "Missing serviceId for ${recipient.id} -- cannot save identity!")
}
}
recipients.setBlocked(recipient.id, contact.isBlocked)

View File

@@ -135,9 +135,10 @@ public class ApplicationMigrations {
static final int SVR2_MIRROR = 91;
static final int ATTACHMENT_CLEANUP_3 = 92;
static final int EMOJI_SEARCH_INDEX_CHECK = 93;
static final int IDENTITY_FIX = 94;
}
public static final int CURRENT_VERSION = 93;
public static final int CURRENT_VERSION = 94;
/**
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
@@ -611,6 +612,10 @@ public class ApplicationMigrations {
jobs.put(Version.EMOJI_SEARCH_INDEX_CHECK, new EmojiSearchIndexCheckMigrationJob());
}
if (lastSeenVersion < Version.IDENTITY_FIX) {
jobs.put(Version.IDENTITY_FIX, new IdentityTableCleanupMigrationJob());
}
return jobs;
}

View File

@@ -0,0 +1,74 @@
package org.thoughtcrime.securesms.migrations
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.IdentityTable
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobs.AccountConsistencyWorkerJob
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
/**
* Migration to help cleanup some inconsistent state for ourself in the identity table.
*/
internal class IdentityTableCleanupMigrationJob(
parameters: Parameters = Parameters.Builder().build()
) : MigrationJob(parameters) {
companion object {
const val KEY = "IdentityTableCleanupMigrationJob"
val TAG = Log.tag(IdentityTableCleanupMigrationJob::class.java)
}
override fun getFactoryKey(): String = KEY
override fun isUiBlocking(): Boolean = false
override fun performMigration() {
if (SignalStore.account().aci == null || SignalStore.account().pni == null) {
Log.i(TAG, "ACI/PNI are unset, skipping.")
return
}
if (!SignalStore.account().hasAciIdentityKey()) {
Log.i(TAG, "No ACI identity set yet, skipping.")
return
}
if (!SignalStore.account().hasPniIdentityKey()) {
Log.i(TAG, "No PNI identity set yet, skipping.")
return
}
ApplicationDependencies.getProtocolStore().aci().identities().saveIdentityWithoutSideEffects(
Recipient.self().id,
SignalStore.account().aci!!,
SignalStore.account().aciIdentityKey.publicKey,
IdentityTable.VerifiedStatus.VERIFIED,
true,
System.currentTimeMillis(),
true
)
ApplicationDependencies.getProtocolStore().pni().identities().saveIdentityWithoutSideEffects(
Recipient.self().id,
SignalStore.account().pni!!,
SignalStore.account().pniIdentityKey.publicKey,
IdentityTable.VerifiedStatus.VERIFIED,
true,
System.currentTimeMillis(),
true
)
ApplicationDependencies.getJobManager().add(AccountConsistencyWorkerJob())
}
override fun shouldRetry(e: Exception): Boolean = false
class Factory : Job.Factory<IdentityTableCleanupMigrationJob> {
override fun create(parameters: Parameters, serializedData: ByteArray?): IdentityTableCleanupMigrationJob {
return IdentityTableCleanupMigrationJob(parameters)
}
}
}

View File

@@ -40,6 +40,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.account.PreKeyCollection;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.PNI;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.Preconditions;
import org.whispersystems.signalservice.internal.ServiceResponse;
@@ -162,8 +163,8 @@ public final class RegistrationRepository {
SignalStore.account().setFcmEnabled(registrationData.isFcm());
long now = System.currentTimeMillis();
saveOwnIdentityKey(selfId, aciProtocolStore, now);
saveOwnIdentityKey(selfId, pniProtocolStore, now);
saveOwnIdentityKey(selfId, aci, aciProtocolStore, now);
saveOwnIdentityKey(selfId, pni, pniProtocolStore, now);
SignalStore.account().setServicePassword(registrationData.getPassword());
SignalStore.account().setRegistered(true);
@@ -200,8 +201,9 @@ public final class RegistrationRepository {
metadataStore.setLastResortKyberPreKeyRotationTime(System.currentTimeMillis());
}
private void saveOwnIdentityKey(@NonNull RecipientId selfId, @NonNull SignalServiceAccountDataStoreImpl protocolStore, long now) {
private void saveOwnIdentityKey(@NonNull RecipientId selfId, @NonNull ServiceId serviceId, @NonNull SignalServiceAccountDataStoreImpl protocolStore, long now) {
protocolStore.identities().saveIdentityWithoutSideEffects(selfId,
serviceId,
protocolStore.getIdentityKeyPair().getPublicKey(),
IdentityTable.VerifiedStatus.VERIFIED,
true,

View File

@@ -543,6 +543,7 @@ public class VerifyDisplayFragment extends Fragment implements ViewTreeObserver.
Log.i(TAG, "Saving identity: " + recipientId);
ApplicationDependencies.getProtocolStore().aci().identities()
.saveIdentityWithoutSideEffects(recipientId,
Recipient.resolved(recipientId).requireServiceId(),
remoteIdentity,
IdentityTable.VerifiedStatus.VERIFIED,
false,