Heal InAppPaymentSubscriber currency if we have a payment with a matching subscriber id.

This commit is contained in:
Alex Hart
2024-06-18 09:19:25 -03:00
committed by Greyson Parrelli
parent 7a696f9a62
commit ea87108def
4 changed files with 240 additions and 4 deletions

View File

@@ -45,10 +45,12 @@ class InAppPaymentSubscriberTable(
private const val ID = "_id"
/** The serialized subscriber id */
private const val SUBSCRIBER_ID = "subscriber_id"
@VisibleForTesting
const val SUBSCRIBER_ID = "subscriber_id"
/** The currency code for this subscriber id */
private const val CURRENCY_CODE = "currency_code"
@VisibleForTesting
const val CURRENCY_CODE = "currency_code"
/** The type of subscription used by this subscriber id */
private const val TYPE = "type"

View File

@@ -93,6 +93,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V232_CreateInAppPay
import org.thoughtcrime.securesms.database.helpers.migration.V233_FixInAppPaymentTableDefaultNotifiedValue
import org.thoughtcrime.securesms.database.helpers.migration.V234_ThumbnailRestoreStateColumn
import org.thoughtcrime.securesms.database.helpers.migration.V235_AttachmentUuidColumn
import org.thoughtcrime.securesms.database.helpers.migration.V236_FixInAppSubscriberCurrencyIfAble
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@@ -188,10 +189,11 @@ object SignalDatabaseMigrations {
232 to V232_CreateInAppPaymentTable,
233 to V233_FixInAppPaymentTableDefaultNotifiedValue,
234 to V234_ThumbnailRestoreStateColumn,
235 to V235_AttachmentUuidColumn
235 to V235_AttachmentUuidColumn,
236 to V236_FixInAppSubscriberCurrencyIfAble
)
const val DATABASE_VERSION = 235
const val DATABASE_VERSION = 236
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import androidx.core.content.contentValuesOf
import net.zetetic.database.sqlcipher.SQLiteDatabase
import org.signal.core.util.logging.Log
import org.signal.core.util.update
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
/**
* Fixes a bug in storage sync where we could end up overwriting a subscriber's currency code with
* an empty string. This can't happen anymore, as we now require a Currency on the InAppPaymentSubscriberRecord
* instead of just a currency code string.
*
* If a subscriber has a null or empty currency code, we try to load the code from the
* in app payments table. We utilize CONFLICT_IGNORE because if there's already a new subscriber id
* created, we don't want to impact it.
*
* Because the data column is a protobuf encoded blob, we cannot do a raw query here.
*/
@Suppress("ClassName")
object V236_FixInAppSubscriberCurrencyIfAble : SignalDatabaseMigration {
private val TAG = Log.tag(V236_FixInAppSubscriberCurrencyIfAble::class)
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
val subscriberIds: List<String> = db.query(
"in_app_payment_subscriber",
arrayOf("subscriber_id"),
"currency_code = ?",
arrayOf(""),
null,
null,
"_id DESC"
).use { cursor ->
val ids = mutableListOf<String>()
val columnIndex = cursor.getColumnIndexOrThrow("subscriber_id")
while (cursor.moveToNext()) {
ids.add(cursor.getString(columnIndex))
}
ids
}
for (id in subscriberIds) {
val currencyCode: String? = db.query(
"in_app_payment",
arrayOf("data"),
"subscriber_id = ?",
arrayOf(id),
null,
null,
"inserted_at DESC",
"1"
).use { cursor ->
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndexOrThrow("data")
val rawData = cursor.getBlob(columnIndex)
val data = InAppPaymentData.ADAPTER.decode(rawData)
data.amount?.currencyCode
} else {
null
}
}
if (currencyCode != null) {
Log.d(TAG, "Found and attempting to heal subscriber of currency $currencyCode")
db.update(
"in_app_payment_subscriber",
SQLiteDatabase.CONFLICT_IGNORE,
contentValuesOf("currency_code" to currencyCode),
"subscriber_id = ?",
arrayOf(id)
)
}
}
}
}