Scaffold for Backup integration tests
This commit is contained in:
parent
3526c2b650
commit
3ffcc47a66
@ -1786,6 +1786,9 @@
|
||||
D9AE0ADB29188A170063488B /* LegacyMessageDecryptJobRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AE0ADA29188A170063488B /* LegacyMessageDecryptJobRecord.swift */; };
|
||||
D9AE0ADD2918B2960063488B /* JobRecord+Columns.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9AE0ADC2918B2960063488B /* JobRecord+Columns.swift */; };
|
||||
D9B0AC7429EF42960070F31C /* TSInfoMessage+DisplayableGroupUpdateItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9B0AC7329EF42960070F31C /* TSInfoMessage+DisplayableGroupUpdateItem.swift */; };
|
||||
D9B6FD752BF2B94A00BB7DF1 /* account-data.jsonproto in Resources */ = {isa = PBXBuildFile; fileRef = D9B6FD742BF2B94A00BB7DF1 /* account-data.jsonproto */; };
|
||||
D9B6FD7A2BF40A7200BB7DF1 /* unregistered-contact.jsonproto in Resources */ = {isa = PBXBuildFile; fileRef = D9B6FD782BF40A7200BB7DF1 /* unregistered-contact.jsonproto */; };
|
||||
D9B6FD852BF53FCF00BB7DF1 /* registered-blocked-contact.jsonproto in Resources */ = {isa = PBXBuildFile; fileRef = D9B6FD7C2BF53C0100BB7DF1 /* registered-blocked-contact.jsonproto */; };
|
||||
D9B8541229137C150058F97B /* JobRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9B8541129137C150058F97B /* JobRecord.swift */; };
|
||||
D9B95A9629E6830B00D7CB95 /* JobRecordTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9B95A9429E682E900D7CB95 /* JobRecordTest.swift */; };
|
||||
D9B95A9829E8906200D7CB95 /* OWSDeviceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9B95A9729E8906200D7CB95 /* OWSDeviceTest.swift */; };
|
||||
@ -1814,6 +1817,8 @@
|
||||
D9C964092BE44D700058F143 /* XCTest+Thenable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C964072BE44D510058F143 /* XCTest+Thenable.swift */; };
|
||||
D9C964102BE451CE0058F143 /* TSMessageStorageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C9640F2BE451CE0058F143 /* TSMessageStorageTest.swift */; };
|
||||
D9C964142BE45A030058F143 /* SignedPreKeyDeletionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C964132BE45A030058F143 /* SignedPreKeyDeletionTests.swift */; };
|
||||
D9C964172BE56DFB0058F143 /* MessageBackupIntegrationTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C964162BE56DFB0058F143 /* MessageBackupIntegrationTestCase.swift */; };
|
||||
D9C964192BE59E270058F143 /* MessageBackupIntegrationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C964182BE59E270058F143 /* MessageBackupIntegrationTest.swift */; };
|
||||
D9CA5BF729B3F61E00D9AAD1 /* LegacyChangePhoneNumber+ChangeTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA5BF629B3F61E00D9AAD1 /* LegacyChangePhoneNumber+ChangeTokens.swift */; };
|
||||
D9CA8AB02B698DFF00787167 /* DeletedCallRecordCleanupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA8AAF2B698DFF00787167 /* DeletedCallRecordCleanupManager.swift */; };
|
||||
D9CA8AB32B6ACC0600787167 /* DeletedCallRecordCleanupManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA8AB22B6ACC0600787167 /* DeletedCallRecordCleanupManagerTest.swift */; };
|
||||
@ -4691,6 +4696,9 @@
|
||||
D9AE0ADA29188A170063488B /* LegacyMessageDecryptJobRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyMessageDecryptJobRecord.swift; sourceTree = "<group>"; };
|
||||
D9AE0ADC2918B2960063488B /* JobRecord+Columns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JobRecord+Columns.swift"; sourceTree = "<group>"; };
|
||||
D9B0AC7329EF42960070F31C /* TSInfoMessage+DisplayableGroupUpdateItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSInfoMessage+DisplayableGroupUpdateItem.swift"; sourceTree = "<group>"; };
|
||||
D9B6FD742BF2B94A00BB7DF1 /* account-data.jsonproto */ = {isa = PBXFileReference; lastKnownFileType = text; path = "account-data.jsonproto"; sourceTree = "<group>"; };
|
||||
D9B6FD782BF40A7200BB7DF1 /* unregistered-contact.jsonproto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "unregistered-contact.jsonproto"; sourceTree = "<group>"; };
|
||||
D9B6FD7C2BF53C0100BB7DF1 /* registered-blocked-contact.jsonproto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "registered-blocked-contact.jsonproto"; sourceTree = "<group>"; };
|
||||
D9B8541129137C150058F97B /* JobRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRecord.swift; sourceTree = "<group>"; };
|
||||
D9B91D8D2B17E2A600BCB11A /* GroupCallRecordRingUpdateDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCallRecordRingUpdateDelegate.swift; sourceTree = "<group>"; };
|
||||
D9B95A9429E682E900D7CB95 /* JobRecordTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRecordTest.swift; sourceTree = "<group>"; };
|
||||
@ -4721,6 +4729,8 @@
|
||||
D9C964072BE44D510058F143 /* XCTest+Thenable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTest+Thenable.swift"; sourceTree = "<group>"; };
|
||||
D9C9640F2BE451CE0058F143 /* TSMessageStorageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSMessageStorageTest.swift; sourceTree = "<group>"; };
|
||||
D9C964132BE45A030058F143 /* SignedPreKeyDeletionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignedPreKeyDeletionTests.swift; sourceTree = "<group>"; };
|
||||
D9C964162BE56DFB0058F143 /* MessageBackupIntegrationTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBackupIntegrationTestCase.swift; sourceTree = "<group>"; };
|
||||
D9C964182BE59E270058F143 /* MessageBackupIntegrationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBackupIntegrationTest.swift; sourceTree = "<group>"; };
|
||||
D9CA5BF629B3F61E00D9AAD1 /* LegacyChangePhoneNumber+ChangeTokens.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LegacyChangePhoneNumber+ChangeTokens.swift"; sourceTree = "<group>"; };
|
||||
D9CA8AAF2B698DFF00787167 /* DeletedCallRecordCleanupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedCallRecordCleanupManager.swift; sourceTree = "<group>"; };
|
||||
D9CA8AB22B6ACC0600787167 /* DeletedCallRecordCleanupManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedCallRecordCleanupManagerTest.swift; sourceTree = "<group>"; };
|
||||
@ -9575,6 +9585,16 @@
|
||||
path = Individual;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9B6FD732BF2B92000BB7DF1 /* TestCases */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9B6FD742BF2B94A00BB7DF1 /* account-data.jsonproto */,
|
||||
D9B6FD7C2BF53C0100BB7DF1 /* registered-blocked-contact.jsonproto */,
|
||||
D9B6FD782BF40A7200BB7DF1 /* unregistered-contact.jsonproto */,
|
||||
);
|
||||
path = TestCases;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9B95A9329E682CA00D7CB95 /* JobRecords */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -9604,6 +9624,16 @@
|
||||
path = ChangePhoneNumber;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9C964152BE56DE20058F143 /* MessageBackup */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D9B6FD732BF2B92000BB7DF1 /* TestCases */,
|
||||
D9C964182BE59E270058F143 /* MessageBackupIntegrationTest.swift */,
|
||||
D9C964162BE56DFB0058F143 /* MessageBackupIntegrationTestCase.swift */,
|
||||
);
|
||||
path = MessageBackup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9CA8AAD2B698B2400787167 /* DeletedCallRecord */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -10202,6 +10232,7 @@
|
||||
5075C21529CA1ED500A260D2 /* GroupMembers */,
|
||||
F94261E2289B1B5400460798 /* Groups */,
|
||||
5000CA2F2B1F97DC00BB8EFF /* Jobs */,
|
||||
D9C964152BE56DE20058F143 /* MessageBackup */,
|
||||
F942621C289B1B5500460798 /* Messages */,
|
||||
D9F399B72A9EA1EB001599EC /* Mocks */,
|
||||
F94261CF289B1B5400460798 /* Network */,
|
||||
@ -11988,10 +12019,13 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D9B6FD752BF2B94A00BB7DF1 /* account-data.jsonproto in Resources */,
|
||||
D9B6FD852BF53FCF00BB7DF1 /* registered-blocked-contact.jsonproto in Resources */,
|
||||
F942628B289B1B5600460798 /* sample-sticker.encrypted in Resources */,
|
||||
F942628C289B1B5600460798 /* sample-sticker.webp in Resources */,
|
||||
F908AA7D28CE629700472E68 /* test-apng.png in Resources */,
|
||||
F927478828CFE9B10056EAFE /* test-png.png in Resources */,
|
||||
D9B6FD7A2BF40A7200BB7DF1 /* unregistered-contact.jsonproto in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -14594,6 +14628,8 @@
|
||||
D938307C2A704338006CDCDE /* LocalUsernameManagerTests.swift in Sources */,
|
||||
F942625F289B1B5500460798 /* LRUCacheTest.swift in Sources */,
|
||||
F9426269289B1B5500460798 /* MathOWSTests.swift in Sources */,
|
||||
D9C964192BE59E270058F143 /* MessageBackupIntegrationTest.swift in Sources */,
|
||||
D9C964172BE56DFB0058F143 /* MessageBackupIntegrationTestCase.swift in Sources */,
|
||||
66FC637229DF7A1500F00DAC /* MessageBodyRangesTests.swift in Sources */,
|
||||
668444822A3292AB00DBED7C /* MessageBodyStyleTests.swift in Sources */,
|
||||
66883A3A29D7630A00E898CF /* MessageBodyTests.swift in Sources */,
|
||||
|
||||
@ -446,7 +446,7 @@ class DebugUIMisc: NSObject, DebugUIPage, Dependencies {
|
||||
updateStorageService: false, /* storage service updated below */
|
||||
transaction: transaction
|
||||
)
|
||||
StoryManager.setHasSetMyStoriesPrivacy(false, transaction: transaction, shouldUpdateStorageService: true)
|
||||
StoryManager.setHasSetMyStoriesPrivacy(false, shouldUpdateStorageService: true, transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,6 @@ public class PerformanceBaseTest: XCTestCase {
|
||||
// MARK: Hooks
|
||||
|
||||
func setUpIteration() {
|
||||
SetCurrentAppContext(TestAppContext())
|
||||
MockSSKEnvironment.activate()
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,6 @@ open class SignalBaseTest: XCTestCase {
|
||||
|
||||
public override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
SetCurrentAppContext(TestAppContext())
|
||||
MockSSKEnvironment.activate()
|
||||
}
|
||||
|
||||
|
||||
@ -185,7 +185,11 @@ class GRDBFinderTest: SignalBaseTest {
|
||||
var expectedAddresses = Set<OWSUserProfile.Address>()
|
||||
self.write { tx in
|
||||
let buildUserProfile = { () -> OWSUserProfile in
|
||||
return OWSUserProfile.getOrBuildUserProfile(for: .otherUser(Aci.randomForTesting()), tx: tx)
|
||||
return OWSUserProfile.getOrBuildUserProfile(
|
||||
for: .otherUser(Aci.randomForTesting()),
|
||||
userProfileWriter: .tests,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
|
||||
func updateUserProfile(
|
||||
|
||||
@ -138,8 +138,8 @@ lastVisibleSortIdOnScreenPercentageObsolete:lastVisibleSortIdOnScreenPercentageO
|
||||
{
|
||||
if ([self isMyStory]) {
|
||||
[StoryManager setHasSetMyStoriesPrivacy:YES
|
||||
transaction:transaction
|
||||
shouldUpdateStorageService:updateStorageService];
|
||||
shouldUpdateStorageService:updateStorageService
|
||||
transaction:transaction];
|
||||
}
|
||||
[self anyUpdatePrivateStoryThreadWithTransaction:transaction
|
||||
block:^(TSPrivateStoryThread *thread) {
|
||||
|
||||
@ -10,28 +10,85 @@ import SignalCoreKit
|
||||
public class AppSetup {
|
||||
public init() {}
|
||||
|
||||
/// Injectable mocks for global singletons accessed by tests for components
|
||||
/// that cannot be isolated in tests.
|
||||
///
|
||||
/// For example, many legacy tests rely on the globally-available singletons
|
||||
/// from ``Dependencies`` and its ``NSObject`` extension, and use this type
|
||||
/// to inject mock versions of those singletons to the global state.
|
||||
///
|
||||
/// Additionally, the integration tests for message backup access these
|
||||
/// globals transitively through message backup's dependency on managers
|
||||
/// that use the global state, and similarly use this type to inject a
|
||||
/// limited set of mock singletons.
|
||||
public struct TestDependencies {
|
||||
let accountServiceClient: AccountServiceClient
|
||||
let contactManager: any ContactManager
|
||||
let groupV2Updates: any GroupV2Updates
|
||||
let groupsV2: any GroupsV2
|
||||
let keyValueStoreFactory: any KeyValueStoreFactory
|
||||
let messageSender: MessageSender
|
||||
let modelReadCaches: ModelReadCaches
|
||||
let networkManager: NetworkManager
|
||||
let paymentsCurrencies: any PaymentsCurrenciesSwift
|
||||
let paymentsHelper: any PaymentsHelperSwift
|
||||
let pendingReceiptRecorder: any PendingReceiptRecorder
|
||||
let profileManager: any ProfileManager
|
||||
let reachabilityManager: any SSKReachabilityManager
|
||||
let remoteConfigManager: any RemoteConfigManager
|
||||
let signalService: any OWSSignalServiceProtocol
|
||||
let storageServiceManager: any StorageServiceManager
|
||||
let subscriptionManager: any SubscriptionManager
|
||||
let syncManager: any SyncManagerProtocol
|
||||
let systemStoryManager: any SystemStoryManagerProtocol
|
||||
let versionedProfiles: any VersionedProfilesSwift
|
||||
let webSocketFactory: any WebSocketFactory
|
||||
let accountServiceClient: AccountServiceClient?
|
||||
let contactManager: (any ContactManager)?
|
||||
let groupV2Updates: (any GroupV2Updates)?
|
||||
let groupsV2: (any GroupsV2)?
|
||||
let keyValueStoreFactory: (any KeyValueStoreFactory)?
|
||||
let messageSender: MessageSender?
|
||||
let modelReadCaches: ModelReadCaches?
|
||||
let networkManager: NetworkManager?
|
||||
let paymentsCurrencies: (any PaymentsCurrenciesSwift)?
|
||||
let paymentsHelper: (any PaymentsHelperSwift)?
|
||||
let pendingReceiptRecorder: (any PendingReceiptRecorder)?
|
||||
let profileManager: (any ProfileManager)?
|
||||
let reachabilityManager: (any SSKReachabilityManager)?
|
||||
let remoteConfigManager: (any RemoteConfigManager)?
|
||||
let signalService: (any OWSSignalServiceProtocol)?
|
||||
let storageServiceManager: (any StorageServiceManager)?
|
||||
let subscriptionManager: (any SubscriptionManager)?
|
||||
let syncManager: (any SyncManagerProtocol)?
|
||||
let systemStoryManager: (any SystemStoryManagerProtocol)?
|
||||
let versionedProfiles: (any VersionedProfilesSwift)?
|
||||
let webSocketFactory: (any WebSocketFactory)?
|
||||
|
||||
public init(
|
||||
accountServiceClient: AccountServiceClient? = nil,
|
||||
contactManager: (any ContactManager)? = nil,
|
||||
groupV2Updates: (any GroupV2Updates)? = nil,
|
||||
groupsV2: (any GroupsV2)? = nil,
|
||||
keyValueStoreFactory: (any KeyValueStoreFactory)? = nil,
|
||||
messageSender: MessageSender? = nil,
|
||||
modelReadCaches: ModelReadCaches? = nil,
|
||||
networkManager: NetworkManager? = nil,
|
||||
paymentsCurrencies: (any PaymentsCurrenciesSwift)? = nil,
|
||||
paymentsHelper: (any PaymentsHelperSwift)? = nil,
|
||||
pendingReceiptRecorder: (any PendingReceiptRecorder)? = nil,
|
||||
profileManager: (any ProfileManager)? = nil,
|
||||
reachabilityManager: (any SSKReachabilityManager)? = nil,
|
||||
remoteConfigManager: (any RemoteConfigManager)? = nil,
|
||||
signalService: (any OWSSignalServiceProtocol)? = nil,
|
||||
storageServiceManager: (any StorageServiceManager)? = nil,
|
||||
subscriptionManager: (any SubscriptionManager)? = nil,
|
||||
syncManager: (any SyncManagerProtocol)? = nil,
|
||||
systemStoryManager: (any SystemStoryManagerProtocol)? = nil,
|
||||
versionedProfiles: (any VersionedProfilesSwift)? = nil,
|
||||
webSocketFactory: (any WebSocketFactory)? = nil
|
||||
) {
|
||||
self.accountServiceClient = accountServiceClient
|
||||
self.contactManager = contactManager
|
||||
self.groupV2Updates = groupV2Updates
|
||||
self.groupsV2 = groupsV2
|
||||
self.keyValueStoreFactory = keyValueStoreFactory
|
||||
self.messageSender = messageSender
|
||||
self.modelReadCaches = modelReadCaches
|
||||
self.networkManager = networkManager
|
||||
self.paymentsCurrencies = paymentsCurrencies
|
||||
self.paymentsHelper = paymentsHelper
|
||||
self.pendingReceiptRecorder = pendingReceiptRecorder
|
||||
self.profileManager = profileManager
|
||||
self.reachabilityManager = reachabilityManager
|
||||
self.remoteConfigManager = remoteConfigManager
|
||||
self.signalService = signalService
|
||||
self.storageServiceManager = storageServiceManager
|
||||
self.subscriptionManager = subscriptionManager
|
||||
self.syncManager = syncManager
|
||||
self.systemStoryManager = systemStoryManager
|
||||
self.versionedProfiles = versionedProfiles
|
||||
self.webSocketFactory = webSocketFactory
|
||||
}
|
||||
}
|
||||
|
||||
public func start(
|
||||
@ -42,7 +99,7 @@ public class AppSetup {
|
||||
callMessageHandler: CallMessageHandler,
|
||||
currentCallThreadProvider: any CurrentCallThreadProvider,
|
||||
notificationPresenter: any NotificationPresenter,
|
||||
testDependencies: TestDependencies? = nil
|
||||
testDependencies: TestDependencies = TestDependencies()
|
||||
) -> AppSetup.DatabaseContinuation {
|
||||
configureUnsatisfiableConstraintLogging()
|
||||
|
||||
@ -58,7 +115,7 @@ public class AppSetup {
|
||||
OWSBackgroundTaskManager.shared().observeNotifications()
|
||||
|
||||
let appVersion = AppVersionImpl.shared
|
||||
let webSocketFactory = testDependencies?.webSocketFactory ?? WebSocketFactoryNative()
|
||||
let webSocketFactory = testDependencies.webSocketFactory ?? WebSocketFactoryNative()
|
||||
|
||||
// AFNetworking (via CFNetworking) spools its attachments in
|
||||
// NSTemporaryDirectory(). If you receive a media message while the device
|
||||
@ -69,13 +126,13 @@ public class AppSetup {
|
||||
owsAssert(OWSFileSystem.protectFileOrFolder(atPath: temporaryDirectory, fileProtectionType: .completeUntilFirstUserAuthentication))
|
||||
|
||||
let tsConstants = TSConstants.shared
|
||||
let keyValueStoreFactory = testDependencies?.keyValueStoreFactory ?? SDSKeyValueStoreFactory()
|
||||
let keyValueStoreFactory = testDependencies.keyValueStoreFactory ?? SDSKeyValueStoreFactory()
|
||||
|
||||
let recipientDatabaseTable = RecipientDatabaseTableImpl()
|
||||
let recipientFetcher = RecipientFetcherImpl(recipientDatabaseTable: recipientDatabaseTable)
|
||||
let recipientIdFinder = RecipientIdFinder(recipientDatabaseTable: recipientDatabaseTable, recipientFetcher: recipientFetcher)
|
||||
|
||||
let accountServiceClient = testDependencies?.accountServiceClient ?? AccountServiceClient()
|
||||
let accountServiceClient = testDependencies.accountServiceClient ?? AccountServiceClient()
|
||||
let aciSignalProtocolStore = SignalProtocolStoreImpl(
|
||||
for: .aci,
|
||||
keyValueStoreFactory: keyValueStoreFactory,
|
||||
@ -85,34 +142,34 @@ public class AppSetup {
|
||||
let dateProvider = Date.provider
|
||||
let earlyMessageManager = EarlyMessageManager()
|
||||
let messageProcessor = MessageProcessor()
|
||||
let messageSender = testDependencies?.messageSender ?? MessageSender()
|
||||
let messageSender = testDependencies.messageSender ?? MessageSender()
|
||||
let messageSenderJobQueue = MessageSenderJobQueue()
|
||||
let modelReadCaches = testDependencies?.modelReadCaches ?? ModelReadCaches(factory: ModelReadCacheFactory())
|
||||
let networkManager = testDependencies?.networkManager ?? NetworkManager()
|
||||
let modelReadCaches = testDependencies.modelReadCaches ?? ModelReadCaches(factory: ModelReadCacheFactory())
|
||||
let networkManager = testDependencies.networkManager ?? NetworkManager()
|
||||
let ows2FAManager = OWS2FAManager()
|
||||
let paymentsHelper = testDependencies?.paymentsHelper ?? PaymentsHelperImpl()
|
||||
let paymentsHelper = testDependencies.paymentsHelper ?? PaymentsHelperImpl()
|
||||
let pniSignalProtocolStore = SignalProtocolStoreImpl(
|
||||
for: .pni,
|
||||
keyValueStoreFactory: keyValueStoreFactory,
|
||||
recipientIdFinder: recipientIdFinder
|
||||
)
|
||||
let profileManager = testDependencies?.profileManager ?? OWSProfileManager(
|
||||
let profileManager = testDependencies.profileManager ?? OWSProfileManager(
|
||||
databaseStorage: databaseStorage,
|
||||
swiftValues: OWSProfileManagerSwiftValues()
|
||||
)
|
||||
let reachabilityManager = testDependencies?.reachabilityManager ?? SSKReachabilityManagerImpl()
|
||||
let reachabilityManager = testDependencies.reachabilityManager ?? SSKReachabilityManagerImpl()
|
||||
let receiptManager = OWSReceiptManager()
|
||||
let senderKeyStore = SenderKeyStore()
|
||||
let signalProtocolStoreManager = SignalProtocolStoreManagerImpl(
|
||||
aciProtocolStore: aciSignalProtocolStore,
|
||||
pniProtocolStore: pniSignalProtocolStore
|
||||
)
|
||||
let signalService = testDependencies?.signalService ?? OWSSignalService()
|
||||
let signalService = testDependencies.signalService ?? OWSSignalService()
|
||||
let signalServiceAddressCache = SignalServiceAddressCache()
|
||||
let storageServiceManager = testDependencies?.storageServiceManager ?? StorageServiceManagerImpl.shared
|
||||
let syncManager = testDependencies?.syncManager ?? OWSSyncManager(default: ())
|
||||
let storageServiceManager = testDependencies.storageServiceManager ?? StorageServiceManagerImpl.shared
|
||||
let syncManager = testDependencies.syncManager ?? OWSSyncManager(default: ())
|
||||
let udManager = OWSUDManagerImpl()
|
||||
let versionedProfiles = testDependencies?.versionedProfiles ?? VersionedProfilesImpl()
|
||||
let versionedProfiles = testDependencies.versionedProfiles ?? VersionedProfilesImpl()
|
||||
|
||||
let signalAccountStore = SignalAccountStoreImpl()
|
||||
let threadStore = ThreadStoreImpl()
|
||||
@ -141,7 +198,7 @@ public class AppSetup {
|
||||
storageServiceManager: storageServiceManager,
|
||||
schedulers: schedulers
|
||||
)
|
||||
let contactManager = testDependencies?.contactManager ?? OWSContactsManager(swiftValues: OWSContactsManagerSwiftValues(
|
||||
let contactManager = testDependencies.contactManager ?? OWSContactsManager(swiftValues: OWSContactsManagerSwiftValues(
|
||||
usernameLookupManager: usernameLookupManager,
|
||||
recipientDatabaseTable: recipientDatabaseTable,
|
||||
nicknameManager: nicknameManager
|
||||
@ -158,7 +215,7 @@ public class AppSetup {
|
||||
db: db
|
||||
)
|
||||
|
||||
let groupsV2 = testDependencies?.groupsV2 ?? GroupsV2Impl(
|
||||
let groupsV2 = testDependencies.groupsV2 ?? GroupsV2Impl(
|
||||
authCredentialStore: authCredentialStore,
|
||||
authCredentialManager: authCredentialManager
|
||||
)
|
||||
@ -664,8 +721,8 @@ public class AppSetup {
|
||||
let messageBackupKeyMaterial = MessageBackupKeyMaterialImpl(svr: svr)
|
||||
let preferences = Preferences()
|
||||
let storyStore = StoryStoreImpl()
|
||||
let subscriptionManager = testDependencies?.subscriptionManager ?? SubscriptionManagerImpl()
|
||||
let systemStoryManager = testDependencies?.systemStoryManager ?? SystemStoryManager()
|
||||
let subscriptionManager = testDependencies.subscriptionManager ?? SubscriptionManagerImpl()
|
||||
let systemStoryManager = testDependencies.systemStoryManager ?? SystemStoryManager()
|
||||
let typingIndicators = TypingIndicatorsImpl()
|
||||
|
||||
let attachmentUploadManager = AttachmentUploadManagerImpl(
|
||||
@ -687,6 +744,7 @@ public class AppSetup {
|
||||
localUsernameManager: localUsernameManager,
|
||||
phoneNumberDiscoverabilityManager: phoneNumberDiscoverabilityManager,
|
||||
preferences: MessageBackup.AccountData.Wrappers.Preferences(preferences: preferences),
|
||||
profileManager: MessageBackup.Wrappers.ProfileManager(profileManager),
|
||||
receiptManager: MessageBackup.AccountData.Wrappers.ReceiptManager(receiptManager: receiptManager),
|
||||
reactionManager: MessageBackup.AccountData.Wrappers.ReactionManager(),
|
||||
sskPreferences: MessageBackup.AccountData.Wrappers.SSKPreferences(),
|
||||
@ -695,8 +753,7 @@ public class AppSetup {
|
||||
systemStoryManager: MessageBackup.AccountData.Wrappers.SystemStoryManager(systemStoryManager: systemStoryManager),
|
||||
typingIndicators: MessageBackup.AccountData.Wrappers.TypingIndicators(typingIndicators: typingIndicators),
|
||||
udManager: MessageBackup.AccountData.Wrappers.UDManager(udManager: udManager),
|
||||
usernameEducationManager: usernameEducationManager,
|
||||
userProfile: MessageBackup.AccountData.Wrappers.UserProfile()
|
||||
usernameEducationManager: usernameEducationManager
|
||||
),
|
||||
attachmentDownloadManager: attachmentDownloadManager,
|
||||
attachmentUploadManager: attachmentUploadManager,
|
||||
@ -919,9 +976,9 @@ public class AppSetup {
|
||||
reachabilityManager: reachabilityManager
|
||||
)
|
||||
|
||||
let pendingReceiptRecorder = testDependencies?.pendingReceiptRecorder ?? MessageRequestPendingReceipts()
|
||||
let pendingReceiptRecorder = testDependencies.pendingReceiptRecorder ?? MessageRequestPendingReceipts()
|
||||
let messageReceiver = MessageReceiver(callMessageHandler: callMessageHandler)
|
||||
let remoteConfigManager = testDependencies?.remoteConfigManager ?? RemoteConfigManagerImpl(
|
||||
let remoteConfigManager = testDependencies.remoteConfigManager ?? RemoteConfigManagerImpl(
|
||||
appExpiry: appExpiry,
|
||||
db: db,
|
||||
keyValueStoreFactory: keyValueStoreFactory,
|
||||
@ -937,7 +994,7 @@ public class AppSetup {
|
||||
)
|
||||
let stickerManager = StickerManager()
|
||||
let sskPreferences = SSKPreferences()
|
||||
let groupV2Updates = testDependencies?.groupV2Updates ?? GroupV2UpdatesImpl()
|
||||
let groupV2Updates = testDependencies.groupV2Updates ?? GroupV2UpdatesImpl()
|
||||
let messageFetcherJob = MessageFetcherJob()
|
||||
let profileFetcher = ProfileFetcherImpl(
|
||||
db: db,
|
||||
@ -953,7 +1010,7 @@ public class AppSetup {
|
||||
versionedProfiles: versionedProfiles
|
||||
)
|
||||
let messagePipelineSupervisor = MessagePipelineSupervisor()
|
||||
let paymentsCurrencies = testDependencies?.paymentsCurrencies ?? PaymentsCurrenciesImpl()
|
||||
let paymentsCurrencies = testDependencies.paymentsCurrencies ?? PaymentsCurrenciesImpl()
|
||||
let spamChallengeResolver = SpamChallengeResolver()
|
||||
let phoneNumberUtil = PhoneNumberUtil(swiftValues: PhoneNumberUtilSwiftValues())
|
||||
let legacyChangePhoneNumber = LegacyChangePhoneNumber()
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import SignalCoreKit
|
||||
|
||||
extension MessageBackup {
|
||||
/// An identifier for the ``BackupProto.AccountData`` backup frame.
|
||||
///
|
||||
@ -48,6 +50,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
private let localUsernameManager: LocalUsernameManager
|
||||
private let phoneNumberDiscoverabilityManager: PhoneNumberDiscoverabilityManager
|
||||
private let preferences: MessageBackup.AccountData.Shims.Preferences
|
||||
private let profileManager: MessageBackup.Shims.ProfileManager
|
||||
private let receiptManager: MessageBackup.AccountData.Shims.ReceiptManager
|
||||
private let reactionManager: MessageBackup.AccountData.Shims.ReactionManager
|
||||
private let sskPreferences: MessageBackup.AccountData.Shims.SSKPreferences
|
||||
@ -57,13 +60,13 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
private let typingIndicators: MessageBackup.AccountData.Shims.TypingIndicators
|
||||
private let udManager: MessageBackup.AccountData.Shims.UDManager
|
||||
private let usernameEducationManager: UsernameEducationManager
|
||||
private let userProfile: MessageBackup.AccountData.Shims.UserProfile
|
||||
|
||||
public init(
|
||||
disappearingMessageConfigurationStore: DisappearingMessagesConfigurationStore,
|
||||
localUsernameManager: LocalUsernameManager,
|
||||
phoneNumberDiscoverabilityManager: PhoneNumberDiscoverabilityManager,
|
||||
preferences: MessageBackup.AccountData.Shims.Preferences,
|
||||
profileManager: MessageBackup.Shims.ProfileManager,
|
||||
receiptManager: MessageBackup.AccountData.Shims.ReceiptManager,
|
||||
reactionManager: MessageBackup.AccountData.Shims.ReactionManager,
|
||||
sskPreferences: MessageBackup.AccountData.Shims.SSKPreferences,
|
||||
@ -72,8 +75,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
systemStoryManager: MessageBackup.AccountData.Shims.SystemStoryManager,
|
||||
typingIndicators: MessageBackup.AccountData.Shims.TypingIndicators,
|
||||
udManager: MessageBackup.AccountData.Shims.UDManager,
|
||||
usernameEducationManager: UsernameEducationManager,
|
||||
userProfile: MessageBackup.AccountData.Shims.UserProfile
|
||||
usernameEducationManager: UsernameEducationManager
|
||||
) {
|
||||
self.disappearingMessageConfigurationStore = disappearingMessageConfigurationStore
|
||||
self.localUsernameManager = localUsernameManager
|
||||
@ -88,7 +90,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
self.typingIndicators = typingIndicators
|
||||
self.udManager = udManager
|
||||
self.usernameEducationManager = usernameEducationManager
|
||||
self.userProfile = userProfile
|
||||
self.profileManager = profileManager
|
||||
}
|
||||
|
||||
public func archiveAccountData(
|
||||
@ -96,7 +98,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
tx: DBReadTransaction
|
||||
) -> MessageBackup.ArchiveAccountDataResult {
|
||||
|
||||
guard let localProfile = userProfile.getLocalProfile(tx: tx) else {
|
||||
guard let localProfile = profileManager.getUserProfileForLocalUser(tx: tx) else {
|
||||
return .failure(.archiveFrameError(.missingLocalProfile, .localUser))
|
||||
}
|
||||
guard let profileKeyData = localProfile.profileKey?.keyData else {
|
||||
@ -224,7 +226,6 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
_ accountData: BackupProto.AccountData,
|
||||
tx: DBWriteTransaction
|
||||
) -> RestoreFrameResult {
|
||||
|
||||
guard let profileKey = OWSAES256Key(data: accountData.profileKey) else {
|
||||
return .failure([.restoreFrameError(
|
||||
.invalidProtoData(.invalidLocalProfileKey),
|
||||
@ -232,6 +233,16 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
)])
|
||||
}
|
||||
|
||||
// Given name and profile key are required for the local profile. The
|
||||
// rest are optional.
|
||||
profileManager.insertLocalUserProfile(
|
||||
givenName: accountData.givenName,
|
||||
familyName: accountData.familyName.nilIfEmpty,
|
||||
avatarUrlPath: accountData.avatarUrlPath.nilIfEmpty,
|
||||
profileKey: profileKey,
|
||||
tx: tx
|
||||
)
|
||||
|
||||
// Restore Subscription data, if nod a default value
|
||||
if accountData.subscriberId.count > 0, accountData.subscriberCurrencyCode.count > 0 {
|
||||
subscriptionManager.setSubscriberID(subscriberID: accountData.subscriberId, tx: tx)
|
||||
@ -288,16 +299,6 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
|
||||
udManager.setPhoneNumberSharingMode(phoneNumberSharingMode, tx: tx)
|
||||
}
|
||||
|
||||
// Restore Local Profile
|
||||
// For familyName & avatarUrlPath, pass in `nil` if the value is empty.
|
||||
userProfile.insertLocalProfile(
|
||||
givenName: accountData.givenName,
|
||||
familyName: accountData.familyName.nilIfEmpty,
|
||||
avatarUrlPath: accountData.avatarUrlPath.nilIfEmpty,
|
||||
profileKey: profileKey,
|
||||
tx: tx
|
||||
)
|
||||
|
||||
// Restore username details (username, link, QR color)
|
||||
if let username = accountData.username, let usernameLink = accountData.usernameLink {
|
||||
if
|
||||
|
||||
@ -51,7 +51,7 @@ public class MessageBackupContactRecipientArchiver: MessageBackupRecipientDestin
|
||||
context: MessageBackup.RecipientArchivingContext,
|
||||
tx: DBReadTransaction
|
||||
) -> ArchiveMultiFrameResult {
|
||||
let whitelistedAddresses = Set(profileManager.allWhitelistedRegisteredAddresses(tx: tx))
|
||||
let whitelistedAddresses = Set(profileManager.allWhitelistedAddresses(tx: tx))
|
||||
let blockedAddresses = blockingManager.blockedAddresses(tx: tx)
|
||||
|
||||
var errors = [ArchiveMultiFrameResult.ArchiveFrameError]()
|
||||
@ -102,7 +102,10 @@ public class MessageBackupContactRecipientArchiver: MessageBackupRecipientDestin
|
||||
contact.registered = recipient.isRegistered ? .REGISTERED : .NOT_REGISTERED
|
||||
contact.aci = recipient.aci.map(\.rawUUID.data)
|
||||
contact.pni = recipient.pni.map(\.rawUUID.data)
|
||||
contact.e164 = recipient.address.e164.map(\.uint64Value)
|
||||
contact.e164 = { () -> UInt64? in
|
||||
guard let phoneNumberString = recipient.phoneNumber?.stringValue else { return nil }
|
||||
return E164(phoneNumberString)?.uint64Value
|
||||
}()
|
||||
|
||||
if let aci = recipient.aci {
|
||||
contact.username = usernameLookupManager.fetchUsername(
|
||||
@ -272,7 +275,7 @@ public class MessageBackupContactRecipientArchiver: MessageBackupRecipientDestin
|
||||
// We only need to active hide, since unhidden is the default.
|
||||
if contactProto.hideStory, let aci = address.aci {
|
||||
let storyContext = storyStore.getOrCreateStoryContextAssociatedData(for: aci, tx: tx)
|
||||
storyStore.updateStoryContext(storyContext, isHidden: true, tx: tx)
|
||||
storyStore.updateStoryContext(storyContext, updateStorageService: false, isHidden: true, tx: tx)
|
||||
}
|
||||
|
||||
profileManager.insertOtherUserProfile(
|
||||
|
||||
@ -43,7 +43,7 @@ public class _MessageBackup_BlockingManagerWrapper: _MessageBackup_BlockingManag
|
||||
}
|
||||
|
||||
public func addBlockedAddress(_ address: SignalServiceAddress, tx: DBWriteTransaction) {
|
||||
blockingManager.addBlockedAddress(address, blockMode: .localShouldNotLeaveGroups, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
blockingManager.addBlockedAddress(address, blockMode: .restoreFromBackup, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,11 +53,11 @@ public protocol _MessageBackup_ProfileManagerShim {
|
||||
|
||||
func getUserProfile(for address: SignalServiceAddress, tx: DBReadTransaction) -> OWSUserProfile?
|
||||
|
||||
func getLocalUsersProfile(tx: DBReadTransaction) -> OWSUserProfile?
|
||||
func getUserProfileForLocalUser(tx: DBReadTransaction) -> OWSUserProfile?
|
||||
|
||||
func getProfileKeyData(for address: SignalServiceAddress, tx: DBReadTransaction) -> Data?
|
||||
|
||||
func allWhitelistedRegisteredAddresses(tx: DBReadTransaction) -> [SignalServiceAddress]
|
||||
func allWhitelistedAddresses(tx: DBReadTransaction) -> [SignalServiceAddress]
|
||||
|
||||
func isThread(inProfileWhitelist thread: TSThread, tx: DBReadTransaction) -> Bool
|
||||
|
||||
@ -72,6 +72,14 @@ public protocol _MessageBackup_ProfileManagerShim {
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
|
||||
func insertLocalUserProfile(
|
||||
givenName: String,
|
||||
familyName: String?,
|
||||
avatarUrlPath: String?,
|
||||
profileKey: OWSAES256Key,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
|
||||
func insertOtherUserProfile(
|
||||
givenName: String?,
|
||||
familyName: String?,
|
||||
@ -82,11 +90,6 @@ public protocol _MessageBackup_ProfileManagerShim {
|
||||
}
|
||||
|
||||
public class _MessageBackup_ProfileManagerWrapper: _MessageBackup_ProfileManagerShim {
|
||||
private var userProfileWriter: UserProfileWriter {
|
||||
// [Backups] TODO: add a dedicated profile writer case
|
||||
return .storageService
|
||||
}
|
||||
|
||||
private let profileManager: ProfileManager
|
||||
|
||||
public init(_ profileManager: ProfileManager) {
|
||||
@ -97,7 +100,7 @@ public class _MessageBackup_ProfileManagerWrapper: _MessageBackup_ProfileManager
|
||||
profileManager.getUserProfile(for: address, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
|
||||
public func getLocalUsersProfile(tx: DBReadTransaction) -> OWSUserProfile? {
|
||||
public func getUserProfileForLocalUser(tx: any DBReadTransaction) -> OWSUserProfile? {
|
||||
return OWSUserProfile.getUserProfileForLocalUser(tx: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
|
||||
@ -105,8 +108,8 @@ public class _MessageBackup_ProfileManagerWrapper: _MessageBackup_ProfileManager
|
||||
profileManager.profileKeyData(for: address, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
|
||||
public func allWhitelistedRegisteredAddresses(tx: DBReadTransaction) -> [SignalServiceAddress] {
|
||||
profileManager.allWhitelistedRegisteredAddresses(tx: SDSDB.shimOnlyBridge(tx))
|
||||
public func allWhitelistedAddresses(tx: any DBReadTransaction) -> [SignalServiceAddress] {
|
||||
profileManager.allWhitelistedAddresses(tx: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
|
||||
public func isThread(inProfileWhitelist thread: TSThread, tx: DBReadTransaction) -> Bool {
|
||||
@ -116,7 +119,7 @@ public class _MessageBackup_ProfileManagerWrapper: _MessageBackup_ProfileManager
|
||||
public func addToWhitelist(_ address: SignalServiceAddress, tx: DBWriteTransaction) {
|
||||
profileManager.addUser(
|
||||
toProfileWhitelist: address,
|
||||
userProfileWriter: userProfileWriter,
|
||||
userProfileWriter: .messageBackupRestore,
|
||||
transaction: SDSDB.shimOnlyBridge(tx)
|
||||
)
|
||||
}
|
||||
@ -136,13 +139,38 @@ public class _MessageBackup_ProfileManagerWrapper: _MessageBackup_ProfileManager
|
||||
for: aci,
|
||||
onlyFillInIfMissing: false,
|
||||
shouldFetchProfile: false,
|
||||
userProfileWriter: userProfileWriter,
|
||||
userProfileWriter: .messageBackupRestore,
|
||||
localIdentifiers: localIdentifiers,
|
||||
authedAccount: .implicit(),
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
|
||||
public func insertLocalUserProfile(
|
||||
givenName: String,
|
||||
familyName: String?,
|
||||
avatarUrlPath: String?,
|
||||
profileKey: OWSAES256Key,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
let sdsTx = SDSDB.shimOnlyBridge(tx)
|
||||
|
||||
let localUserProfile = OWSUserProfile.getOrBuildUserProfileForLocalUser(
|
||||
userProfileWriter: .messageBackupRestore,
|
||||
tx: sdsTx
|
||||
)
|
||||
|
||||
localUserProfile.update(
|
||||
givenName: .setTo(givenName),
|
||||
familyName: .setTo(familyName),
|
||||
avatarUrlPath: .setTo(avatarUrlPath),
|
||||
profileKey: .setTo(profileKey),
|
||||
userProfileWriter: .messageBackupRestore,
|
||||
transaction: sdsTx,
|
||||
completion: nil
|
||||
)
|
||||
}
|
||||
|
||||
public func insertOtherUserProfile(
|
||||
givenName: String?,
|
||||
familyName: String?,
|
||||
@ -162,6 +190,8 @@ public class _MessageBackup_ProfileManagerWrapper: _MessageBackup_ProfileManager
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - AccountData
|
||||
|
||||
extension MessageBackup {
|
||||
public enum AccountData {}
|
||||
}
|
||||
@ -177,7 +207,6 @@ extension MessageBackup.AccountData {
|
||||
public typealias SystemStoryManager = _MessageBackup_AccountData_SystemStoryManagerShim
|
||||
public typealias ReactionManager = _MessageBackup_AccountData_ReactionManagerShim
|
||||
public typealias UDManager = _MessageBackup_AccountData_UDManagerShim
|
||||
public typealias UserProfile = _MessageBackup_AccountData_UserProfileShim
|
||||
}
|
||||
|
||||
public enum Wrappers {
|
||||
@ -190,7 +219,6 @@ extension MessageBackup.AccountData {
|
||||
public typealias SystemStoryManager = _MessageBackup_AccountData_SystemStoryManagerWrapper
|
||||
public typealias ReactionManager = _MessageBackup_AccountData_ReactionManagerWrapper
|
||||
public typealias UDManager = _MessageBackup_AccountData_UDManagerWrapper
|
||||
public typealias UserProfile = _MessageBackup_AccountData_UserProfileWrapper
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +285,7 @@ public class _MessageBackup_AccountData_PreferencesWrapper: _MessageBackup_Accou
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SSKPreferences
|
||||
// MARK: SSKPreferences
|
||||
|
||||
public protocol _MessageBackup_AccountData_SSKPreferencesShim {
|
||||
func areLinkPreviewsEnabled(tx: DBReadTransaction) -> Bool
|
||||
@ -268,8 +296,8 @@ public protocol _MessageBackup_AccountData_SSKPreferencesShim {
|
||||
|
||||
func shouldKeepMutedChatsArchived(tx: DBReadTransaction) -> Bool
|
||||
func setShouldKeepMutedChatsArchived(value: Bool, tx: DBWriteTransaction)
|
||||
|
||||
}
|
||||
|
||||
public class _MessageBackup_AccountData_SSKPreferencesWrapper: _MessageBackup_AccountData_SSKPreferencesShim {
|
||||
public func areLinkPreviewsEnabled(tx: DBReadTransaction) -> Bool {
|
||||
SSKPreferences.areLinkPreviewsEnabled(transaction: SDSDB.shimOnlyBridge(tx))
|
||||
@ -293,7 +321,7 @@ public class _MessageBackup_AccountData_SSKPreferencesWrapper: _MessageBackup_Ac
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SubscriptionManager
|
||||
// MARK: SubscriptionManager
|
||||
|
||||
public protocol _MessageBackup_AccountData_SubscriptionManagerShim {
|
||||
func displayBadgesOnProfile(tx: DBReadTransaction) -> Bool
|
||||
@ -305,6 +333,7 @@ public protocol _MessageBackup_AccountData_SubscriptionManagerShim {
|
||||
func userManuallyCancelledSubscription(tx: DBReadTransaction) -> Bool
|
||||
func setUserManuallyCancelledSubscription(value: Bool, tx: DBWriteTransaction)
|
||||
}
|
||||
|
||||
public class _MessageBackup_AccountData_SubscriptionManagerWrapper: _MessageBackup_AccountData_SubscriptionManagerShim {
|
||||
let subscriptionManager: SubscriptionManager
|
||||
init(subscriptionManager: SubscriptionManager) {
|
||||
@ -342,7 +371,7 @@ public class _MessageBackup_AccountData_SubscriptionManagerWrapper: _MessageBack
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - StoryManager
|
||||
// MARK: StoryManager
|
||||
|
||||
public protocol _MessageBackup_AccountData_StoryManagerShim {
|
||||
func hasSetMyStoriesPrivacy(tx: DBReadTransaction) -> Bool
|
||||
@ -352,28 +381,29 @@ public protocol _MessageBackup_AccountData_StoryManagerShim {
|
||||
func areViewReceiptsEnabled(tx: DBReadTransaction) -> Bool
|
||||
func setAreViewReceiptsEnabled(value: Bool, tx: DBWriteTransaction)
|
||||
}
|
||||
|
||||
public class _MessageBackup_AccountData_StoryManagerWrapper: _MessageBackup_AccountData_StoryManagerShim {
|
||||
public func hasSetMyStoriesPrivacy(tx: DBReadTransaction) -> Bool {
|
||||
StoryManager.hasSetMyStoriesPrivacy(transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
public func setHasSetMyStoriesPrivacy(value: Bool, tx: DBWriteTransaction) {
|
||||
StoryManager.setHasSetMyStoriesPrivacy(value, transaction: SDSDB.shimOnlyBridge(tx), shouldUpdateStorageService: false)
|
||||
StoryManager.setHasSetMyStoriesPrivacy(value, shouldUpdateStorageService: false, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
public func areStoriesEnabled(tx: DBReadTransaction) -> Bool {
|
||||
StoryManager.areStoriesEnabled(transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
public func setAreStoriesEnabled(value: Bool, tx: DBWriteTransaction) {
|
||||
StoryManager.setAreStoriesEnabled(value, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
StoryManager.setAreStoriesEnabled(value, shouldUpdateStorageService: false, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
public func areViewReceiptsEnabled(tx: DBReadTransaction) -> Bool {
|
||||
StoryManager.areViewReceiptsEnabled(transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
public func setAreViewReceiptsEnabled(value: Bool, tx: DBWriteTransaction) {
|
||||
StoryManager.setAreViewReceiptsEnabled(value, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
StoryManager.setAreViewReceiptsEnabled(value, shouldUpdateStorageService: false, transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SystemStoryManager
|
||||
// MARK: SystemStoryManager
|
||||
|
||||
public protocol _MessageBackup_AccountData_SystemStoryManagerShim {
|
||||
func isOnboardingStoryViewed(tx: DBReadTransaction) -> Bool
|
||||
@ -381,6 +411,7 @@ public protocol _MessageBackup_AccountData_SystemStoryManagerShim {
|
||||
func hasSeenGroupStoryEducationSheet(tx: DBReadTransaction) -> Bool
|
||||
func setHasSeenGroupStoryEducationSheet(value: Bool, tx: DBWriteTransaction)
|
||||
}
|
||||
|
||||
public class _MessageBackup_AccountData_SystemStoryManagerWrapper: _MessageBackup_AccountData_SystemStoryManagerShim {
|
||||
let systemStoryManager: SystemStoryManagerProtocol
|
||||
init(systemStoryManager: SystemStoryManagerProtocol) {
|
||||
@ -404,12 +435,13 @@ public class _MessageBackup_AccountData_SystemStoryManagerWrapper: _MessageBacku
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ReactionManager
|
||||
// MARK: ReactionManager
|
||||
|
||||
public protocol _MessageBackup_AccountData_ReactionManagerShim {
|
||||
func customEmojiSet(tx: DBReadTransaction) -> [String]?
|
||||
func setCustomEmojiSet(emojis: [String]?, tx: DBWriteTransaction)
|
||||
}
|
||||
|
||||
public class _MessageBackup_AccountData_ReactionManagerWrapper: _MessageBackup_AccountData_ReactionManagerShim {
|
||||
public func customEmojiSet(tx: DBReadTransaction) -> [String]? {
|
||||
ReactionManager.customEmojiSet(transaction: SDSDB.shimOnlyBridge(tx))
|
||||
@ -419,12 +451,13 @@ public class _MessageBackup_AccountData_ReactionManagerWrapper: _MessageBackup_A
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UDManager
|
||||
// MARK: UDManager
|
||||
|
||||
public protocol _MessageBackup_AccountData_UDManagerShim {
|
||||
func phoneNumberSharingMode(tx: DBReadTransaction) -> PhoneNumberSharingMode?
|
||||
func setPhoneNumberSharingMode(_ mode: PhoneNumberSharingMode, tx: DBWriteTransaction)
|
||||
}
|
||||
|
||||
public class _MessageBackup_AccountData_UDManagerWrapper: _MessageBackup_AccountData_UDManagerShim {
|
||||
let udManager: OWSUDManager
|
||||
init(udManager: OWSUDManager) {
|
||||
@ -437,37 +470,3 @@ public class _MessageBackup_AccountData_UDManagerWrapper: _MessageBackup_Account
|
||||
udManager.setPhoneNumberSharingMode(mode, updateStorageServiceAndProfile: false, tx: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UserProfile
|
||||
|
||||
public protocol _MessageBackup_AccountData_UserProfileShim {
|
||||
func getLocalProfile(tx: DBReadTransaction) -> OWSUserProfile?
|
||||
func insertLocalProfile(
|
||||
givenName: String,
|
||||
familyName: String?,
|
||||
avatarUrlPath: String?,
|
||||
profileKey: OWSAES256Key,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
}
|
||||
public class _MessageBackup_AccountData_UserProfileWrapper: _MessageBackup_AccountData_UserProfileShim {
|
||||
public func getLocalProfile(tx: DBReadTransaction) -> OWSUserProfile? {
|
||||
return OWSUserProfile.getUserProfileForLocalUser(tx: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
|
||||
public func insertLocalProfile(
|
||||
givenName: String,
|
||||
familyName: String?,
|
||||
avatarUrlPath: String?,
|
||||
profileKey: OWSAES256Key,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
OWSUserProfile(
|
||||
address: .localUser,
|
||||
givenName: givenName,
|
||||
familyName: familyName,
|
||||
profileKey: profileKey,
|
||||
avatarUrlPath: avatarUrlPath
|
||||
).anyInsert(transaction: SDSDB.shimOnlyBridge(tx))
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,16 +9,15 @@ import SignalCoreKit
|
||||
|
||||
public enum BlockMode: UInt {
|
||||
case remote
|
||||
case restoreFromBackup
|
||||
case localShouldLeaveGroups
|
||||
case localShouldNotLeaveGroups
|
||||
|
||||
var locallyInitiated: Bool {
|
||||
switch self {
|
||||
case .remote:
|
||||
case .remote, .restoreFromBackup:
|
||||
return false
|
||||
case .localShouldLeaveGroups:
|
||||
return true
|
||||
case .localShouldNotLeaveGroups:
|
||||
case .localShouldLeaveGroups, .localShouldNotLeaveGroups:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,9 +213,9 @@ public class StoryManager: NSObject {
|
||||
|
||||
@objc
|
||||
public class func setHasSetMyStoriesPrivacy(
|
||||
_ hasSet: Bool = true,
|
||||
transaction: SDSAnyWriteTransaction,
|
||||
shouldUpdateStorageService: Bool = true
|
||||
_ hasSet: Bool,
|
||||
shouldUpdateStorageService: Bool,
|
||||
transaction: SDSAnyWriteTransaction
|
||||
) {
|
||||
guard hasSet != hasSetMyStoriesPrivacy(transaction: transaction) else {
|
||||
// Don't trigger account record updates unneccesarily!
|
||||
|
||||
@ -162,16 +162,16 @@ public class SystemStoryManager: NSObject, Dependencies, SystemStoryManagerProto
|
||||
|
||||
public func isOnboardingOverlayViewed(transaction: SDSAnyReadTransaction) -> Bool {
|
||||
if overlayKvStore.getBool(Constants.kvStoreOnboardingOverlayViewedKey, defaultValue: false, transaction: transaction) {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
if isOnboardingStoryViewed(transaction: transaction) {
|
||||
// We don't sync view state for the onboarding overlay. But we can use
|
||||
// viewing of the onboarding story as an imperfect proxy; if they viewed it
|
||||
// that means they also definitely saw the viewer overlay.
|
||||
return false
|
||||
return true
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
public func setOnboardingOverlayViewed(value: Bool, transaction: SDSAnyWriteTransaction) {
|
||||
|
||||
@ -177,7 +177,9 @@ NSString *const kNSNotificationKey_UserProfileWriter = @"kNSNotificationKey_User
|
||||
}
|
||||
|
||||
DatabaseStorageWrite(self.databaseStorage, ^(SDSAnyWriteTransaction *transaction) {
|
||||
localUserProfile = [OWSUserProfile getOrBuildUserProfileForLocalUserWithTx:transaction];
|
||||
localUserProfile =
|
||||
[OWSUserProfile getOrBuildUserProfileForLocalUserWithUserProfileWriter:UserProfileWriter_LocalUser
|
||||
tx:transaction];
|
||||
OWSAssertDebug(localUserProfile.profileKey);
|
||||
});
|
||||
|
||||
@ -416,8 +418,9 @@ NSString *const kNSNotificationKey_UserProfileWriter = @"kNSNotificationKey_User
|
||||
// by the time this method is called. If it's not, we've changed our caching
|
||||
// logic and should re-evaluate this method.
|
||||
OWSFailDebug(@"Missing local profile when setting key.");
|
||||
|
||||
localUserProfile = [OWSUserProfile getOrBuildUserProfileForLocalUserWithTx:transaction];
|
||||
localUserProfile =
|
||||
[OWSUserProfile getOrBuildUserProfileForLocalUserWithUserProfileWriter:UserProfileWriter_LocalUser
|
||||
tx:transaction];
|
||||
|
||||
_localUserProfile = localUserProfile;
|
||||
} else {
|
||||
@ -931,11 +934,6 @@ NSString *const kNSNotificationKey_UserProfileWriter = @"kNSNotificationKey_User
|
||||
return userProfile.avatarUrlPath;
|
||||
}
|
||||
|
||||
- (NSArray<SignalServiceAddress *> *)allWhitelistedRegisteredAddressesWithTx:(SDSAnyReadTransaction *)tx
|
||||
{
|
||||
return [self objc_allWhitelistedRegisteredAddressesWithTx:tx];
|
||||
}
|
||||
|
||||
- (nullable NSString *)profileBioForDisplayForAddress:(SignalServiceAddress *)address
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
|
||||
@ -10,8 +10,7 @@ import SignalCoreKit
|
||||
public class OWSProfileManagerSwiftValues {
|
||||
fileprivate let pendingUpdateRequests = AtomicValue<[OWSProfileManager.ProfileUpdateRequest]>([], lock: .init())
|
||||
|
||||
public init() {
|
||||
}
|
||||
public init() {}
|
||||
}
|
||||
|
||||
extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
@ -38,7 +37,11 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
) {
|
||||
AssertNotOnMainThread()
|
||||
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(for: address, tx: tx)
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: address,
|
||||
userProfileWriter: userProfileWriter,
|
||||
tx: tx
|
||||
)
|
||||
|
||||
var givenNameChange: OptionalChange<String> = .noChange
|
||||
var familyNameChange: OptionalChange<String?> = .noChange
|
||||
@ -164,9 +167,9 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
)
|
||||
}
|
||||
|
||||
@objc
|
||||
@available(swift, obsoleted: 1.0)
|
||||
func objc_allWhitelistedRegisteredAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress] {
|
||||
// MARK: -
|
||||
|
||||
public func allWhitelistedAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress] {
|
||||
var addresses = Set<SignalServiceAddress>()
|
||||
for serviceIdString in whitelistedServiceIdsStore.allKeys(transaction: tx) {
|
||||
addresses.insert(SignalServiceAddress(serviceIdString: serviceIdString))
|
||||
@ -175,12 +178,20 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
addresses.insert(SignalServiceAddress.legacyAddress(serviceId: nil, phoneNumber: phoneNumber))
|
||||
}
|
||||
|
||||
return Array(
|
||||
SignalRecipientFinder().signalRecipients(for: Array(addresses), tx: tx)
|
||||
.lazy.filter { $0.isRegistered }.map { $0.address }
|
||||
)
|
||||
return Array(addresses)
|
||||
}
|
||||
|
||||
public func allWhitelistedRegisteredAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress] {
|
||||
return SignalRecipientFinder().signalRecipients(
|
||||
for: allWhitelistedAddresses(tx: tx),
|
||||
tx: tx
|
||||
)
|
||||
.lazy
|
||||
.filter { $0.isRegistered }.map { $0.address }
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
internal func rotateLocalProfileKeyIfNecessary() {
|
||||
DispatchQueue.global().async {
|
||||
@ -618,7 +629,11 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
return
|
||||
}
|
||||
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(for: address, tx: SDSDB.shimOnlyBridge(tx))
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: address,
|
||||
userProfileWriter: userProfileWriter,
|
||||
tx: SDSDB.shimOnlyBridge(tx)
|
||||
)
|
||||
|
||||
if onlyFillInIfMissing, userProfile.profileKey != nil {
|
||||
return
|
||||
@ -982,7 +997,11 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
await databaseStorage.awaitableWrite { tx in
|
||||
self.tryToDequeueProfileChanges(profileChanges, tx: tx)
|
||||
// Apply the changes to our local profile.
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(for: .localUser, tx: tx)
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: .localUser,
|
||||
userProfileWriter: .localUser,
|
||||
tx: tx
|
||||
)
|
||||
userProfile.update(
|
||||
givenName: .setTo(newGivenName?.stringValue.rawValue),
|
||||
familyName: .setTo(newFamilyName?.stringValue.rawValue),
|
||||
@ -1214,6 +1233,8 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
localIdentifiers: LocalIdentifiers,
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
let userProfileWriter: UserProfileWriter = .metadataUpdate
|
||||
|
||||
let address = OWSUserProfile.insertableAddress(for: serviceId, localIdentifiers: localIdentifiers)
|
||||
switch address {
|
||||
case .localUser:
|
||||
@ -1221,7 +1242,11 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
case .otherUser:
|
||||
break
|
||||
}
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(for: address, tx: SDSDB.shimOnlyBridge(tx))
|
||||
let userProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: address,
|
||||
userProfileWriter: userProfileWriter,
|
||||
tx: SDSDB.shimOnlyBridge(tx)
|
||||
)
|
||||
|
||||
// lastMessagingDate is coarse; we don't need to track every single message
|
||||
// sent or received. It is sufficient to update it only when the value
|
||||
@ -1232,7 +1257,7 @@ extension OWSProfileManager: ProfileManager, Dependencies {
|
||||
|
||||
userProfile.update(
|
||||
lastMessagingDate: .setTo(Date()),
|
||||
userProfileWriter: .metadataUpdate,
|
||||
userProfileWriter: userProfileWriter,
|
||||
transaction: SDSDB.shimOnlyBridge(tx),
|
||||
completion: nil
|
||||
)
|
||||
|
||||
@ -79,11 +79,23 @@ public enum OptionalAvatarChange<Wrapped: Equatable>: Equatable {
|
||||
}
|
||||
|
||||
public protocol ProfileManager: ProfileManagerProtocol {
|
||||
|
||||
// MARK: -
|
||||
|
||||
func fetchLocalUsersProfile(authedAccount: AuthedAccount) -> Promise<FetchedProfile>
|
||||
func fetchUserProfiles(for addresses: [SignalServiceAddress], tx: SDSAnyReadTransaction) -> [OWSUserProfile?]
|
||||
|
||||
func reuploadLocalProfile(
|
||||
unsavedRotatedProfileKey: OWSAES256Key?,
|
||||
mustReuploadAvatar: Bool,
|
||||
authedAccount: AuthedAccount,
|
||||
tx: DBWriteTransaction
|
||||
) -> Promise<Void>
|
||||
|
||||
func downloadAndDecryptLocalUserAvatarIfNeeded(authedAccount: AuthedAccount) async throws
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Downloads & decrypts the avatar at a particular URL.
|
||||
///
|
||||
/// While this method de-dupes in-flight requests, it won't de-dupe requests
|
||||
@ -119,13 +131,6 @@ public protocol ProfileManager: ProfileManagerProtocol {
|
||||
tx: SDSAnyWriteTransaction
|
||||
) -> Promise<Void>
|
||||
|
||||
func reuploadLocalProfile(
|
||||
unsavedRotatedProfileKey: OWSAES256Key?,
|
||||
mustReuploadAvatar: Bool,
|
||||
authedAccount: AuthedAccount,
|
||||
tx: DBWriteTransaction
|
||||
) -> Promise<Void>
|
||||
|
||||
func didSendOrReceiveMessage(
|
||||
serviceId: ServiceId,
|
||||
localIdentifiers: LocalIdentifiers,
|
||||
@ -150,4 +155,9 @@ public protocol ProfileManager: ProfileManagerProtocol {
|
||||
localIdentifiers: LocalIdentifiers,
|
||||
tx: DBWriteTransaction
|
||||
)
|
||||
|
||||
// MARK: -
|
||||
|
||||
func allWhitelistedAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress]
|
||||
func allWhitelistedRegisteredAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress]
|
||||
}
|
||||
|
||||
@ -115,9 +115,6 @@ typedef NS_ENUM(NSUInteger, UserProfileWriter) {
|
||||
|
||||
- (nullable ModelReadCacheSizeLease *)leaseCacheSize:(NSInteger)size;
|
||||
|
||||
- (NSArray<SignalServiceAddress *> *)allWhitelistedRegisteredAddressesWithTx:(SDSAnyReadTransaction *)tx
|
||||
NS_SWIFT_NAME(allWhitelistedRegisteredAddresses(tx:));
|
||||
|
||||
/**
|
||||
* Rotates the local profile key. Intended specifically for the
|
||||
* use case of recipient hiding.
|
||||
|
||||
@ -525,6 +525,7 @@ class StorageServiceContactRecordUpdater: StorageServiceRecordUpdater {
|
||||
)
|
||||
let localUserProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: profileAddress,
|
||||
userProfileWriter: .storageService,
|
||||
tx: SDSDB.shimOnlyBridge(tx)
|
||||
)
|
||||
localUserProfile.update(
|
||||
@ -1351,7 +1352,10 @@ class StorageServiceAccountRecordUpdater: StorageServiceRecordUpdater {
|
||||
|| localUserProfile?.familyName != normalizedRemoteFamilyName
|
||||
|| localAvatarUrl != record.avatarURL
|
||||
) {
|
||||
let localUserProfile = OWSUserProfile.getOrBuildUserProfileForLocalUser(tx: transaction)
|
||||
let localUserProfile = OWSUserProfile.getOrBuildUserProfileForLocalUser(
|
||||
userProfileWriter: .storageService,
|
||||
tx: transaction
|
||||
)
|
||||
localUserProfile.update(
|
||||
givenName: .setTo(normalizedRemoteGivenName),
|
||||
familyName: .setTo(normalizedRemoteFamilyName),
|
||||
@ -1555,7 +1559,7 @@ class StorageServiceAccountRecordUpdater: StorageServiceRecordUpdater {
|
||||
|
||||
let localHasSetMyStoriesPrivacy = StoryManager.hasSetMyStoriesPrivacy(transaction: transaction)
|
||||
if !localHasSetMyStoriesPrivacy && record.myStoryPrivacyHasBeenSet {
|
||||
StoryManager.setHasSetMyStoriesPrivacy(transaction: transaction, shouldUpdateStorageService: false)
|
||||
StoryManager.setHasSetMyStoriesPrivacy(true, shouldUpdateStorageService: false, transaction: transaction)
|
||||
}
|
||||
|
||||
let localHasReadOnboardingStory = systemStoryManager.isOnboardingStoryRead(transaction: transaction)
|
||||
|
||||
@ -14,8 +14,11 @@ public class MockSSKEnvironment: NSObject {
|
||||
/// Set up a mock SSK environment as well as ``DependenciesBridge``.
|
||||
@objc
|
||||
public static func activate() {
|
||||
let testAppContext = TestAppContext()
|
||||
SetCurrentAppContext(testAppContext)
|
||||
|
||||
let finalContinuation = AppSetup().start(
|
||||
appContext: TestAppContext(),
|
||||
appContext: testAppContext,
|
||||
databaseStorage: try! SDSDatabaseStorage(
|
||||
databaseFileUrl: SDSDatabaseStorage.grdbDatabaseFileUrl,
|
||||
keychainStorage: MockKeychainStorage()
|
||||
|
||||
@ -245,11 +245,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
- (NSArray<SignalServiceAddress *> *)allWhitelistedRegisteredAddressesWithTx:(SDSAnyReadTransaction *)tx
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (void)rotateProfileKeyUponRecipientHideWithTx:(SDSAnyWriteTransaction *)tx
|
||||
{
|
||||
// Do nothing.
|
||||
|
||||
@ -90,6 +90,9 @@ extension OWSFakeProfileManager: ProfileManager {
|
||||
tx: DBWriteTransaction
|
||||
) {
|
||||
}
|
||||
|
||||
public func allWhitelistedAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress] { [] }
|
||||
public func allWhitelistedRegisteredAddresses(tx: SDSAnyReadTransaction) -> [SignalServiceAddress] { [] }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -789,12 +789,20 @@ public final class OWSUserProfile: NSObject, NSCopying, SDSCodableModel, Decodab
|
||||
}
|
||||
|
||||
@objc
|
||||
public class func getOrBuildUserProfileForLocalUser(tx: SDSAnyWriteTransaction) -> OWSUserProfile {
|
||||
return getOrBuildUserProfile(for: .localUser, tx: tx)
|
||||
public class func getOrBuildUserProfileForLocalUser(
|
||||
userProfileWriter: UserProfileWriter,
|
||||
tx: SDSAnyWriteTransaction
|
||||
) -> OWSUserProfile {
|
||||
return getOrBuildUserProfile(
|
||||
for: .localUser,
|
||||
userProfileWriter: userProfileWriter,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
|
||||
public class func getOrBuildUserProfile(
|
||||
for insertableAddress: InsertableAddress,
|
||||
userProfileWriter: UserProfileWriter,
|
||||
tx: SDSAnyWriteTransaction
|
||||
) -> OWSUserProfile {
|
||||
// If we already have a profile for this address, return it.
|
||||
@ -815,7 +823,7 @@ public final class OWSUserProfile: NSObject, NSCopying, SDSCodableModel, Decodab
|
||||
if case .localUser = address {
|
||||
userProfile.update(
|
||||
profileKey: .setTo(OWSAES256Key.generateRandom()),
|
||||
userProfileWriter: .localUser,
|
||||
userProfileWriter: userProfileWriter,
|
||||
transaction: tx,
|
||||
completion: nil
|
||||
)
|
||||
|
||||
@ -92,6 +92,7 @@ class SignalRecipientTest: SSKBaseTest {
|
||||
write { transaction in
|
||||
let aciProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: .otherUser(aci),
|
||||
userProfileWriter: .tests,
|
||||
tx: transaction
|
||||
)
|
||||
aciProfile.anyInsert(transaction: transaction)
|
||||
@ -154,7 +155,11 @@ class SignalRecipientTest: SSKBaseTest {
|
||||
let oldMessage = messageBuilder.build()
|
||||
oldMessage.anyInsert(transaction: transaction)
|
||||
|
||||
let oldPhoneNumberProfile = OWSUserProfile.getOrBuildUserProfile(for: .otherUser(aci), tx: transaction)
|
||||
let oldPhoneNumberProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: .otherUser(aci),
|
||||
userProfileWriter: .tests,
|
||||
tx: transaction
|
||||
)
|
||||
oldPhoneNumberProfile.anyInsert(transaction: transaction)
|
||||
oldPhoneNumberProfile.update(
|
||||
isPhoneNumberShared: .setTo(true),
|
||||
@ -183,7 +188,11 @@ class SignalRecipientTest: SSKBaseTest {
|
||||
uniqueId: oldMessage.uniqueId,
|
||||
transaction: transaction
|
||||
)!
|
||||
let newProfile = OWSUserProfile.getOrBuildUserProfile(for: .otherUser(aci), tx: transaction)
|
||||
let newProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: .otherUser(aci),
|
||||
userProfileWriter: .tests,
|
||||
tx: transaction
|
||||
)
|
||||
let newAccount = SignalAccount.anyFetch(
|
||||
uniqueId: oldAccount.uniqueId,
|
||||
transaction: transaction
|
||||
@ -259,7 +268,11 @@ class SignalRecipientTest: SSKBaseTest {
|
||||
uniqueId: oldMessage.uniqueId,
|
||||
transaction: transaction
|
||||
)!
|
||||
let newProfile = OWSUserProfile.getOrBuildUserProfile(for: .otherUser(newAci), tx: transaction)
|
||||
let newProfile = OWSUserProfile.getOrBuildUserProfile(
|
||||
for: .otherUser(newAci),
|
||||
userProfileWriter: .tests,
|
||||
tx: transaction
|
||||
)
|
||||
let newAccount = SignalAccount.anyFetch(
|
||||
uniqueId: oldAccount.uniqueId,
|
||||
transaction: transaction
|
||||
|
||||
@ -0,0 +1,177 @@
|
||||
//
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import GRDB
|
||||
import LibSignalClient
|
||||
import XCTest
|
||||
|
||||
@testable import SignalServiceKit
|
||||
|
||||
private extension MessageBackupIntegrationTestCase {
|
||||
var depBridge: DependenciesBridge { .shared }
|
||||
|
||||
func skipTestForNow() throws {
|
||||
// [Backup] TODO: unwind this once we've codified shared integration test cases.
|
||||
throw XCTSkip("Skipped while we codify shared integration test cases.")
|
||||
}
|
||||
}
|
||||
|
||||
final class MessageBackupAccountDataTest: MessageBackupIntegrationTestCase {
|
||||
func testAccountData() async throws {
|
||||
try skipTestForNow()
|
||||
|
||||
try await runTest(backupName: "account-data") { sdsTx, tx in
|
||||
XCTAssertNotNil(profileManager.localProfileKey())
|
||||
|
||||
switch depBridge.localUsernameManager.usernameState(tx: tx) {
|
||||
case .available(let username, let usernameLink):
|
||||
XCTAssertEqual(username, "boba_fett.66")
|
||||
XCTAssertEqual(usernameLink.handle, UUID("61C101A2-00D5-4217-89C2-0518D8497AF0"))
|
||||
XCTAssertEqual(depBridge.localUsernameManager.usernameLinkQRCodeColor(tx: tx), .olive)
|
||||
case .unset, .linkCorrupted, .usernameAndLinkCorrupted:
|
||||
XCTFail("Unexpected username state!")
|
||||
}
|
||||
|
||||
XCTAssertEqual(profileManager.localGivenName(), "Boba")
|
||||
XCTAssertEqual(profileManager.localFamilyName(), "Fett")
|
||||
XCTAssertNil(profileManager.localProfileAvatarData())
|
||||
|
||||
XCTAssertNotNil(subscriptionManager.getSubscriberID(transaction: sdsTx))
|
||||
XCTAssertEqual(subscriptionManager.getSubscriberCurrencyCode(transaction: sdsTx), "USD")
|
||||
XCTAssertTrue(subscriptionManager.userManuallyCancelledSubscription(transaction: sdsTx))
|
||||
|
||||
XCTAssertTrue(receiptManager.areReadReceiptsEnabled(transaction: sdsTx))
|
||||
XCTAssertTrue(preferences.shouldShowUnidentifiedDeliveryIndicators(transaction: sdsTx))
|
||||
XCTAssertTrue(typingIndicatorsImpl.areTypingIndicatorsEnabled())
|
||||
XCTAssertFalse(SSKPreferences.areLinkPreviewsEnabled(transaction: sdsTx))
|
||||
XCTAssertEqual(depBridge.phoneNumberDiscoverabilityManager.phoneNumberDiscoverability(tx: tx), .nobody)
|
||||
XCTAssertTrue(SSKPreferences.preferContactAvatars(transaction: sdsTx))
|
||||
let universalExpireConfig = depBridge.disappearingMessagesConfigurationStore.fetch(for: .universal, tx: tx)
|
||||
XCTAssertEqual(universalExpireConfig?.isEnabled, true)
|
||||
XCTAssertEqual(universalExpireConfig?.durationSeconds, 3600)
|
||||
XCTAssertEqual(ReactionManager.customEmojiSet(transaction: sdsTx), ["🏎️"])
|
||||
XCTAssertTrue(subscriptionManager.displayBadgesOnProfile(transaction: sdsTx))
|
||||
XCTAssertTrue(SSKPreferences.shouldKeepMutedChatsArchived(transaction: sdsTx))
|
||||
XCTAssertTrue(StoryManager.hasSetMyStoriesPrivacy(transaction: sdsTx))
|
||||
XCTAssertTrue(systemStoryManager.isOnboardingStoryRead(transaction: sdsTx))
|
||||
XCTAssertFalse(StoryManager.areStoriesEnabled(transaction: sdsTx))
|
||||
XCTAssertTrue(StoryManager.areViewReceiptsEnabled(transaction: sdsTx))
|
||||
XCTAssertTrue(systemStoryManager.isOnboardingOverlayViewed(transaction: sdsTx))
|
||||
XCTAssertFalse(depBridge.usernameEducationManager.shouldShowUsernameEducation(tx: tx))
|
||||
XCTAssertEqual(udManager.phoneNumberSharingMode(tx: tx), .nobody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class MessageBackupContactTest: MessageBackupIntegrationTestCase {
|
||||
private func assert(
|
||||
recipient: SignalRecipient,
|
||||
aci: Aci = .fixture,
|
||||
pni: Pni = .fixture,
|
||||
username: String = "han_solo.44",
|
||||
phoneNumber: String = "+17735550199",
|
||||
isBlocked: Bool,
|
||||
isHidden: Bool,
|
||||
isRegistered: Bool,
|
||||
unregisteredAtTimestamp: UInt64?,
|
||||
isWhitelisted: Bool,
|
||||
givenName: String = "Han",
|
||||
familyName: String = "Solo",
|
||||
isStoryHidden: Bool = true,
|
||||
sdsTx: SDSAnyReadTransaction,
|
||||
tx: DBReadTransaction
|
||||
) {
|
||||
XCTAssertEqual(recipient.aci, aci)
|
||||
XCTAssertEqual(recipient.pni, pni)
|
||||
XCTAssertEqual(depBridge.usernameLookupManager.fetchUsername(forAci: recipient.aci!, transaction: tx), username)
|
||||
XCTAssertEqual(recipient.phoneNumber?.stringValue, phoneNumber)
|
||||
XCTAssertEqual(blockingManager.isAddressBlocked(recipient.address, transaction: sdsTx), isBlocked)
|
||||
XCTAssertEqual(depBridge.recipientHidingManager.isHiddenRecipient(recipient, tx: tx), isHidden)
|
||||
XCTAssertEqual(recipient.isRegistered, isRegistered)
|
||||
XCTAssertEqual(recipient.unregisteredAtTimestamp, unregisteredAtTimestamp)
|
||||
let recipientProfile = profileManager.getUserProfile(for: recipient.address, transaction: sdsTx)
|
||||
XCTAssertNotNil(recipientProfile?.profileKey)
|
||||
XCTAssertEqual(profileManager.isUser(inProfileWhitelist: recipient.address, transaction: sdsTx), isWhitelisted)
|
||||
XCTAssertEqual(recipientProfile?.givenName, givenName)
|
||||
XCTAssertEqual(recipientProfile?.familyName, familyName)
|
||||
XCTAssertEqual(StoryStoreImpl().getOrCreateStoryContextAssociatedData(for: recipient.aci!, tx: tx).isHidden, isStoryHidden)
|
||||
}
|
||||
|
||||
func testRegisteredBlockedContact() async throws {
|
||||
try skipTestForNow()
|
||||
|
||||
try await runTest(backupName: "registered-blocked-contact") { sdsTx, tx in
|
||||
let allRecipients = depBridge.recipientDatabaseTable.allRecipients(tx: tx)
|
||||
XCTAssertEqual(allRecipients.count, 1)
|
||||
|
||||
assert(
|
||||
recipient: allRecipients.first!,
|
||||
isBlocked: true,
|
||||
isHidden: true,
|
||||
isRegistered: true,
|
||||
unregisteredAtTimestamp: nil,
|
||||
isWhitelisted: false,
|
||||
sdsTx: sdsTx,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func testUnregisteredContact() async throws {
|
||||
try skipTestForNow()
|
||||
|
||||
try await runTest(backupName: "unregistered-contact") { sdsTx, tx in
|
||||
let allRecipients = depBridge.recipientDatabaseTable.allRecipients(tx: tx)
|
||||
XCTAssertEqual(allRecipients.count, 1)
|
||||
|
||||
assert(
|
||||
recipient: allRecipients.first!,
|
||||
isBlocked: false,
|
||||
isHidden: false,
|
||||
isRegistered: false,
|
||||
unregisteredAtTimestamp: 1713157772000,
|
||||
isWhitelisted: true,
|
||||
sdsTx: sdsTx,
|
||||
tx: tx
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private extension RecipientDatabaseTable {
|
||||
func allRecipients(tx: any DBReadTransaction) -> [SignalRecipient] {
|
||||
var result = [SignalRecipient]()
|
||||
enumerateAll(tx: tx) { result.append($0) }
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: _
|
||||
|
||||
private extension UUID {
|
||||
init(_ string: String) {
|
||||
self.init(uuidString: string)!
|
||||
}
|
||||
}
|
||||
|
||||
private extension Aci {
|
||||
/// Corresponds to base64 data `QHaZXgUxQEKp5B5np33zWA==`.
|
||||
static let fixture: Aci = Aci("4076995E-0531-4042-A9E4-1E67A77DF358")
|
||||
|
||||
convenience init(_ string: String) {
|
||||
self.init(fromUUID: UUID(string))
|
||||
}
|
||||
}
|
||||
|
||||
private extension Pni {
|
||||
/// Corresponds to base64 data `JvwCorpYSn2wgZ2iOXFXCg==`.
|
||||
static let fixture: Pni = Pni("26FC02A2-BA58-4A7D-B081-9DA23971570A")
|
||||
|
||||
convenience init(_ string: String) {
|
||||
self.init(fromUUID: UUID(string))
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,175 @@
|
||||
//
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import LibSignalClient
|
||||
import XCTest
|
||||
|
||||
@testable import SignalServiceKit
|
||||
|
||||
class MessageBackupIntegrationTestCase: XCTestCase {
|
||||
override func setUp() {
|
||||
DDLog.add(DDTTYLogger.sharedInstance!)
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private var messageBackupManager: MessageBackupManager {
|
||||
DependenciesBridge.shared.messageBackupManager
|
||||
}
|
||||
|
||||
private var localIdentifiers: LocalIdentifiers {
|
||||
/// A backup doesn't contain our own local identifiers. Rather, those
|
||||
/// are determined as part of registration for a backup import, and are
|
||||
/// already-known for a backup export.
|
||||
///
|
||||
/// Consequently, we can use any local identifiers for our test
|
||||
/// purposes without worrying about the contents of each test case's
|
||||
/// backup file.
|
||||
return .forUnitTests
|
||||
}
|
||||
|
||||
func runTest(
|
||||
backupName: String,
|
||||
assertionsBlock: (SDSAnyReadTransaction, DBReadTransaction) throws -> Void
|
||||
) async throws {
|
||||
try await importAndAssert(
|
||||
localIdentifiers: localIdentifiers,
|
||||
backupUrl: backupFileUrl(named: backupName),
|
||||
assertionsBlock: assertionsBlock
|
||||
)
|
||||
|
||||
let exportedBackupUrl = try await messageBackupManager
|
||||
.exportPlaintextBackup(localIdentifiers: localIdentifiers)
|
||||
|
||||
try await importAndAssert(
|
||||
localIdentifiers: localIdentifiers,
|
||||
backupUrl: exportedBackupUrl,
|
||||
assertionsBlock: assertionsBlock
|
||||
)
|
||||
}
|
||||
|
||||
private func backupFileUrl(named backupName: String) -> URL {
|
||||
let testBundle = Bundle(for: type(of: self))
|
||||
return testBundle.url(forResource: backupName, withExtension: "binproto")!
|
||||
}
|
||||
|
||||
private func importAndAssert(
|
||||
localIdentifiers: LocalIdentifiers,
|
||||
backupUrl: URL,
|
||||
assertionsBlock: (SDSAnyReadTransaction, DBReadTransaction) throws -> Void
|
||||
) async throws {
|
||||
await initializeApp()
|
||||
|
||||
try await messageBackupManager.importPlaintextBackup(
|
||||
fileUrl: backupUrl,
|
||||
localIdentifiers: localIdentifiers
|
||||
)
|
||||
|
||||
try NSObject.databaseStorage.read { tx in
|
||||
try assertionsBlock(tx, tx.asV2Read)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@MainActor
|
||||
final func initializeApp() async {
|
||||
let testAppContext = TestAppContext()
|
||||
SetCurrentAppContext(testAppContext)
|
||||
|
||||
/// Note that ``SDSDatabaseStorage/grdbDatabaseFileUrl``, through a few
|
||||
/// layers of abstraction, uses the "current app context" to decide
|
||||
/// where to put the database,
|
||||
///
|
||||
/// For a ``TestAppContext`` as configured above, this will be a
|
||||
/// subdirectory of our temp directory unique to the instantiation of
|
||||
/// the app context.
|
||||
let databaseStorage = try! SDSDatabaseStorage(
|
||||
databaseFileUrl: SDSDatabaseStorage.grdbDatabaseFileUrl,
|
||||
keychainStorage: MockKeychainStorage()
|
||||
)
|
||||
|
||||
/// We use crashy versions of dependencies that should never be called
|
||||
/// during backups, and no-op implementations of payments because those
|
||||
/// are bound to the SignalUI target.
|
||||
_ = await AppSetup().start(
|
||||
appContext: testAppContext,
|
||||
databaseStorage: databaseStorage,
|
||||
paymentsEvents: PaymentsEventsNoop(),
|
||||
mobileCoinHelper: MobileCoinHelperMock(),
|
||||
callMessageHandler: CrashyMocks.MockCallMessageHandler(),
|
||||
currentCallThreadProvider: CrashyMocks.MockCurrentCallThreadProvider(),
|
||||
notificationPresenter: CrashyMocks.MockNotificationPresenter(),
|
||||
testDependencies: AppSetup.TestDependencies(
|
||||
networkManager: CrashyMocks.MockNetworkManager(),
|
||||
webSocketFactory: CrashyMocks.MockWebSocketFactory()
|
||||
)
|
||||
).prepareDatabase().awaitable()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private func failTest<T>(
|
||||
_ type: T.Type,
|
||||
_ function: StaticString = #function
|
||||
) -> Never {
|
||||
let message = "Unexpectedly called \(type)#\(function)!"
|
||||
XCTFail(message)
|
||||
owsFail(message)
|
||||
}
|
||||
|
||||
/// As a rule, integration tests for message backup should not mock out their
|
||||
/// dependencies as their goal is to validate how the real, production app will
|
||||
/// behave with respect to Backups.
|
||||
///
|
||||
/// These mocks are the exceptions to that rule, and encompass managers that
|
||||
/// should never be invoked during Backup import or export.
|
||||
private enum CrashyMocks {
|
||||
final class MockNetworkManager: NetworkManager {
|
||||
override func makePromise(request: TSRequest, canUseWebSocket: Bool = false) -> Promise<any HTTPResponse> { failTest(Self.self) }
|
||||
}
|
||||
|
||||
final class MockWebSocketFactory: WebSocketFactory {
|
||||
var canBuildWebSocket: Bool { failTest(Self.self) }
|
||||
func buildSocket(request: WebSocketRequest, callbackScheduler: any Scheduler) -> (any SSKWebSocket)? { failTest(Self.self) }
|
||||
}
|
||||
|
||||
final class MockCallMessageHandler: CallMessageHandler {
|
||||
func action(for envelope: SSKProtoEnvelope, callMessage: SSKProtoCallMessage, serverDeliveryTimestamp: UInt64) -> CallMessageAction { failTest(Self.self) }
|
||||
func receivedOffer(_ offer: SSKProtoCallMessageOffer, from caller: (aci: Aci, deviceId: UInt32), sentAtTimestamp: UInt64, serverReceivedTimestamp: UInt64, serverDeliveryTimestamp: UInt64, tx: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
func receivedAnswer(_ answer: SSKProtoCallMessageAnswer, from caller: (aci: Aci, deviceId: UInt32)) { failTest(Self.self) }
|
||||
func receivedIceUpdate(_ iceUpdate: [SSKProtoCallMessageIceUpdate], from caller: (aci: Aci, deviceId: UInt32)) { failTest(Self.self) }
|
||||
func receivedHangup(_ hangup: SSKProtoCallMessageHangup, from caller: (aci: Aci, deviceId: UInt32)) { failTest(Self.self) }
|
||||
func receivedBusy(_ busy: SSKProtoCallMessageBusy, from caller: (aci: Aci, deviceId: UInt32)) { failTest(Self.self) }
|
||||
func receivedOpaque(_ opaque: SSKProtoCallMessageOpaque, from caller: (aci: Aci, deviceId: UInt32), serverReceivedTimestamp: UInt64, serverDeliveryTimestamp: UInt64, tx: SDSAnyReadTransaction) { failTest(Self.self) }
|
||||
func receivedGroupCallUpdateMessage(_ updateMessage: SSKProtoDataMessageGroupCallUpdate, for thread: TSGroupThread, serverReceivedTimestamp: UInt64) async { failTest(Self.self) }
|
||||
func externallyHandleCallMessage(envelope: SSKProtoEnvelope, plaintextData: Data, wasReceivedByUD: Bool, serverDeliveryTimestamp: UInt64, tx: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
}
|
||||
|
||||
final class MockCurrentCallThreadProvider: CurrentCallThreadProvider {
|
||||
var currentCallThread: TSThread? { failTest(Self.self) }
|
||||
}
|
||||
|
||||
final class MockNotificationPresenter: NotificationPresenter {
|
||||
func notifyUser(forIncomingMessage: TSIncomingMessage, thread: TSThread, transaction: SDSAnyReadTransaction) { failTest(Self.self) }
|
||||
func notifyUser(forIncomingMessage: TSIncomingMessage, editTarget: TSIncomingMessage, thread: TSThread, transaction: SDSAnyReadTransaction) { failTest(Self.self) }
|
||||
func notifyUser(forReaction: OWSReaction, onOutgoingMessage: TSOutgoingMessage, thread: TSThread, transaction: SDSAnyReadTransaction) { failTest(Self.self) }
|
||||
func notifyUser(forErrorMessage: TSErrorMessage, thread: TSThread, transaction: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
func notifyUser(forTSMessage: TSMessage, thread: TSThread, wantsSound: Bool, transaction: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
func notifyUser(forPreviewableInteraction: any TSInteraction & OWSPreviewText, thread: TSThread, wantsSound: Bool, transaction: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
func notifyTestPopulation(ofErrorMessage errorString: String) { failTest(Self.self) }
|
||||
func notifyUser(forFailedStorySend: StoryMessage, to: TSThread, transaction: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
func notifyUserToRelaunchAfterTransfer(completion: (() -> Void)?) { failTest(Self.self) }
|
||||
func notifyUserOfDeregistration(transaction: SDSAnyWriteTransaction) { failTest(Self.self) }
|
||||
func clearAllNotifications() { failTest(Self.self) }
|
||||
func cancelNotifications(threadId: String) { failTest(Self.self) }
|
||||
func cancelNotifications(messageIds: [String]) { failTest(Self.self) }
|
||||
func cancelNotifications(reactionId: String) { failTest(Self.self) }
|
||||
func cancelNotificationsForMissedCalls(threadUniqueId: String) { failTest(Self.self) }
|
||||
func cancelNotifications(for storyMessage: StoryMessage) { failTest(Self.self) }
|
||||
func notifyUserOfDeregistration(tx: any DBWriteTransaction) { failTest(Self.self) }
|
||||
}
|
||||
}
|
||||
9
SignalServiceKit/tests/MessageBackup/Scripts/generate-base64-bytes.zsh
Executable file
9
SignalServiceKit/tests/MessageBackup/Scripts/generate-base64-bytes.zsh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
length=32
|
||||
else
|
||||
length="$1"
|
||||
fi
|
||||
|
||||
openssl rand -base64 "$length"
|
||||
6
SignalServiceKit/tests/MessageBackup/Scripts/generate-base64-uuid.zsh
Executable file
6
SignalServiceKit/tests/MessageBackup/Scripts/generate-base64-uuid.zsh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
uuid=$(uuidgen)
|
||||
|
||||
echo "UUID: $uuid"
|
||||
echo "UUID Base64: $(echo $uuid | xxd -r -p | base64)"
|
||||
@ -0,0 +1,42 @@
|
||||
[
|
||||
{
|
||||
"version": "1",
|
||||
"backupTimeMs": "1715636551000"
|
||||
},
|
||||
{
|
||||
"account": {
|
||||
"profileKey": "YQKRq+3DQklInaOaMcmlzZnN0m/1hzLiaONX7gB12dg=",
|
||||
"username": "boba_fett.66",
|
||||
"usernameLink": {
|
||||
"entropy": "ZWdcc9AOsBAF47t8SkfylstlVPeJgSOIFekV2CT9LpM=",
|
||||
"serverId": "YcEBogDVQheJwgUY2El68A==",
|
||||
"color": "OLIVE"
|
||||
},
|
||||
"givenName": "Boba",
|
||||
"familyName": "Fett",
|
||||
"avatarUrlPath": "",
|
||||
"subscriberId": "7LtoxzQzGi6jM82nR8mMRVNlImFYK0/OWuDeqE3OZRk=",
|
||||
"subscriberCurrencyCode": "USD",
|
||||
"subscriptionManuallyCancelled": true,
|
||||
"accountSettings": {
|
||||
"readReceipts": true,
|
||||
"sealedSenderIndicators": true,
|
||||
"typingIndicators": true,
|
||||
"linkPreviews": false,
|
||||
"notDiscoverableByPhoneNumber": true,
|
||||
"preferContactAvatars": true,
|
||||
"universalExpireTimer": 3600,
|
||||
"preferredReactionEmoji": ["🏎️"],
|
||||
"displayBadgesOnProfile": true,
|
||||
"keepMutedChatsArchived": true,
|
||||
"hasSetMyStoriesPrivacy": true,
|
||||
"hasViewedOnboardingStory": true,
|
||||
"storiesDisabled": true,
|
||||
"storyViewReceiptsEnabled": true,
|
||||
"hasSeenGroupStoryEducationSheet": true,
|
||||
"hasCompletedUsernameOnboarding": true,
|
||||
"phoneNumberSharingMode": "NOBODY"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"version": "1",
|
||||
"backupTimeMs": "1715636551000"
|
||||
},
|
||||
{
|
||||
"account": {
|
||||
"profileKey": "YQKRq+3DQklInaOaMcmlzZnN0m/1hzLiaONX7gB12dg=",
|
||||
"givenName": "Boba",
|
||||
"familyName": "Fett",
|
||||
"avatarUrlPath": "",
|
||||
"subscriberId": "",
|
||||
"subscriberCurrencyCode": "",
|
||||
"subscriptionManuallyCancelled": false,
|
||||
"accountSettings": {
|
||||
"readReceipts": false,
|
||||
"sealedSenderIndicators": true,
|
||||
"typingIndicators": false,
|
||||
"linkPreviews": false,
|
||||
"notDiscoverableByPhoneNumber": false,
|
||||
"preferContactAvatars": false,
|
||||
"universalExpireTimer": 0,
|
||||
"preferredReactionEmoji": [],
|
||||
"displayBadgesOnProfile": false,
|
||||
"keepMutedChatsArchived": false,
|
||||
"hasSetMyStoriesPrivacy": false,
|
||||
"hasViewedOnboardingStory": false,
|
||||
"storiesDisabled": false,
|
||||
"storyViewReceiptsEnabled": false,
|
||||
"hasSeenGroupStoryEducationSheet": false,
|
||||
"hasCompletedUsernameOnboarding": false,
|
||||
"phoneNumberSharingMode": "NOBODY"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"recipient": {
|
||||
"id": "1",
|
||||
"self": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"recipient": {
|
||||
"id": "2",
|
||||
"contact": {
|
||||
"aci": "QHaZXgUxQEKp5B5np33zWA==",
|
||||
"pni": "JvwCorpYSn2wgZ2iOXFXCg==",
|
||||
"username": "han_solo.44",
|
||||
"e164": "17735550199",
|
||||
"blocked": true,
|
||||
"hidden": true,
|
||||
"registered": "REGISTERED",
|
||||
"unregisteredTimestamp": 0,
|
||||
"profileKey": "nH0NX5+LqtIe85lAy958oyRNH9INMHFn2eb1VF6i4/o=",
|
||||
"profileSharing": false,
|
||||
"profileGivenName": "Han",
|
||||
"profileFamilyName": "Solo",
|
||||
"hideStory": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chat": {
|
||||
"id": "1",
|
||||
"recipientId": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"chat": {
|
||||
"id": "2",
|
||||
"recipientId": "2"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"version": "1",
|
||||
"backupTimeMs": "1715636551000"
|
||||
},
|
||||
{
|
||||
"account": {
|
||||
"profileKey": "YQKRq+3DQklInaOaMcmlzZnN0m/1hzLiaONX7gB12dg=",
|
||||
"givenName": "Boba",
|
||||
"familyName": "Fett",
|
||||
"avatarUrlPath": "",
|
||||
"subscriberId": "",
|
||||
"subscriberCurrencyCode": "",
|
||||
"subscriptionManuallyCancelled": false,
|
||||
"accountSettings": {
|
||||
"readReceipts": false,
|
||||
"sealedSenderIndicators": true,
|
||||
"typingIndicators": false,
|
||||
"linkPreviews": false,
|
||||
"notDiscoverableByPhoneNumber": false,
|
||||
"preferContactAvatars": false,
|
||||
"universalExpireTimer": 0,
|
||||
"preferredReactionEmoji": [],
|
||||
"displayBadgesOnProfile": false,
|
||||
"keepMutedChatsArchived": false,
|
||||
"hasSetMyStoriesPrivacy": false,
|
||||
"hasViewedOnboardingStory": false,
|
||||
"storiesDisabled": false,
|
||||
"storyViewReceiptsEnabled": false,
|
||||
"hasSeenGroupStoryEducationSheet": false,
|
||||
"hasCompletedUsernameOnboarding": false,
|
||||
"phoneNumberSharingMode": "NOBODY"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"recipient": {
|
||||
"id": "1",
|
||||
"self": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"recipient": {
|
||||
"id": "2",
|
||||
"contact": {
|
||||
"aci": "QHaZXgUxQEKp5B5np33zWA==",
|
||||
"pni": "JvwCorpYSn2wgZ2iOXFXCg==",
|
||||
"username": "han_solo.44",
|
||||
"e164": "17735550199",
|
||||
"blocked": false,
|
||||
"hidden": false,
|
||||
"registered": "NOT_REGISTERED",
|
||||
"unregisteredTimestamp": 1713157772000,
|
||||
"profileKey": "nH0NX5+LqtIe85lAy958oyRNH9INMHFn2eb1VF6i4/o=",
|
||||
"profileSharing": true,
|
||||
"profileGivenName": "Han",
|
||||
"profileFamilyName": "Solo",
|
||||
"hideStory": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chat": {
|
||||
"id": "1",
|
||||
"recipientId": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"chat": {
|
||||
"id": "2",
|
||||
"recipientId": "2"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -10,7 +10,6 @@ import CocoaLumberjack
|
||||
public class SSKBaseTest: XCTestCase {
|
||||
public override func setUp() {
|
||||
DDLog.add(DDTTYLogger.sharedInstance!)
|
||||
SetCurrentAppContext(TestAppContext())
|
||||
MockSSKEnvironment.activate()
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user