From fdcf0a76e8276ca9ee3964046f77887161f1352e Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 7 Feb 2023 14:49:44 -0500 Subject: [PATCH] Split unregistered contacts when in PNP mode. --- .../securesms/database/RecipientTableTest.kt | 29 +++++++++++ .../securesms/database/RecipientTable.kt | 50 ++++++++++++++++--- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest.kt index b90f14210e..d2d33a2d99 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest.kt @@ -11,6 +11,11 @@ import org.signal.core.util.CursorUtil import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.testing.SignalActivityRule +import org.thoughtcrime.securesms.util.FeatureFlags +import org.thoughtcrime.securesms.util.FeatureFlagsAccessor +import org.whispersystems.signalservice.api.push.ACI +import org.whispersystems.signalservice.api.push.PNI +import java.util.UUID @RunWith(AndroidJUnit4::class) class RecipientTableTest { @@ -159,4 +164,28 @@ class RecipientTableTest { assertNotEquals(0, results.size) assertFalse(blockedRecipient in results) } + + @Test + fun givenARecipientWithPniAndAci_whenIMarkItUnregistered_thenIExpectItToBeSplit() { + FeatureFlagsAccessor.forceValue(FeatureFlags.PHONE_NUMBER_PRIVACY, true) + + val mainId = SignalDatabase.recipients.getAndPossiblyMerge(ACI_A, PNI_A, E164_A) + + SignalDatabase.recipients.markUnregistered(mainId) + + val byAci: RecipientId = SignalDatabase.recipients.getByServiceId(ACI_A).get() + + val byE164: RecipientId = SignalDatabase.recipients.getByE164(E164_A).get() + val byPni: RecipientId = SignalDatabase.recipients.getByServiceId(PNI_A).get() + + assertEquals(mainId, byAci) + assertEquals(byE164, byPni) + assertNotEquals(byAci, byE164) + } + + companion object { + val ACI_A = ACI.from(UUID.fromString("aaaa0000-5a76-47fa-a98a-7e72c948a82e")) + val PNI_A = PNI.from(UUID.fromString("aaaa1111-c960-4f6c-8385-671ad2ffb999")) + const val E164_A = "+12222222222" + } } 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 4bd2f7da5e..78ca6bc0f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt @@ -2207,13 +2207,53 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } fun markUnregistered(id: RecipientId) { + if (FeatureFlags.phoneNumberPrivacy()) { + val record = getRecord(id) + + if (record.pni != null && record.serviceId != record.pni) { + markUnregisteredAndSplit(id, record) + } else { + markUnregisteredWithoutSplit(id) + } + } else { + markUnregisteredWithoutSplit(id) + } + } + + /** + * Marks the user unregistered and also splits it into an ACI-only and PNI-only contact. + * This is to allow a new user to register the number with a new ACI. + */ + private fun markUnregisteredAndSplit(id: RecipientId, record: RecipientRecord) { + check(record.pni != null && record.pni != record.serviceId) + + val contentValues = contentValuesOf( + REGISTERED to RegisteredState.NOT_REGISTERED.id, + UNREGISTERED_TIMESTAMP to System.currentTimeMillis(), + PHONE to null, + PNI_COLUMN to null + ) + + if (update(id, contentValues)) { + Log.i(TAG, "[WithSplit] Newly marked $id as unregistered.") + ApplicationDependencies.getDatabaseObserver().notifyRecipientChanged(id) + } + + val splitId = getAndPossiblyMerge(record.pni, record.pni, record.e164) + Log.i(TAG, "Split off new recipient as $splitId (ACI-only recipient is $id)") + } + + /** + * Marks the user unregistered without splitting the contact into an ACI-only and PNI-only contact. + */ + private fun markUnregisteredWithoutSplit(id: RecipientId) { val contentValues = contentValuesOf( REGISTERED to RegisteredState.NOT_REGISTERED.id, UNREGISTERED_TIMESTAMP to System.currentTimeMillis() ) if (update(id, contentValues)) { - Log.i(TAG, "Newly marked $id as unregistered.") + Log.i(TAG, "[WithoutSplit] Newly marked $id as unregistered.") ApplicationDependencies.getDatabaseObserver().notifyRecipientChanged(id) } } @@ -2246,13 +2286,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } for (id in unregistered) { - val values = contentValuesOf( - REGISTERED to RegisteredState.NOT_REGISTERED.id, - UNREGISTERED_TIMESTAMP to System.currentTimeMillis() - ) - if (update(id, values)) { - ApplicationDependencies.getDatabaseObserver().notifyRecipientChanged(id) - } + markUnregistered(id) } } }