From 64fff2adb2594a6978fc2f44cd0ce5166bdd7538 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Fri, 12 Jan 2024 13:22:30 -0500 Subject: [PATCH] Do not show contact info for non-discoverable contacts. --- .../sync/ContactDiscoveryRefreshV2.kt | 9 ++- .../securesms/database/RecipientTable.kt | 78 ++++++++++++++----- .../helpers/SignalDatabaseMigrations.kt | 6 +- .../migration/V216_PhoneNumberDiscoverable.kt | 15 ++++ 4 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V216_PhoneNumberDiscoverable.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt index 5ef96ca151..d1378c878b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscoveryRefreshV2.kt @@ -182,9 +182,12 @@ object ContactDiscoveryRefreshV2 { val existingIds: Set = SignalDatabase.recipients.getAllPossiblyRegisteredByE164(recipientE164s + rewrites.values) stopwatch.split("get-ids") - val inactiveIds: Set = (existingIds - registeredIds).removePossiblyRegisteredButUnlisted() + val inactiveIds: Set = (existingIds - registeredIds).removePossiblyRegisteredButUndiscoverable() stopwatch.split("registered-but-unlisted") + val missingFromCds: Set = existingIds - registeredIds + SignalDatabase.recipients.updatePhoneNumberDiscoverability(registeredIds, missingFromCds) + SignalDatabase.recipients.bulkUpdatedRegisteredStatus(registeredIds, inactiveIds) stopwatch.split("update-registered") @@ -199,13 +202,13 @@ object ContactDiscoveryRefreshV2 { } /** - * If an account is unlisted, it won't come back in the CDS response. So just because we're missing a entry doesn't mean they've become unregistered. + * If an account is undiscoverable, it won't come back in the CDS response. So just because we're missing a entry doesn't mean they've become unregistered. * This function removes people from the list that both have a serviceId and some history of communication. We consider this a good heuristic for * "maybe this person just removed themselves from CDS". We'll rely on profile fetches that occur during chat opens to check registered status and clear * actually-unregistered users out. */ @WorkerThread - private fun Set.removePossiblyRegisteredButUnlisted(): Set { + private fun Set.removePossiblyRegisteredButUndiscoverable(): Set { val selfId = Recipient.self().id return this - Recipient.resolvedList(this) .filter { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt index 32ecb296e3..20b9a85f52 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt @@ -16,6 +16,7 @@ import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.delete import org.signal.core.util.exists +import org.signal.core.util.forEach import org.signal.core.util.logging.Log import org.signal.core.util.nullIfBlank import org.signal.core.util.optionalString @@ -178,6 +179,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da const val NEEDS_PNI_SIGNATURE = "needs_pni_signature" const val REPORTING_TOKEN = "reporting_token" const val PHONE_NUMBER_SHARING = "phone_number_sharing" + const val PHONE_NUMBER_DISCOVERABLE = "phone_number_discoverable" const val SEARCH_PROFILE_NAME = "search_signal_profile" const val SORT_NAME = "sort_name" @@ -244,7 +246,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da $BADGES BLOB DEFAULT NULL, $NEEDS_PNI_SIGNATURE INTEGER DEFAULT 0, $REPORTING_TOKEN BLOB DEFAULT NULL, - $PHONE_NUMBER_SHARING INTEGER DEFAULT ${PhoneNumberSharingState.UNKNOWN.id} + $PHONE_NUMBER_SHARING INTEGER DEFAULT ${PhoneNumberSharingState.UNKNOWN.id}, + $PHONE_NUMBER_DISCOVERABLE INTEGER DEFAULT ${PhoneNumberDiscoverableState.UNKNOWN.id} ) """ @@ -3662,6 +3665,24 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } } + fun updatePhoneNumberDiscoverability(presentInCds: Set, missingFromCds: Set) { + SqlUtil.buildCollectionQuery(ID, presentInCds).forEach { query -> + writableDatabase + .update(TABLE_NAME) + .values(PHONE_NUMBER_DISCOVERABLE to PhoneNumberDiscoverableState.DISCOVERABLE.id) + .where(query.where, query.whereArgs) + .run() + } + + SqlUtil.buildCollectionQuery(ID, missingFromCds).forEach { query -> + writableDatabase + .update(TABLE_NAME) + .values(PHONE_NUMBER_DISCOVERABLE to PhoneNumberDiscoverableState.UNDISCOVERABLE.id) + .where(query.where, query.whereArgs) + .run() + } + } + private fun updateExtras(recipientId: RecipientId, updater: java.util.function.Function) { val db = writableDatabase db.beginTransaction() @@ -4168,16 +4189,16 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da put(SYSTEM_CONTACT_URI, systemContactUri) } - val updatedValues = update(id, refreshQualifyingValues) - if (updatedValues) { + val updateQuery = SqlUtil.buildTrueUpdateQuery("$ID = ? AND $PHONE_NUMBER_DISCOVERABLE != ?", SqlUtil.buildArgs(id, PhoneNumberDiscoverableState.UNDISCOVERABLE.id), refreshQualifyingValues) + if (update(updateQuery, refreshQualifyingValues)) { pendingRecipients.add(id) } - val otherValues = ContentValues().apply { - put(SYSTEM_INFO_PENDING, 0) - } - - update(id, otherValues) + writableDatabase + .update(TABLE_NAME) + .values(SYSTEM_INFO_PENDING to 0) + .where("$ID = ? AND $PHONE_NUMBER_DISCOVERABLE != ?", id, PhoneNumberDiscoverableState.UNDISCOVERABLE.id) + .run() } fun finish() { @@ -4203,18 +4224,25 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } private fun clearSystemDataForPendingInfo() { - database.update(TABLE_NAME) - .values( - SYSTEM_INFO_PENDING to 0, - SYSTEM_GIVEN_NAME to null, - SYSTEM_FAMILY_NAME to null, - SYSTEM_JOINED_NAME to null, - SYSTEM_PHOTO_URI to null, - SYSTEM_PHONE_LABEL to null, - SYSTEM_CONTACT_URI to null - ) - .where("$SYSTEM_INFO_PENDING = ?", 1) - .run() + writableDatabase.rawQuery( + """ + UPDATE $TABLE_NAME + SET + $SYSTEM_INFO_PENDING = 0, + $SYSTEM_GIVEN_NAME = NULL, + $SYSTEM_FAMILY_NAME = NULL, + $SYSTEM_JOINED_NAME = NULL, + $SYSTEM_PHOTO_URI = NULL, + $SYSTEM_PHONE_LABEL = NULL, + $SYSTEM_CONTACT_URI = NULL + WHERE $SYSTEM_INFO_PENDING = 1 + RETURNING $ID + """, + null + ).forEach { cursor -> + val id = RecipientId.from(cursor.requireLong(ID)) + ApplicationDependencies.getDatabaseObserver().notifyRecipientChanged(id) + } } } @@ -4519,6 +4547,16 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } } + enum class PhoneNumberDiscoverableState(val id: Int) { + UNKNOWN(0), DISCOVERABLE(1), UNDISCOVERABLE(2); + + companion object { + fun fromId(id: Int): PhoneNumberDiscoverableState { + return PhoneNumberDiscoverableState.values()[id] + } + } + } + data class CdsV2Result( val pni: PNI, val aci: ACI? diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt index 292af9cd1d..cc98a4818c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt @@ -73,6 +73,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V212_RemoveDistribu import org.thoughtcrime.securesms.database.helpers.migration.V213_FixUsernameInE164Column import org.thoughtcrime.securesms.database.helpers.migration.V214_PhoneNumberSharingColumn import org.thoughtcrime.securesms.database.helpers.migration.V215_RemoveAttachmentUniqueId +import org.thoughtcrime.securesms.database.helpers.migration.V216_PhoneNumberDiscoverable /** * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. @@ -148,10 +149,11 @@ object SignalDatabaseMigrations { 212 to V212_RemoveDistributionListUniqueConstraint, 213 to V213_FixUsernameInE164Column, 214 to V214_PhoneNumberSharingColumn, - 215 to V215_RemoveAttachmentUniqueId + 215 to V215_RemoveAttachmentUniqueId, + 216 to V216_PhoneNumberDiscoverable ) - const val DATABASE_VERSION = 215 + const val DATABASE_VERSION = 216 @JvmStatic fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V216_PhoneNumberDiscoverable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V216_PhoneNumberDiscoverable.kt new file mode 100644 index 0000000000..92e4ea03a7 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V216_PhoneNumberDiscoverable.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.database.helpers.migration + +import android.app.Application +import net.zetetic.database.sqlcipher.SQLiteDatabase + +object V216_PhoneNumberDiscoverable : SignalDatabaseMigration { + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL("""ALTER TABLE recipient ADD COLUMN phone_number_discoverable INTEGER DEFAULT 0""") + } +}