Add & use RegisteredState

This commit is contained in:
Max Radermacher 2025-12-10 16:52:53 -06:00 committed by GitHub
parent 14c38514e0
commit 422d7547ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 230 additions and 237 deletions

View File

@ -695,6 +695,7 @@
5079F3C22DA47554008430EC /* NotificationPreconditionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5079F3C02DA47554008430EC /* NotificationPreconditionTest.swift */; };
507B69112C503FA800F1C6D7 /* CallLinkTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50552C302BAC079A00815474 /* CallLinkTest.swift */; };
507B69122C5044F800F1C6D7 /* LinkPreviewGroupLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A95517271B510400B05242 /* LinkPreviewGroupLink.swift */; };
507C6AF52ED10BD900A7C74C /* RegisteredState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507C6AF42ED10BD900A7C74C /* RegisteredState.swift */; };
507CD5E529660D5100E47DAC /* ServiceId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CD5E429660D5100E47DAC /* ServiceId.swift */; };
507E1BDF2A0E13B100650611 /* NSKeyedUnarchiver+SSK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507E1BDE2A0E13B100650611 /* NSKeyedUnarchiver+SSK.swift */; };
508622AD2D026F5200931BF9 /* CanonicalPhoneNumberTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508622AC2D026F5200931BF9 /* CanonicalPhoneNumberTest.swift */; };
@ -4871,6 +4872,7 @@
50791B1C2D037A9800D747F8 /* PhoneNumberCountryTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneNumberCountryTest.swift; sourceTree = "<group>"; };
5079F3B52DA4713C008430EC /* NotificationPrecondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPrecondition.swift; sourceTree = "<group>"; };
5079F3C02DA47554008430EC /* NotificationPreconditionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPreconditionTest.swift; sourceTree = "<group>"; };
507C6AF42ED10BD900A7C74C /* RegisteredState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisteredState.swift; sourceTree = "<group>"; };
507CD5E429660D5100E47DAC /* ServiceId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceId.swift; sourceTree = "<group>"; };
507D614B2BE433EE00DA7BA3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = translations/be.lproj/InfoPlist.strings; sourceTree = "<group>"; };
507D614C2BE433EE00DA7BA3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = translations/be.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -14741,6 +14743,7 @@
D9CAF74F2A0ACFF20049193A /* PniDistributionParameterBuilder.swift */,
C18E3C712A9FF65D003D1CF1 /* PniDistributionSyncMessage.swift */,
50D146CC2D1F4E5800D628DE /* ProfileKey.swift */,
507C6AF42ED10BD900A7C74C /* RegisteredState.swift */,
C1C2185C2E70BA27008567A1 /* RegistrationIdMismatchManager.swift */,
507CD5E429660D5100E47DAC /* ServiceId.swift */,
);
@ -19356,6 +19359,7 @@
66EB029B2BAB9F1C004F0580 /* ReferencedAttachment.swift in Sources */,
F9C5CE18289453B400548EEE /* Refinery.swift in Sources */,
720547F62B9C985300E2CF2F /* RefreshEvent.swift in Sources */,
507C6AF52ED10BD900A7C74C /* RegisteredState.swift in Sources */,
C13EDC3F2D94636000670597 /* Registration.pb.swift in Sources */,
661170C12ABA459D00A1B16D /* RegistrationIdGenerator.swift in Sources */,
C1C2185D2E70BA27008567A1 /* RegistrationIdMismatchManager.swift in Sources */,

View File

@ -794,16 +794,16 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
}
let recipientDatabaseTable = DependenciesBridge.shared.recipientDatabaseTable
let tsRegistrationState: TSRegistrationState = SSKEnvironment.shared.databaseStorageRef.read { tx in
let registrationState = tsAccountManager.registrationState(tx: tx)
if registrationState.isRegistered, let localIdentifiers = tsAccountManager.localIdentifiers(tx: tx) {
let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction()
SSKEnvironment.shared.databaseStorageRef.read { tx in
if let registeredState {
let localIdentifiers = registeredState.localIdentifiers
let deviceId = tsAccountManager.storedDeviceId(tx: tx)
let localRecipient = recipientDatabaseTable.fetchRecipient(serviceId: localIdentifiers.aci, transaction: tx)
let deviceCount = localRecipient?.deviceIds.count ?? 0
let linkedDeviceMessage = deviceCount > 1 ? "\(deviceCount) devices including the primary" : "no linked devices"
Logger.info("localAci: \(localIdentifiers.aci), deviceId: \(deviceId) (\(linkedDeviceMessage))")
}
return registrationState
}
let profileManager = SSKEnvironment.shared.profileManagerRef
@ -852,12 +852,12 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
self.refreshConnection(isAppActive: false, shouldRunCron: false)
}
if tsRegistrationState.isRegistered {
if registeredState != nil {
// This should happen at any launch, background or foreground.
SyncPushTokensJob.run()
}
if tsRegistrationState.isRegistered {
if registeredState != nil {
Task {
do {
try await APNSRotationStore.rotateIfNeededOnAppLaunchAndReadiness(
@ -878,7 +878,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
AppVersionImpl.shared.mainAppLaunchDidComplete()
scheduleBgAppRefresh()
Self.updateApplicationShortcutItems(isRegistered: tsRegistrationState.isRegistered)
Self.updateApplicationShortcutItems(isRegistered: registeredState != nil)
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(
@ -888,7 +888,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
object: nil
)
checkDatabaseIntegrityIfNecessary(isRegistered: tsRegistrationState.isRegistered)
checkDatabaseIntegrityIfNecessary(isRegistered: registeredState != nil)
SignalApp.shared.showLaunchInterface(
launchInterface,
@ -1388,13 +1388,14 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
Logger.info("Activated.")
}
let tsRegistrationState: TSRegistrationState = DependenciesBridge.shared.db.read { tx in
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction()
if registeredState != nil {
DependenciesBridge.shared.db.read { tx in
// Always check prekeys after app launches, and sometimes check on app activation.
let registrationState = DependenciesBridge.shared.tsAccountManager.registrationState(tx: tx)
if registrationState.isRegistered {
DependenciesBridge.shared.preKeyManager.checkPreKeysIfNecessary(tx: tx)
}
return registrationState
}
if !hasActivated {
@ -1406,7 +1407,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
// cleaning in the background.
SSKEnvironment.shared.disappearingMessagesJobRef.startIfNecessary()
if !tsRegistrationState.isRegistered {
if registeredState == nil {
// Unregistered user should have no unread messages. e.g. if you delete your account.
SSKEnvironment.shared.notificationPresenterRef.clearAllNotifications()
}
@ -1415,7 +1416,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
refreshConnection(isAppActive: true, shouldRunCron: true)
// Every time we become active...
if tsRegistrationState.isRegistered {
if registeredState != nil {
// TODO: Should we run this immediately even if we would like to process already decrypted envelopes handed to us by the NSE?
Task {
await SSKEnvironment.shared.groupMessageProcessorManagerRef.startAllProcessors()
@ -1639,10 +1640,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
break
case .notHandled:
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
Logger.info("Ignoring remote notification; user is not registered.")
return
}
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
let backgroundMessageFetcher = DependenciesBridge.shared.backgroundMessageFetcherFactory.buildFetcher()
await backgroundMessageFetcher.start()
@ -1838,15 +1836,11 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
scheduleBgAppRefresh()
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let isRegistered = tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered
if isRegistered {
appReadiness.runNowOrWhenAppDidBecomeReadySync {
SSKEnvironment.shared.databaseStorageRef.write { transaction in
let localAddress = tsAccountManager.localIdentifiers(tx: transaction)?.aciAddress
Logger.info("localAddress: \(String(describing: localAddress))")
ExperienceUpgradeFinder.markAllCompleteForNewUser(transaction: transaction)
}
let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction()
if let registeredState {
Logger.info("localAci: \(registeredState.localIdentifiers.aci)")
SSKEnvironment.shared.databaseStorageRef.write { transaction in
ExperienceUpgradeFinder.markAllCompleteForNewUser(transaction: transaction)
}
DependenciesBridge.shared.attachmentDownloadManager.beginDownloadingIfNecessary()
Task {
@ -1859,7 +1853,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
Self.updateApplicationShortcutItems(isRegistered: isRegistered)
Self.updateApplicationShortcutItems(isRegistered: registeredState != nil)
}
// MARK: - Shortcut Items

View File

@ -89,13 +89,11 @@ actor CallLinkStateUpdater {
}
}
guard let localIdentifiers = tsAccountManager.localIdentifiersWithMaybeSneakyTransaction else {
throw OWSGenericError("Not registered.")
}
let registeredState = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
let oldRecord = try db.read { tx -> CallLinkRecord? in
return try callLinkStore.fetch(roomId: roomId, tx: tx)
}
let authCredential = try await authCredentialManager.fetchCallLinkAuthCredential(localIdentifiers: localIdentifiers)
let authCredential = try await authCredentialManager.fetchCallLinkAuthCredential(localIdentifiers: registeredState.localIdentifiers)
let updateResult = await Result { try await updateAndFetch(authCredential) }
let updateAction: UpdateAction

View File

@ -1223,10 +1223,10 @@ class CallsListViewController: OWSViewController, HomeTabViewController, CallSer
}
private static nonisolated func peekCallLink(rootKey: CallLinkRootKey, deps: Dependencies) async throws {
guard let localIdentifiers = deps.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction else {
throw OWSGenericError("Not registered.")
}
let authCredential = try await deps.callService.authCredentialManager.fetchCallLinkAuthCredential(localIdentifiers: localIdentifiers)
let registeredState = try deps.tsAccountManager.registeredStateWithMaybeSneakyTransaction()
let authCredential = try await deps.callService.authCredentialManager.fetchCallLinkAuthCredential(
localIdentifiers: registeredState.localIdentifiers,
)
let eraId: String?
do {
eraId = try await deps.callService.callLinkManager.peekCallLink(rootKey: rootKey, authCredential: authCredential)

View File

@ -123,11 +123,9 @@ class UrlOpener {
@MainActor
func openUrl(_ parsedUrl: ParsedUrl, in window: UIWindow) {
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return owsFailDebug("Ignoring URL; not registered.")
}
guard let rootViewController = window.rootViewController else {
return owsFailDebug("Ignoring URL; no root view controller.")
owsFailDebug("Ignoring URL; no root view controller.")
return
}
if shouldDismiss(for: parsedUrl.openableUrl) && rootViewController.presentedViewController != nil {
rootViewController.dismiss(animated: false, completion: {
@ -147,11 +145,22 @@ class UrlOpener {
@MainActor
private func openUrlAfterDismissing(_ openableUrl: OpenableUrl, rootViewController: UIViewController) {
do throws(NotRegisteredError) {
try _openUrlAfterDismissing(openableUrl, rootViewController: rootViewController)
} catch {
Logger.warn("Ignoring url because we're not registered")
}
}
@MainActor
private func _openUrlAfterDismissing(_ openableUrl: OpenableUrl, rootViewController: UIViewController) throws(NotRegisteredError) {
switch openableUrl {
case .phoneNumberLink(let url):
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
SignalDotMePhoneNumberLink.openChat(url: url, fromViewController: rootViewController)
case .usernameLink(let link):
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
Task {
guard let (_, aci) = await UsernameQuerier().queryForUsernameLink(
link: link,
@ -167,18 +176,21 @@ class UrlOpener {
}
case .stickerPack(let stickerPackInfo):
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
let stickerPackViewController = StickerPackViewController(stickerPackInfo: stickerPackInfo)
stickerPackViewController.present(from: rootViewController, animated: false)
case .groupInvite(let url):
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
GroupInviteLinksUI.openGroupInviteLink(url, fromViewController: rootViewController)
case .signalProxy(let url):
rootViewController.present(ProxyLinkSheetViewController(url: url)!, animated: true)
case .linkDevice:
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegisteredPrimaryDevice else {
owsFailDebug("Ignoring URL; not primary device.")
let registeredState = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
guard registeredState.isPrimary else {
Logger.warn("Ignoring URL; not primary device.")
return
}
@ -203,9 +215,9 @@ class UrlOpener {
rootViewController.presentActionSheet(linkDeviceWarningActionSheet)
case .quickRestore(let url):
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegisteredPrimaryDevice else {
owsFailDebug("Ignoring URL; not primary device.")
let registeredState = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
guard registeredState.isPrimary else {
Logger.warn("Ignoring URL; not primary device.")
return
}
@ -219,6 +231,7 @@ class UrlOpener {
}
case .completeIDEALDonation(let donationType):
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
Task { [appReadiness, databaseStorage] in
let handled = await DonationViewsUtil.attemptToContinueActiveIDEALDonation(
type: donationType,
@ -245,6 +258,7 @@ class UrlOpener {
}
case .callLink(let callLink):
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
GroupCallViewController.presentLobby(for: callLink)
}
}

View File

@ -269,8 +269,8 @@ class AccountSettingsViewController: OWSTableViewController2 {
private func changeNumberState() -> ChangeNumberState {
return SSKEnvironment.shared.databaseStorageRef.read { transaction -> ChangeNumberState in
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let tsRegistrationState = tsAccountManager.registrationState(tx: transaction)
guard tsRegistrationState.isRegistered else {
let registeredState = try? tsAccountManager.registeredState(tx: transaction)
guard let registeredState else {
return .disallowed
}
let loader = RegistrationCoordinatorLoaderImpl(dependencies: .from(self))
@ -282,8 +282,7 @@ class AccountSettingsViewController: OWSTableViewController2 {
return .disallowed
}
guard
let localIdentifiers = tsAccountManager.localIdentifiers(tx: transaction),
let localE164 = E164(localIdentifiers.phoneNumber),
let localE164 = E164(registeredState.localIdentifiers.phoneNumber),
let authToken = tsAccountManager.storedServerAuthToken(tx: transaction),
let localDeviceId = tsAccountManager.storedDeviceId(tx: transaction).ifValid
else {
@ -293,7 +292,7 @@ class AccountSettingsViewController: OWSTableViewController2 {
return .allowed(RegistrationMode.ChangeNumberParams(
oldE164: localE164,
oldAuthToken: authToken,
localAci: localIdentifiers.aci,
localAci: registeredState.localIdentifiers.aci,
localDeviceId: localDeviceId
))
}

View File

@ -151,13 +151,9 @@ class IdentityKeyMismatchManagerImpl: IdentityKeyMismatchManager {
let localIdentifier: ServiceId
do {
let loadLocalIdentifiers = { [db, tsAccountManager] () throws -> LocalIdentifiers in
let localIdentifiers = db.read { tx in
return tsAccountManager.localIdentifiers(tx: tx)
return try db.read { tx in
return try tsAccountManager.registeredState(tx: tx).localIdentifiers
}
guard let localIdentifiers else {
throw OWSGenericError("not registered")
}
return localIdentifiers
}
switch identity {

View File

@ -0,0 +1,20 @@
//
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public struct RegisteredState {
public let isPrimary: Bool
public let localIdentifiers: LocalIdentifiers
init(registrationState: TSRegistrationState, localIdentifiers: LocalIdentifiers?) throws(NotRegisteredError) {
guard registrationState.isRegistered else {
throw NotRegisteredError()
}
// These are both valid when we're registered.
self.isPrimary = registrationState.isPrimaryDevice!
self.localIdentifiers = localIdentifiers!
}
}

View File

@ -34,26 +34,19 @@ public class RegistrationIdMismatchManagerImpl: RegistrationIdMismatchManager {
return
}
guard db.read(block: {
tsAccountManager.registrationState(tx: $0).isRegistered
guard let registeredState = db.read(block: { tx in
return try? tsAccountManager.registeredState(tx: tx)
}) else {
Logger.warn("Attempting to check registrationId while unregistered.")
return
}
guard let localIdentifiers = db.read(block: {
tsAccountManager.localIdentifiers(tx: $0)
}) else {
owsFailDebug("Missing local identifiers during registrationId check")
return
}
do {
// Check ACI
try await _checkRegistrationIdMatches(identity: .aci, serviceId: localIdentifiers.aci)
try await _checkRegistrationIdMatches(identity: .aci, serviceId: registeredState.localIdentifiers.aci)
// Check PNI
if let pni = localIdentifiers.pni {
if let pni = registeredState.localIdentifiers.pni {
try await _checkRegistrationIdMatches(identity: .pni, serviceId: pni)
} else {
owsFailDebug("Missing PNI during registrationId check")

View File

@ -111,6 +111,20 @@ public enum LocalDeviceId: CustomStringConvertible {
}
extension TSAccountManager {
public func registeredStateWithMaybeSneakyTransaction() throws(NotRegisteredError) -> RegisteredState {
return try RegisteredState(
registrationState: self.registrationStateWithMaybeSneakyTransaction,
localIdentifiers: self.localIdentifiersWithMaybeSneakyTransaction,
)
}
public func registeredState(tx: DBReadTransaction) throws(NotRegisteredError) -> RegisteredState {
return try RegisteredState(
registrationState: self.registrationState(tx: tx),
localIdentifiers: self.localIdentifiers(tx: tx),
)
}
public func localIdentifiersWithMaybeSneakyTransaction(authedAccount: AuthedAccount) throws -> LocalIdentifiers {
switch authedAccount.info {
case .explicit(let info):

View File

@ -173,10 +173,7 @@ public class BackupArchiveAvatarFetcher {
record: Record,
loader: TaskQueueLoader<TaskRunner>
) async -> TaskRecordResult {
guard
tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered,
let localIdentifiers = tsAccountManager.localIdentifiersWithMaybeSneakyTransaction
else {
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
try? await loader.stop()
return .cancelled
}
@ -198,7 +195,7 @@ public class BackupArchiveAvatarFetcher {
}
do {
if localIdentifiers.contains(serviceId: serviceId) {
if registeredState.localIdentifiers.contains(serviceId: serviceId) {
_ = try await profileManager.fetchLocalUsersProfile(
authedAccount: .implicit()
)

View File

@ -4,6 +4,7 @@
//
import Foundation
import LibSignalClient
public protocol BackupAttachmentUploadQueueRunner {
@ -415,17 +416,18 @@ class BackupAttachmentUploadQueueRunnerImpl: BackupAttachmentUploadQueueRunner {
break
}
let (localAci, isRegisteredPrimaryDevice) = db.read { tx in
return (
self.tsAccountManager.localIdentifiers(tx: tx)?.aci,
self.tsAccountManager.registrationState(tx: tx).isRegisteredPrimaryDevice,
)
let localAci: Aci
let isPrimary: Bool
do throws(NotRegisteredError) {
let registeredState = try self.tsAccountManager.registeredStateWithMaybeSneakyTransaction()
localAci = registeredState.localIdentifiers.aci
isPrimary = registeredState.isPrimary
} catch {
try? await loader.stop(reason: error)
return .retryableError(error)
}
guard
isRegisteredPrimaryDevice,
let localAci
else {
let error = OWSAssertionError("Not registered!")
guard isPrimary else {
let error = OWSAssertionError("not primary")
try? await loader.stop(reason: error)
return .retryableError(error)
}

View File

@ -82,15 +82,11 @@ extension OWSSyncManager: SyncManagerProtocolObjc {
private func _sendConfigurationSyncMessage(tx: DBWriteTransaction) {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationState(tx: tx).isRegistered else {
return
}
guard let thread = TSContactThread.getOrCreateLocalThread(transaction: tx) else {
owsFailDebug("Missing thread.")
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return
}
let thread = TSContactThread.getOrCreateThread(withContactAddress: registeredState.localIdentifiers.aciAddress, transaction: tx)
let linkPreviews = DependenciesBridge.shared.linkPreviewSettingStore.areLinkPreviewsEnabled(tx: tx)
let readReceipts = OWSReceiptManager.areReadReceiptsEnabled(transaction: tx)
let sealedSenderIndicators = SSKEnvironment.shared.preferencesRef.shouldShowUnidentifiedDeliveryIndicators(transaction: tx)
@ -140,9 +136,8 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
}
private func _sendAllSyncRequestMessages(onlyIfNecessary: Bool) async throws {
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
throw OWSAssertionError("Unexpectedly tried to send sync request before registration.")
}
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
let databaseStorage = SSKEnvironment.shared.databaseStorageRef
let completionGuarantees = await databaseStorage.awaitableWrite { (transaction) -> [Guarantee<Notification>] in
@ -186,16 +181,19 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
public func sendKeysSyncMessage() {
Logger.info("")
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return owsFailDebug("Unexpectedly tried to send sync request before registration.")
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
owsFailDebug("Unexpectedly tried to send sync request before registration.")
return
}
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isPrimaryDevice ?? false else {
return owsFailDebug("Keys sync should only be initiated from the primary device")
guard registeredState.isPrimary else {
owsFailDebug("Keys sync should only be initiated from the primary device")
return
}
SSKEnvironment.shared.databaseStorageRef.asyncWrite { [weak self] transaction in
self?.sendKeysSyncMessage(tx: transaction)
SSKEnvironment.shared.databaseStorageRef.asyncWrite { transaction in
self.sendKeysSyncMessage(tx: transaction)
}
}
@ -360,12 +358,14 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
public func sendMessageRequestResponseSyncMessage(thread: TSThread, responseType: OWSSyncMessageRequestResponseType) {
Logger.info("")
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return owsFailDebug("Unexpectedly tried to send sync message before registration.")
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
owsFailDebug("Unexpectedly tried to send sync message before registration.")
return
}
SSKEnvironment.shared.databaseStorageRef.asyncWrite { [weak self] transaction in
self?.sendMessageRequestResponseSyncMessage(thread: thread, responseType: responseType, transaction: transaction)
SSKEnvironment.shared.databaseStorageRef.asyncWrite { transaction in
self.sendMessageRequestResponseSyncMessage(thread: thread, responseType: responseType, transaction: transaction)
}
}
@ -376,15 +376,17 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
) {
Logger.info("")
guard DependenciesBridge.shared.tsAccountManager.registrationState(tx: transaction).isRegistered else {
return owsFailDebug("Unexpectedly tried to send sync message before registration.")
}
guard let localThread = TSContactThread.getOrCreateLocalThread(transaction: transaction) else {
owsFailDebug("Couldn't get localThread.")
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: transaction) else {
owsFailDebug("Unexpectedly tried to send sync message before registration.")
return
}
let localThread = TSContactThread.getOrCreateThread(
withContactAddress: registeredState.localIdentifiers.aciAddress,
transaction: transaction,
)
let syncMessageRequestResponse = OWSSyncMessageRequestResponseMessage(
localThread: localThread,
messageRequestThread: thread,
@ -465,9 +467,8 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let (localIdentifiers, hasAnyLinkedDevice) = try SSKEnvironment.shared.databaseStorageRef.read { tx in
guard let localIdentifiers = tsAccountManager.localIdentifiers(tx: tx) else {
throw OWSError(error: .contactSyncFailed, description: "Not registered.", isRetryable: false)
}
let registeredState = try tsAccountManager.registeredState(tx: tx)
let localIdentifiers = registeredState.localIdentifiers
let localRecipient = recipientDatabaseTable.fetchRecipient(serviceId: localIdentifiers.aci, transaction: tx)
return (localIdentifiers, (localRecipient?.deviceIds ?? []).count >= 2)
}
@ -599,15 +600,15 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
private func _sendFetchLatestSyncMessage(type: OWSSyncFetchType, tx: DBWriteTransaction) {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationState(tx: tx).isRegistered else {
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
owsFailDebug("Tried to send sync message before registration.")
return
}
guard let thread = TSContactThread.getOrCreateLocalThread(transaction: tx) else {
owsFailDebug("Missing thread.")
return
}
let thread = TSContactThread.getOrCreateThread(
withContactAddress: registeredState.localIdentifiers.aciAddress,
transaction: tx,
)
let fetchLatestSyncMessage = OWSSyncFetchLatestMessage(localThread: thread, fetchType: type, transaction: tx)
let preparedMessage = PreparedOutgoingMessage.preprepared(
@ -660,7 +661,8 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
public func sendInitialSyncRequestsAwaitingCreatedThreadOrdering(timeoutSeconds: TimeInterval) -> Promise<[String]> {
Logger.info("")
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return Promise(error: OWSAssertionError("Unexpectedly tried to send sync request before registration."))
}
@ -698,17 +700,21 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
Logger.info("keys")
}
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return owsFailDebug("Unexpectedly tried to send sync request before registration.")
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
owsFailDebug("Unexpectedly tried to send sync request before registration.")
return
}
guard !DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegisteredPrimaryDevice else {
return owsFailDebug("Sync request should only be sent from a linked device")
guard !registeredState.isPrimary else {
owsFailDebug("Sync request should only be sent from a linked device")
return
}
guard let thread = TSContactThread.getOrCreateLocalThread(transaction: transaction) else {
return owsFailDebug("Missing thread")
}
let thread = TSContactThread.getOrCreateThread(
withContactAddress: registeredState.localIdentifiers.aciAddress,
transaction: transaction,
)
let syncRequestMessage = OWSSyncRequestMessage(localThread: thread, requestType: requestType.rawValue, transaction: transaction)
let preparedMessage = PreparedOutgoingMessage.preprepared(

View File

@ -166,20 +166,15 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
tokenId: DeviceProvisioningTokenId,
progress: OWSSequentialProgressRootSink<PrimaryLinkNSyncProgressPhase>
) async throws(PrimaryLinkNSyncError) {
let (localIdentifiers, registrationState) = db.read { tx in
return (
tsAccountManager.localIdentifiers(tx: tx),
tsAccountManager.registrationState(tx: tx)
)
}
guard let localIdentifiers else {
owsFailDebug("Not registered!")
return
}
guard registrationState.isPrimaryDevice == true else {
owsFailDebug("Non-primary device waiting for secondary linking")
let registeredState: RegisteredState
do throws(NotRegisteredError) {
registeredState = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
} catch {
// TODO: Throw an error to indicate this failed because we're not registered.
Logger.warn("Couldn't wait for linking because we're no longer registered")
return
}
owsPrecondition(registeredState.isPrimary, "Can't wait for linking unless we're a primary")
let blockObject = DeviceSleepBlockObject(blockReason: Constants.sleepBlockingDescription)
await deviceSleepManager?.addBlock(blockObject: blockObject)
@ -235,7 +230,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
backupMetadata = try await generateBackup(
waitForDeviceToLinkResponse: waitForLinkResponse,
ephemeralBackupKey: ephemeralBackupKey,
localIdentifiers: localIdentifiers,
localIdentifiers: registeredState.localIdentifiers,
progress: progress.child(for: .exportingBackup)
)
} catch let error {

View File

@ -1280,21 +1280,17 @@ public class GroupManager: NSObject {
}
private static func _ensureLocalProfileHasCommitmentIfNecessary() async throws {
let accountManager = DependenciesBridge.shared.tsAccountManager
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let registeredState = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
func hasProfileKeyCredential() throws -> Bool {
return try SSKEnvironment.shared.databaseStorageRef.read { tx in
guard accountManager.registrationState(tx: tx).isRegistered else {
return false
}
guard let localAci = accountManager.localIdentifiers(tx: tx)?.aci else {
throw OWSAssertionError("Missing localAci.")
}
func hasProfileKeyCredential() -> Bool {
return SSKEnvironment.shared.databaseStorageRef.read { tx in
let localAci = registeredState.localIdentifiers.aci
return SSKEnvironment.shared.groupsV2Ref.hasProfileKeyCredential(for: localAci, transaction: tx)
}
}
guard try !hasProfileKeyCredential() else {
guard !hasProfileKeyCredential() else {
return
}
@ -1303,16 +1299,11 @@ public class GroupManager: NSObject {
// would get as part of fetching our local profile).
_ = try await SSKEnvironment.shared.profileManagerRef.fetchLocalUsersProfile(authedAccount: .implicit())
guard try !hasProfileKeyCredential() else {
guard !hasProfileKeyCredential() else {
return
}
guard
CurrentAppContext().isMainApp,
SSKEnvironment.shared.databaseStorageRef.read(block: { tx in
accountManager.registrationState(tx: tx).isRegisteredPrimaryDevice
})
else {
guard registeredState.isPrimary, CurrentAppContext().isMainApp else {
Logger.warn("Skipping upload of local profile key commitment, not in main app!")
return
}

View File

@ -525,20 +525,11 @@ private class DonationReceiptCredentialRedemptionJobRunner: JobRunner {
// Now that we know what type of job we are, suffix the logger.
logger = logger.suffixed(with: "[\(configuration.paymentType)]")
let (
registrationState,
badgesSnapshotBeforeJob,
) = db.read { tx in
return (
tsAccountManager.registrationState(tx: tx),
// In order to properly show the "you have a new badge" UI after this job
// succeeds, we need to know what badges we had beforehand.
ProfileBadgesSnapshot.forLocalProfile(profileManager: profileManager, tx: tx),
)
}
guard registrationState.isRegistered else {
throw OWSAssertionError("Attempting to redeem a donation, but not registered!")
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
let badgesSnapshotBeforeJob = db.read { tx in
// In order to properly show the "you have a new badge" UI after this job
// succeeds, we need to know what badges we had beforehand.
return ProfileBadgesSnapshot.forLocalProfile(profileManager: profileManager, tx: tx)
}
logger.info("Running job.")

View File

@ -427,13 +427,12 @@ public class BlockingManager {
}
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationState(tx: tx).isRegistered else {
throw OWSGenericError("Not registered.")
}
let registeredState = try tsAccountManager.registeredState(tx: tx)
guard let localThread = TSContactThread.getOrCreateLocalThread(transaction: tx) else {
throw OWSAssertionError("Missing thread.")
}
let localThread = TSContactThread.getOrCreateThread(
withContactAddress: registeredState.localIdentifiers.aciAddress,
transaction: tx,
)
let recipientDatabaseTable = DependenciesBridge.shared.recipientDatabaseTable
let blockedRecipients = try blockedRecipientStore.blockedRecipientIds(tx: tx).compactMap {

View File

@ -159,7 +159,6 @@ public class MessageProcessor {
private func drainPendingEnvelopes() {
guard CurrentAppContext().shouldProcessIncomingMessages else { return }
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else { return }
guard SSKEnvironment.shared.messagePipelineSupervisorRef.isMessageProcessingPermitted else { return }
queueForProcessing.async {

View File

@ -604,9 +604,7 @@ public class MessageSender {
throw AppExpiredError()
}
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
if !tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered {
throw NotRegisteredError()
}
_ = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
if message.shouldBeSaved {
let latestCopy = SSKEnvironment.shared.databaseStorageRef.read { tx in
TSInteraction.anyFetch(uniqueId: message.uniqueId, transaction: tx) as? TSOutgoingMessage

View File

@ -593,13 +593,10 @@ public class OWSIdentityManagerImpl: OWSIdentityManager {
}
private func syncQueuedVerificationStates() {
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return
}
guard let thread = TSContactThread.getOrCreateLocalThreadWithSneakyTransaction() else {
owsFailDebug("Missing thread.")
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
return
}
let thread = TSContactThread.getOrCreateThread(contactAddress: registeredState.localIdentifiers.aciAddress)
let allKeys = db.read { tx in queuedVerificationStateSyncMessagesKeyValueStore.allKeys(transaction: tx) }
// We expect very few keys in practice, and each key triggers multiple
// database write transactions. If we do end up with thousands of keys,

View File

@ -1096,13 +1096,14 @@ public class StickerManager: NSObject {
packs: [StickerPackInfo],
transaction: DBWriteTransaction
) {
guard DependenciesBridge.shared.tsAccountManager.registrationState(tx: transaction).isRegistered else {
return
}
guard let thread = TSContactThread.getOrCreateLocalThread(transaction: transaction) else {
owsFailDebug("Missing thread.")
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: transaction) else {
return
}
let thread = TSContactThread.getOrCreateThread(
withContactAddress: registeredState.localIdentifiers.aciAddress,
transaction: transaction,
)
let message = OWSStickerPackSyncMessage(
localThread: thread,
packs: packs,

View File

@ -296,10 +296,7 @@ public class OWSUDManagerImpl: OWSUDManager {
}
private func _fetchSenderCertificates(forceRefresh: Bool) async throws -> SenderCertificates {
guard self.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
// We don't want to assert but we should log and fail.
throw OWSGenericError("Not registered and ready.")
}
_ = try self.tsAccountManager.registeredStateWithMaybeSneakyTransaction()
async let defaultCert = fetchSenderCertificate(aciOnly: false, forceRefresh: forceRefresh)
async let aciOnlyCert = fetchSenderCertificate(aciOnly: true, forceRefresh: forceRefresh)
return SenderCertificates(

View File

@ -29,12 +29,11 @@ public class PaymentsHelperImpl: PaymentsHelperSwift, PaymentsHelper {
}
public var hasValidPhoneNumberForPayments: Bool {
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
return false
}
guard let localNumber = DependenciesBridge.shared.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.phoneNumber else {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
return false
}
let localNumber = registeredState.localIdentifiers.phoneNumber
let paymentsDisabledRegions = RemoteConfig.current.paymentsDisabledRegions
if paymentsDisabledRegions.isEmpty {
return Self.isValidPhoneNumberForPayments_fixedAllowlist(localNumber)

View File

@ -707,8 +707,10 @@ extension OWSProfileManager: ProfileManager {
triggers: [RotateProfileKeyTrigger],
authedAccount: AuthedAccount
) async throws -> Bool {
guard DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegisteredPrimaryDevice else {
throw OWSAssertionError("tsAccountManager.isRegistered was unexpectedly false")
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
let registeredState = try tsAccountManager.registeredStateWithMaybeSneakyTransaction()
guard registeredState.isPrimary else {
throw OWSAssertionError("not a primary device")
}
Logger.info("Beginning profile key rotation.")
@ -738,9 +740,7 @@ extension OWSProfileManager: ProfileManager {
}
try await uploadPromise.awaitable()
guard let localAci = DependenciesBridge.shared.tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.aci else {
throw OWSAssertionError("Missing localAci.")
}
let localAci = registeredState.localIdentifiers.aci
Logger.info("Persisting rotated profile key and kicking off subsequent operations.")
@ -1489,11 +1489,11 @@ extension OWSProfileManager: ProfileManager {
///
/// - Parameter tx: The transaction to use for this operation.
func rotateProfileKeyUponRecipientHideObjC(tx: DBWriteTransaction) {
let tsRegistrationState = DependenciesBridge.shared.tsAccountManager.registrationState(tx: tx)
guard tsRegistrationState.isRegistered else {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return
}
guard tsRegistrationState.isPrimaryDevice ?? false else {
guard registeredState.isPrimary else {
return
}
// We schedule in the NSE by writing state; the actual rotation
@ -1503,11 +1503,11 @@ extension OWSProfileManager: ProfileManager {
}
fileprivate func _forceRotateLocalProfileKeyForGroupDeparture(tx: DBWriteTransaction) {
let tsRegistrationState = DependenciesBridge.shared.tsAccountManager.registrationState(tx: tx)
guard tsRegistrationState.isRegistered else {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return
}
guard tsRegistrationState.isPrimaryDevice ?? false else {
guard registeredState.isPrimary else {
return
}
// We schedule in the NSE by writing state; the actual rotation

View File

@ -47,18 +47,14 @@ class MasterKeySyncManagerImpl: MasterKeySyncManager {
}
func runStartupJobs(tx: DBWriteTransaction) {
switch tsAccountManager.registrationState(tx: tx) {
case .registered:
runStartupJobsForPrimaryDevice(tx: tx)
case .provisioned:
runStartupJobsForLinkedDevice(tx: tx)
case .delinked, .deregistered, .unregistered, .transferred,
.transferringIncoming, .transferringLinkedOutgoing,
.transferringPrimaryOutgoing,
.reregistering, .relinking:
logger.info("Skipping; not registered")
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return
}
if registeredState.isPrimary {
runStartupJobsForPrimaryDevice(tx: tx)
} else {
runStartupJobsForLinkedDevice(tx: tx)
}
}
private func runStartupJobsForPrimaryDevice(tx: DBWriteTransaction) {

View File

@ -447,8 +447,8 @@ public class StorageServiceManagerImpl: NSObject, StorageServiceManager {
case .implicit:
// Under the new reg flow, we will sync kbs keys before being fully ready with
// ts account manager auth set up. skip if so.
let registrationState = DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction
guard registrationState.isRegistered else {
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
Logger.info("Skipping storage service operation with implicit auth during registration.")
return nil
}
@ -460,11 +460,7 @@ public class StorageServiceManagerImpl: NSObject, StorageServiceManager {
return nil
}
localIdentifiers = implicitLocalIdentifiers
guard let implicitIsPrimaryDevice = registrationState.isPrimaryDevice else {
owsFailDebug("Trying to perform storage service operation without isPrimaryDevice.")
return nil
}
isPrimaryDevice = implicitIsPrimaryDevice
isPrimaryDevice = registeredState.isPrimary
}
return {

View File

@ -346,8 +346,8 @@ public class StorageServiceUnknownFieldMigrator {
return
}
guard let isPrimaryDevice = DependenciesBridge.shared.tsAccountManager.registrationState(tx: tx).isPrimaryDevice else {
// Not registered!
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return
}
@ -356,7 +356,7 @@ public class StorageServiceUnknownFieldMigrator {
migration: Migration
) {
let filteredRecords = records.compactMap { $0 as? Migration.RecordType }
migration.mergeUnknownFields(filteredRecords, isPrimaryDevice, tx)
migration.mergeUnknownFields(filteredRecords, registeredState.isPrimary, tx)
}
necessaryMigrations.forEach { migrationId in
@ -378,8 +378,8 @@ public class StorageServiceUnknownFieldMigrator {
return record
}
guard let isPrimaryDevice = DependenciesBridge.shared.tsAccountManager.registrationState(tx: tx).isPrimaryDevice else {
// Not registered!
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return record
}
@ -393,7 +393,7 @@ public class StorageServiceUnknownFieldMigrator {
}
let builder = _builder ?? record.asBuilder()
var typecastBuilder = builder as! Migration.RecordType.Builder
migration.interceptRemoteManifest(record as! Migration.RecordType, &typecastBuilder, isPrimaryDevice, tx)
migration.interceptRemoteManifest(record as! Migration.RecordType, &typecastBuilder, registeredState.isPrimary, tx)
_builder = (typecastBuilder as! RecordType.Builder)
}
@ -421,8 +421,8 @@ public class StorageServiceUnknownFieldMigrator {
return record
}
guard let isPrimaryDevice = DependenciesBridge.shared.tsAccountManager.registrationState(tx: tx).isPrimaryDevice else {
// Not registered!
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard let registeredState = try? tsAccountManager.registeredState(tx: tx) else {
return record
}
@ -436,7 +436,7 @@ public class StorageServiceUnknownFieldMigrator {
}
let builder = _builder ?? record.asBuilder()
var typecastBuilder = builder as! Migration.RecordType.Builder
migration.interceptLocalManifest(record as! Migration.RecordType, &typecastBuilder, isPrimaryDevice, tx)
migration.interceptLocalManifest(record as! Migration.RecordType, &typecastBuilder, registeredState.isPrimary, tx)
_builder = (typecastBuilder as! RecordType.Builder)
}

View File

@ -153,17 +153,14 @@ public class DonationUtilities {
inMode donationMode: DonationMode,
tsAccountManager: TSAccountManager,
) -> Bool {
let registrationState = tsAccountManager.registrationStateWithMaybeSneakyTransaction
let localNumber = tsAccountManager.localIdentifiersWithMaybeSneakyTransaction?.phoneNumber
guard registrationState.isRegistered else {
guard let registeredState = try? tsAccountManager.registeredStateWithMaybeSneakyTransaction() else {
// Don't allow donations if unregistered.
return false
}
return !supportedDonationPaymentMethods(
forDonationMode: donationMode,
localNumber: localNumber
localNumber: registeredState.localIdentifiers.phoneNumber,
).isEmpty
}