diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt index 6df870349..63e1f9e7a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt @@ -104,7 +104,7 @@ class ChangeNumberRepository(private val accountManager: SignalServiceAccountMan @WorkerThread fun changeLocalNumber(e164: String, pni: PNI): Single { val oldStorageId: ByteArray? = Recipient.self().storageServiceId - SignalDatabase.recipients.updateSelfPhone(e164) + SignalDatabase.recipients.updateSelfPhone(e164, pni) val newStorageId: ByteArray? = Recipient.self().storageServiceId if (MessageDigest.isEqual(oldStorageId, newStorageId)) { @@ -117,7 +117,6 @@ class ChangeNumberRepository(private val accountManager: SignalServiceAccountMan } } - SignalDatabase.recipients.setPni(Recipient.self().id, pni) ApplicationDependencies.getRecipientCache().clear() SignalStore.account().setE164(e164) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt index f8226e098..08639ca0d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt @@ -28,7 +28,6 @@ import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.livedata.Store -import org.whispersystems.signalservice.api.push.ServiceId import java.util.Objects /** @@ -62,27 +61,26 @@ class InternalConversationSettingsFragment : DSLSettingsFragment( ) if (!recipient.isGroup) { - if (recipient.isSelf) { - val aci: String = SignalStore.account().aci?.toString() ?: "null" - longClickPref( - title = DSLSettingsText.from("ACI"), - summary = DSLSettingsText.from(aci), - onLongClick = { copyToClipboard(aci) } - ) - val pni: String = SignalStore.account().pni?.toString() ?: "null" - longClickPref( - title = DSLSettingsText.from("PNI"), - summary = DSLSettingsText.from(pni), - onLongClick = { copyToClipboard(pni) } - ) - } else { - val serviceId: String = recipient.serviceId.map(ServiceId::toString).orElse("null") - longClickPref( - title = DSLSettingsText.from("ServiceId"), - summary = DSLSettingsText.from(serviceId), - onLongClick = { copyToClipboard(serviceId) } - ) - } + val e164: String = recipient.e164.orElse("null") + longClickPref( + title = DSLSettingsText.from("E164"), + summary = DSLSettingsText.from(e164), + onLongClick = { copyToClipboard(e164) } + ) + + val serviceId: String = recipient.serviceId.map { it.toString() }.orElse("null") + longClickPref( + title = DSLSettingsText.from("ServiceId"), + summary = DSLSettingsText.from(serviceId), + onLongClick = { copyToClipboard(serviceId) } + ) + + val pni: String = recipient.pni.map { it.toString() }.orElse("null") + longClickPref( + title = DSLSettingsText.from("PNI"), + summary = DSLSettingsText.from(pni), + onLongClick = { copyToClipboard(pni) } + ) } if (state.groupId != null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java index 23f0a46fd..672aca782 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java @@ -126,10 +126,9 @@ public class SignalBaseIdentityKeyStore { } public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, IdentityKeyStore.Direction direction) { - Recipient self = Recipient.self(); - - boolean isSelf = address.getName().equals(self.requireServiceId().toString()) || - address.getName().equals(self.requireE164()); + boolean isSelf = address.getName().equals(SignalStore.account().requireAci().toString()) || + address.getName().equals(SignalStore.account().requirePni().toString()) || + address.getName().equals(SignalStore.account().getE164()); if (isSelf) { return identityKey.equals(SignalStore.account().getAciIdentityKey().getPublicKey()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt index 3dbb4f83a..f825a518e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt @@ -2046,16 +2046,23 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } } + /** + * Associates the provided IDs together. The assumption here is that all of the IDs correspond to the local user and have been verified. + */ + fun linkIdsForSelf(aci: ACI, pni: PNI, e164: String) { + getAndPossiblyMergePnp(serviceId = aci, pni = pni, e164 = e164, changeSelf = true, pniVerified = true) + } + /** * Does *not* handle clearing the recipient cache. It is assumed the caller handles this. */ - fun updateSelfPhone(e164: String) { + fun updateSelfPhone(e164: String, pni: PNI) { val db = writableDatabase db.beginTransaction() try { val id = Recipient.self().id - val newId = getAndPossiblyMerge(SignalStore.account().requireAci(), e164, changeSelf = true) + val newId = getAndPossiblyMergePnp(serviceId = SignalStore.account().requireAci(), pni = pni, e164 = e164, pniVerified = true, changeSelf = true) if (id == newId) { Log.i(TAG, "[updateSelfPhone] Phone updated for self") @@ -2068,7 +2075,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : .values(NEEDS_PNI_SIGNATURE to 0) .run() - SignalDatabase.pendingPniSignatureMessages.deleteAll() + pendingPniSignatureMessages.deleteAll() db.setTransactionSuccessful() } finally { @@ -2392,18 +2399,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : .run() } is PnpOperation.Merge -> { - val primary = getRecord(operation.primaryId) - val secondary = getRecord(operation.secondaryId) - - if (primary.serviceId != null && !primary.sidIsPni() && secondary.e164 != null) { - merge(operation.primaryId, operation.secondaryId, inputPni) - } else { - if (!pnpEnabled) { - throw AssertionError("This type of merge is not supported in production!") - } - - merge(operation.primaryId, operation.secondaryId, inputPni) - } + merge(operation.primaryId, operation.secondaryId, inputPni) } is PnpOperation.SessionSwitchoverInsert -> { // TODO [pnp] diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt index 267acba21..931648722 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt @@ -24,6 +24,7 @@ import org.whispersystems.signalservice.api.push.ACI import org.whispersystems.signalservice.api.push.PNI import org.whispersystems.signalservice.api.push.ServiceIds import org.whispersystems.signalservice.api.push.SignalServiceAddress +import java.lang.IllegalStateException import java.security.SecureRandom internal class AccountValues internal constructor(store: KeyValueStore) : SignalStoreValues(store) { @@ -121,6 +122,12 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal val e164: String? get() = getString(KEY_E164, null) + /** The local user's e164. Will throw if not present. */ + fun requireE164(): String { + val e164: String? = getString(KEY_E164, null) + return e164 ?: throw IllegalStateException("No e164!") + } + fun setE164(e164: String) { putString(KEY_E164, e164) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index 3d22a09bf..481dcfc8e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -107,9 +107,10 @@ public class ApplicationMigrations { static final int EMOJI_SEARCH_INDEX_10 = 63; static final int REFRESH_PNI_REGISTRATION_ID = 64; static final int KBS_MIGRATION_2 = 65; + static final int PNI_2 = 66; } - public static final int CURRENT_VERSION = 65; + public static final int CURRENT_VERSION = 66; /** * This *must* be called after the {@link JobManager} has been instantiated, but *before* the call @@ -471,6 +472,10 @@ public class ApplicationMigrations { jobs.put(Version.KBS_MIGRATION_2, new KbsEnclaveMigrationJob()); } + if (lastSeenVersion < Version.PNI_2) { + jobs.put(Version.PNI_2, new PniMigrationJob()); + } + return jobs; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/PniMigrationJob.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/PniMigrationJob.java index 3cc674b05..53129350a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/PniMigrationJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/PniMigrationJob.java @@ -49,14 +49,13 @@ public class PniMigrationJob extends MigrationJob { return; } - RecipientId self = Recipient.self().getId(); - PNI pni = PNI.parseOrNull(ApplicationDependencies.getSignalServiceAccountManager().getWhoAmI().getPni()); + PNI pni = PNI.parseOrNull(ApplicationDependencies.getSignalServiceAccountManager().getWhoAmI().getPni()); if (pni == null) { throw new IOException("Invalid PNI!"); } - SignalDatabase.recipients().setPni(self, pni); + SignalDatabase.recipients().linkIdsForSelf(SignalStore.account().requireAci(), pni, SignalStore.account().requireE164()); SignalStore.account().setPni(pni); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java index 755563fad..77b008e02 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java @@ -159,11 +159,11 @@ public final class RegistrationRepository { } RecipientDatabase recipientDatabase = SignalDatabase.recipients(); - RecipientId selfId = Recipient.externalPush(new SignalServiceAddress(aci, registrationData.getE164())).getId(); + RecipientId selfId = Recipient.trustedPush(aci, pni, registrationData.getE164()).getId(); recipientDatabase.setProfileSharing(selfId, true); recipientDatabase.markRegisteredOrThrow(selfId, aci); - recipientDatabase.setPni(selfId, pni); + recipientDatabase.linkIdsForSelf(aci, pni, registrationData.getE164()); recipientDatabase.setProfileKey(selfId, registrationData.getProfileKey()); ApplicationDependencies.getRecipientCache().clearSelf();