Fix potential bad state with change numbers.

This commit is contained in:
Greyson Parrelli
2025-04-15 16:59:44 -04:00
parent 193f6460b0
commit 4cb5bd9edd
4 changed files with 83 additions and 3 deletions

View File

@@ -113,7 +113,6 @@ import org.thoughtcrime.securesms.util.CachedInflater
import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme
import org.thoughtcrime.securesms.util.DynamicTheme
import org.thoughtcrime.securesms.util.RemoteConfig
import org.thoughtcrime.securesms.util.SplashScreenUtil
import org.thoughtcrime.securesms.util.viewModel
import org.thoughtcrime.securesms.window.AppScaffold

View File

@@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.migrations.DuplicateE164MigrationJob;
import org.thoughtcrime.securesms.migrations.E164FormattingMigrationJob;
import org.thoughtcrime.securesms.migrations.EmojiDownloadMigrationJob;
import org.thoughtcrime.securesms.migrations.EmojiSearchIndexCheckMigrationJob;
import org.thoughtcrime.securesms.migrations.FixChangeNumberErrorMigrationJob;
import org.thoughtcrime.securesms.migrations.GooglePlayBillingPurchaseTokenMigrationJob;
import org.thoughtcrime.securesms.migrations.IdentityTableCleanupMigrationJob;
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
@@ -299,6 +300,7 @@ public final class JobManagerFactories {
put(E164FormattingMigrationJob.KEY, new E164FormattingMigrationJob.Factory());
put(EmojiDownloadMigrationJob.KEY, new EmojiDownloadMigrationJob.Factory());
put(EmojiSearchIndexCheckMigrationJob.KEY, new EmojiSearchIndexCheckMigrationJob.Factory());
put(FixChangeNumberErrorMigrationJob.KEY, new FixChangeNumberErrorMigrationJob.Factory());
put(GooglePlayBillingPurchaseTokenMigrationJob.KEY, new GooglePlayBillingPurchaseTokenMigrationJob.Factory());
put(IdentityTableCleanupMigrationJob.KEY, new IdentityTableCleanupMigrationJob.Factory());
put(LegacyMigrationJob.KEY, new LegacyMigrationJob.Factory());

View File

@@ -176,10 +176,12 @@ public class ApplicationMigrations {
static final int AVATAR_COLOR_MIGRATION_JOB = 132;
static final int DUPLICATE_E164_FIX_2 = 133;
static final int E164_FORMATTING = 134;
static final int CHAT_FOLDER_STORAGE_SYNC = 135;
// Need to skip 135 because of hotfix ordering issues
static final int FIX_CHANGE_NUMBER_ERROR = 136;
static final int CHAT_FOLDER_STORAGE_SYNC = 137;
}
public static final int CURRENT_VERSION = 135;
public static final int CURRENT_VERSION = 137;
/**
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
@@ -814,6 +816,10 @@ public class ApplicationMigrations {
jobs.put(Version.E164_FORMATTING, new E164FormattingMigrationJob());
}
if (lastSeenVersion < Version.FIX_CHANGE_NUMBER_ERROR) {
jobs.put(Version.FIX_CHANGE_NUMBER_ERROR, new FixChangeNumberErrorMigrationJob());
}
if (lastSeenVersion < Version.CHAT_FOLDER_STORAGE_SYNC) {
jobs.put(Version.CHAT_FOLDER_STORAGE_SYNC, new SyncChatFoldersMigrationJob());
}

View File

@@ -0,0 +1,73 @@
package org.thoughtcrime.securesms.migrations
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.components.settings.app.changenumber.ChangeNumberRepository
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.net.SignalNetwork
import org.whispersystems.signalservice.api.NetworkResult
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.internal.push.WhoAmIResponse
import java.io.IOException
/**
* There was a server error during change number where a number was changed but gave back a 409 response.
* We need devices to re-fetch their E164+PNI's, save them, and then get prekeys.
*/
internal class FixChangeNumberErrorMigrationJob(
parameters: Parameters = Parameters.Builder().build()
) : MigrationJob(parameters) {
companion object {
const val KEY = "FixChangeNumberErrorMigrationJob"
private val TAG = Log.tag(FixChangeNumberErrorMigrationJob::class)
}
override fun getFactoryKey(): String = KEY
override fun isUiBlocking(): Boolean = false
override fun performMigration() {
if (!SignalStore.account.isRegistered) {
Log.i(TAG, "Not registered, skipping.")
return
}
val pendingChangeNumberMetadata = SignalStore.misc.pendingChangeNumberMetadata
if (pendingChangeNumberMetadata == null) {
Log.i(TAG, "No pending change number metadata, skipping.")
return
}
if (pendingChangeNumberMetadata.previousPni != SignalStore.account.pni?.toByteString()) {
Log.i(TAG, "Pending change number operation isn't for our current PNI, skipping.")
return
}
when (val result = SignalNetwork.account.whoAmI()) {
is NetworkResult.Success<WhoAmIResponse> -> {
val pni = result.result.pni?.let { ServiceId.PNI.parseOrNull(it) } ?: return
if (result.result.number != SignalStore.account.e164 || pni != SignalStore.account.pni) {
Log.w(TAG, "Detected a number or PNI mismatch! Fixing...")
ChangeNumberRepository().changeLocalNumber(result.result.number, pni)
Log.w(TAG, "Done!")
} else {
Log.i(TAG, "No number or PNI mismatch detected.")
return
}
}
is NetworkResult.ApplicationError -> throw result.throwable
is NetworkResult.NetworkError -> throw result.exception
is NetworkResult.StatusCodeError -> throw result.exception
}
}
override fun shouldRetry(e: Exception): Boolean = e is IOException
class Factory : Job.Factory<FixChangeNumberErrorMigrationJob> {
override fun create(parameters: Parameters, serializedData: ByteArray?): FixChangeNumberErrorMigrationJob {
return FixChangeNumberErrorMigrationJob(parameters)
}
}
}