diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index eeb3b4ad6f..e82d8bfafd 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -2763,6 +2763,9 @@ 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 */; }; + D9C96F712E21A6BE00CA885A /* BackupCDNReadCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C96F702E21A6B900CA885A /* BackupCDNReadCredential.swift */; }; + D9C96F752E21AA5800CA885A /* BackupCDNCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C96F742E21AA4900CA885A /* BackupCDNCache.swift */; }; + D9C96F772E21ADF000CA885A /* BackupCDNMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C96F762E21ADBE00CA885A /* BackupCDNMetadata.swift */; }; D9CA61482C2E2D0000F99EA3 /* BackupArchiveAdHocCallArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA61472C2E2D0000F99EA3 /* BackupArchiveAdHocCallArchiver.swift */; }; D9CA614B2C2F675E00F99EA3 /* PrivateStoryThreadDeletionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA614A2C2F675E00F99EA3 /* PrivateStoryThreadDeletionManager.swift */; }; D9CA8AB02B698DFF00787167 /* DeletedCallRecordCleanupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CA8AAF2B698DFF00787167 /* DeletedCallRecordCleanupManager.swift */; }; @@ -6720,6 +6723,9 @@ D9C964072BE44D510058F143 /* XCTest+Thenable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTest+Thenable.swift"; sourceTree = ""; }; D9C9640F2BE451CE0058F143 /* TSMessageStorageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSMessageStorageTest.swift; sourceTree = ""; }; D9C964132BE45A030058F143 /* SignedPreKeyDeletionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignedPreKeyDeletionTests.swift; sourceTree = ""; }; + D9C96F702E21A6B900CA885A /* BackupCDNReadCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupCDNReadCredential.swift; sourceTree = ""; }; + D9C96F742E21AA4900CA885A /* BackupCDNCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupCDNCache.swift; sourceTree = ""; }; + D9C96F762E21ADBE00CA885A /* BackupCDNMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupCDNMetadata.swift; sourceTree = ""; }; D9CA61472C2E2D0000F99EA3 /* BackupArchiveAdHocCallArchiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupArchiveAdHocCallArchiver.swift; sourceTree = ""; }; D9CA614A2C2F675E00F99EA3 /* PrivateStoryThreadDeletionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateStoryThreadDeletionManager.swift; sourceTree = ""; }; D9CA8AAF2B698DFF00787167 /* DeletedCallRecordCleanupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedCallRecordCleanupManager.swift; sourceTree = ""; }; @@ -9626,6 +9632,9 @@ 667BB2042C58073600E79B57 /* Attachments */, 66A1F4E02E035BE40095DE4B /* BackupExportJob */, D9388C8F2DA4751A0048D4F9 /* Settings */, + D9C96F742E21AA4900CA885A /* BackupCDNCache.swift */, + D9C96F762E21ADBE00CA885A /* BackupCDNMetadata.swift */, + D9C96F702E21A6B900CA885A /* BackupCDNReadCredential.swift */, C1A0F79C2B9F57340009DC0D /* BackupKeyMaterial.swift */, C1A0F79E2B9F59920009DC0D /* BackupKeyMaterialImpl.swift */, C14391122BD1C0DF00ED6FCB /* BackupRequestManager.swift */, @@ -17748,6 +17757,9 @@ 66734F012CA1ED3F00558494 /* BackupAttachmentUploadScheduler.swift in Sources */, 66C7952D2C9B78E900C13937 /* BackupAttachmentUploadStore.swift in Sources */, C18806342BD8080B0024044A /* BackupAuthCredentialManager.swift in Sources */, + D9C96F752E21AA5800CA885A /* BackupCDNCache.swift in Sources */, + D9C96F772E21ADF000CA885A /* BackupCDNMetadata.swift in Sources */, + D9C96F712E21A6BE00CA885A /* BackupCDNReadCredential.swift in Sources */, 66A1F4E22E035C020095DE4B /* BackupExportJob.swift in Sources */, D923DF9C2DC135D200CDAFC3 /* BackupIdManager.swift in Sources */, C1A0F79D2B9F57340009DC0D /* BackupKeyMaterial.swift in Sources */, diff --git a/SignalServiceKit/Backups/BackupCDNCache.swift b/SignalServiceKit/Backups/BackupCDNCache.swift new file mode 100644 index 0000000000..0366eee838 --- /dev/null +++ b/SignalServiceKit/Backups/BackupCDNCache.swift @@ -0,0 +1,138 @@ +// +// Copyright 2025 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +struct BackupCDNCache { + private enum Constants { + static let cdnMetadataLifetime: TimeInterval = BackupCDNReadCredential.lifetime + } + + private let kvStore: KeyValueStore + + init() { + self.kvStore = KeyValueStore(collection: "BackupCDNCache") + } + + // MARK: - + + func wipe(tx: DBWriteTransaction) { + kvStore.removeAll(transaction: tx) + } + + // MARK: - + + private static func backupCDNAuthCredentialKey( + cdnNumber: Int32, + authType: BackupAuthCredentialType, + ) -> String { + let cdn2 = "BackupCDN2:\(authType.rawValue)" + let cdn3 = "BackupCDN3:\(authType.rawValue)" + + switch cdnNumber { + case 2: + return cdn2 + case 3: + return cdn3 + default: + owsFailDebug("Unexpected CDN number \(cdnNumber): assuming CDN3!") + return cdn3 + } + } + + func backupCDNReadCredential( + cdnNumber: Int32, + authType: BackupAuthCredentialType, + now: Date, + tx: DBReadTransaction, + ) -> BackupCDNReadCredential? { + do { + let cachedCredential: BackupCDNReadCredential? = try kvStore.getCodableValue( + forKey: Self.backupCDNAuthCredentialKey(cdnNumber: cdnNumber, authType: authType), + transaction: tx + ) + + if + let cachedCredential, + !cachedCredential.isExpired(now: now) + { + return cachedCredential + } + } catch { + Logger.warn("Failed to deserialize BackupCDNReadCredential!") + } + + return nil + } + + func setBackupCDNReadCredential( + _ backupCDNReadCredential: BackupCDNReadCredential, + cdnNumber: Int32, + authType: BackupAuthCredentialType, + tx: DBWriteTransaction, + ) { + do { + try kvStore.setCodable( + backupCDNReadCredential, + key: Self.backupCDNAuthCredentialKey(cdnNumber: cdnNumber, authType: authType), + transaction: tx + ) + } catch { + Logger.warn("Failed to serialize BackupCDNReadCredential! \(error)") + } + } + + // MARK: - + + private static func backupCDNMetadataKeys(authType: BackupAuthCredentialType) -> ( + metadata: String, + metadataSavedDate: String + ) { + return ( + "BackupCDNMetadata:\(authType.rawValue)", + "BackupCDNMetadataSavedDate:\(authType.rawValue)", + ) + } + + func backupCDNMetadata( + authType: BackupAuthCredentialType, + now: Date, + tx: DBReadTransaction, + ) -> BackupCDNMetadata? { + let (metadataKey, metadataSavedDateKey) = Self.backupCDNMetadataKeys(authType: authType) + + if + let metadataSavedDate = kvStore.getDate(metadataSavedDateKey, transaction: tx), + now > metadataSavedDate.addingTimeInterval(Constants.cdnMetadataLifetime) + { + // It's been long enough that we should skip the cached value. + return nil + } + + do { + if let metadata: BackupCDNMetadata = try kvStore.getCodableValue(forKey: metadataKey, transaction: tx) { + return metadata + } + } catch { + Logger.warn("Failed to deserialize BackupCDNMetadata! \(error)") + } + + return nil + } + + func setBackupCDNMetadata( + _ backupCDNMetadata: BackupCDNMetadata, + authType: BackupAuthCredentialType, + dateProvider: DateProvider, + tx: DBWriteTransaction, + ) { + let (metadataKey, metadataSavedDateKey) = Self.backupCDNMetadataKeys(authType: authType) + + do { + try kvStore.setCodable(backupCDNMetadata, key: metadataKey, transaction: tx) + kvStore.setDate(dateProvider(), key: metadataSavedDateKey, transaction: tx) + } catch { + Logger.warn("Failed to serialize BackupCDNMetadata! \(error)") + } + } +} diff --git a/SignalServiceKit/Backups/BackupCDNMetadata.swift b/SignalServiceKit/Backups/BackupCDNMetadata.swift new file mode 100644 index 0000000000..7612b18333 --- /dev/null +++ b/SignalServiceKit/Backups/BackupCDNMetadata.swift @@ -0,0 +1,28 @@ +// +// Copyright 2025 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +/// Backup info provided by the server that is cached locally, so this can be discarded and +/// refreshed at any time. +/// +/// `cdn`, `backupDir`, and `mediaDir` should be static as long as backup state doesn't +/// significantly change (e.g. - changing subscription level, re-enabling backups after the grace period) +struct BackupCDNMetadata: Codable, Equatable { + /// The CDN type where the message backup is stored. Media may be stored elsewhere. + let cdn: Int32 + + /// The base directory of your backup data on the cdn. The message backup can befound in the + /// returned cdn at /backupDir/backupName and stored media can be found at /backupDir/mediaDir/mediaId + let backupDir: String + + /// The prefix path component for media objects on a cdn. Stored media for mediaId + /// can be found at /backupDir/mediaDir/mediaId. + let mediaDir: String + + /// The name of the most recent message backup on the cdn. The backup is at /backupDir/backupName + let backupName: String + + /// The amount of space used to store media + let usedSpace: Int64 +} diff --git a/SignalServiceKit/Backups/BackupCDNReadCredential.swift b/SignalServiceKit/Backups/BackupCDNReadCredential.swift new file mode 100644 index 0000000000..32d2ab980f --- /dev/null +++ b/SignalServiceKit/Backups/BackupCDNReadCredential.swift @@ -0,0 +1,23 @@ +// +// Copyright 2025 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +struct BackupCDNReadCredential: Codable { + static let lifetime: TimeInterval = .day + + let createDate: Date + let headers: HttpHeaders + + func isExpired(now: Date) -> Bool { + return now > createDate.addingTimeInterval(Self.lifetime) + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.headers = try container.decode(HttpHeaders.self, forKey: .headers) + + // createDate will default to current date, but can be overwritten during decodable initialization + self.createDate = try container.decodeIfPresent(Date.self, forKey: .createDate) ?? Date() + } +} diff --git a/SignalServiceKit/Backups/BackupRequestManager.swift b/SignalServiceKit/Backups/BackupRequestManager.swift index 4c53a25d55..860e4a316c 100644 --- a/SignalServiceKit/Backups/BackupRequestManager.swift +++ b/SignalServiceKit/Backups/BackupRequestManager.swift @@ -142,38 +142,8 @@ extension BackupRequestManager { public struct BackupRequestManagerImpl: BackupRequestManager { - private enum Constants { - static let keyValueStoreCollectionName = "BackupRequestManager" - - static let cdnNumberOfDaysFetchIntervalInSeconds: TimeInterval = .day - private static let keyValueStoreCdn2CredentialKey = "Cdn2Credential:" - private static let keyValueStoreCdn3CredentialKey = "Cdn3Credential:" - - static func cdnCredentialCacheKey(for cdn: Int32, auth: BackupServiceAuth) -> String { - switch cdn { - case 2: - return Constants.keyValueStoreCdn2CredentialKey + auth.type.rawValue - case 3: - return Constants.keyValueStoreCdn3CredentialKey + auth.type.rawValue - default: - owsFailDebug("Invalid CDN version requested") - return Constants.keyValueStoreCdn3CredentialKey + auth.type.rawValue - } - } - - static let backupInfoNumberOfDaysFetchIntervalInSeconds: TimeInterval = .day - private static let keyValueStoreBackupInfoKeyPrefix = "BackupInfo:" - private static let keyValueStoreLastBackupInfoFetchTimeKeyPrefix = "LastBackupInfoFetchTime:" - - static func backupInfoCacheInfo(for auth: BackupServiceAuth) -> (infoKey: String, lastfetchTimeKey: String) { - ( - keyValueStoreBackupInfoKeyPrefix + auth.type.rawValue, - keyValueStoreLastBackupInfoFetchTimeKeyPrefix + auth.type.rawValue - ) - } - } - private let backupAuthCredentialManager: BackupAuthCredentialManager + private let backupCDNCache: BackupCDNCache private let backupKeyMaterial: BackupKeyMaterial private let dateProvider: DateProvider private let db: any DB @@ -182,16 +152,18 @@ public struct BackupRequestManagerImpl: BackupRequestManager { init( backupAuthCredentialManager: BackupAuthCredentialManager, + backupCDNCache: BackupCDNCache, backupKeyMaterial: BackupKeyMaterial, dateProvider: @escaping DateProvider, db: any DB, networkManager: NetworkManager ) { self.backupAuthCredentialManager = backupAuthCredentialManager + self.backupCDNCache = backupCDNCache self.backupKeyMaterial = backupKeyMaterial self.dateProvider = dateProvider self.db = db - self.kvStore = KeyValueStore(collection: Constants.keyValueStoreCollectionName) + self.kvStore = KeyValueStore(collection: "BackupRequestManager") self.networkManager = networkManager } @@ -247,82 +219,32 @@ public struct BackupRequestManagerImpl: BackupRequestManager { // MARK: - Backup Info - /// Backup info provided by the server that is cached locally, so this can be discarded and - /// refreshed at any time. - /// - /// `cdn`, `backupDir`, and `mediaDir` should be static as long as backup state doesn't - /// significantly change (e.g. - changing subscription level, re-enabling backups after the grace period) - fileprivate struct BackupRemoteInfo: Codable, Equatable { - /// The CDN type where the message backup is stored. Media may be stored elsewhere. - public let cdn: Int32 - - /// The base directory of your backup data on the cdn. The message backup can befound in the - /// returned cdn at /backupDir/backupName and stored media can be found at /backupDir/mediaDir/mediaId - public let backupDir: String - - /// The prefix path component for media objects on a cdn. Stored media for mediaId - /// can be found at /backupDir/mediaDir/mediaId. - public let mediaDir: String - - /// The name of the most recent message backup on the cdn. The backup is at /backupDir/backupName - public let backupName: String - - /// The amount of space used to store media - let usedSpace: Int64 - } - - /// Fetch details about the current backup - private func fetchBackupInfo(auth: BackupServiceAuth) async throws -> BackupRemoteInfo { - let cacheInfo = Constants.backupInfoCacheInfo(for: auth) - let cachedBackupInfo = db.read { tx -> BackupRemoteInfo? in - let lastInfoFetchTime = kvStore.getDate( - cacheInfo.lastfetchTimeKey, - transaction: tx - ) ?? .distantPast - - // Refresh backup info after 24 hours - if abs(lastInfoFetchTime.timeIntervalSinceNow) < Constants.backupInfoNumberOfDaysFetchIntervalInSeconds { - do { - if let backupInfo: BackupRemoteInfo = try kvStore.getCodableValue( - forKey: cacheInfo.infoKey, - transaction: tx - ) { - return backupInfo - } - } catch { - // Failure to deserialize this object should be ok since it's simply - // a cache of the remote info and can be refetched. But still worth - // a log entry in case something results in repeated errors. - Logger.debug("Couldn't decode backup info, fetch remotely") - } - } - return nil + private func fetchBackupCDNMetadata(auth: BackupServiceAuth) async throws -> BackupCDNMetadata { + if let cachedCDNMetadata = db.read(block: { tx in + backupCDNCache.backupCDNMetadata( + authType: auth.type, + now: dateProvider(), + tx: tx + ) + }) { + return cachedCDNMetadata } - if let cachedBackupInfo { - return cachedBackupInfo - } - - let backupInfo: BackupRemoteInfo = try await executeBackupService( + let cdnMetadata: BackupCDNMetadata = try await executeBackupService( auth: auth, requestFactory: OWSRequestFactory.backupInfoRequest(auth:) ) - try await db.awaitableWrite { tx in - try kvStore.setCodable( - backupInfo, - key: cacheInfo.infoKey, - transaction: tx - ) - - kvStore.setDate( - dateProvider(), - key: cacheInfo.lastfetchTimeKey, - transaction: tx + await db.awaitableWrite { tx in + backupCDNCache.setBackupCDNMetadata( + cdnMetadata, + authType: auth.type, + dateProvider: dateProvider, + tx: tx ) } - return backupInfo + return cdnMetadata } // TODO: [Backups] Call this regularly, or move it somewhere it is called regularly @@ -340,45 +262,39 @@ public struct BackupRequestManagerImpl: BackupRequestManager { private func fetchCDNReadCredentials( cdn: Int32, auth: BackupServiceAuth - ) async throws -> CDNReadCredential { - let cacheKey = Constants.cdnCredentialCacheKey(for: cdn, auth: auth) - let result = db.read { tx -> CDNReadCredential? in - do { - if - let backupAuthCredential: CDNReadCredential = try kvStore.getCodableValue(forKey: cacheKey, transaction: tx), - backupAuthCredential.isExpired.negated - { - return backupAuthCredential - } - } catch { - // Failure to deserialize this object should be ok since the credential - // can be refetched. But still worth a log entry in case something - // results in repeated errors. - Logger.info("Couldn't decode backup info, fetch remotely") - } - return nil + ) async throws -> BackupCDNReadCredential { + if let cachedCDNReadCredential = db.read(block: { tx in + backupCDNCache.backupCDNReadCredential( + cdnNumber: cdn, + authType: auth.type, + now: dateProvider(), + tx: tx + ) + }) { + return cachedCDNReadCredential } - if let result { - return result - } - - let authCredential: CDNReadCredential = try await executeBackupService( + let cdnReadCredential: BackupCDNReadCredential = try await executeBackupService( auth: auth, - requestFactory: { OWSRequestFactory.fetchCDNCredentials(auth: $0, cdn: cdn) } + requestFactory: { OWSRequestFactory.fetchBackupCDNCredentials(auth: $0, cdn: cdn) } ) - try await db.awaitableWrite { tx in - try kvStore.setCodable(authCredential, key: cacheKey, transaction: tx) + await db.awaitableWrite { tx in + backupCDNCache.setBackupCDNReadCredential( + cdnReadCredential, + cdnNumber: cdn, + authType: auth.type, + tx: tx + ) } - return authCredential + return cdnReadCredential } public func fetchBackupRequestMetadata(auth: BackupServiceAuth) async throws -> BackupReadCredential { - let info = try await fetchBackupInfo(auth: auth) - let authCredential = try await fetchCDNReadCredentials(cdn: info.cdn, auth: auth) - return BackupReadCredential(credential: authCredential, info: info) + let metadata = try await fetchBackupCDNMetadata(auth: auth) + let authCredential = try await fetchCDNReadCredentials(cdn: metadata.cdn, auth: auth) + return BackupReadCredential(credential: authCredential, metadata: metadata) } public func fetchMediaTierCdnRequestMetadata( @@ -386,9 +302,9 @@ public struct BackupRequestManagerImpl: BackupRequestManager { auth: BackupServiceAuth ) async throws -> MediaTierReadCredential { owsAssertDebug(auth.type == .media) - let info = try await fetchBackupInfo(auth: auth) + let metadata = try await fetchBackupCDNMetadata(auth: auth) let authCredential = try await fetchCDNReadCredentials(cdn: cdn, auth: auth) - return MediaTierReadCredential(cdn: cdn, credential: authCredential, info: info) + return MediaTierReadCredential(cdn: cdn, credential: authCredential, metadata: metadata) } public func copyToMediaTier( @@ -501,43 +417,24 @@ public struct BackupRequestManagerImpl: BackupRequestManager { } } -private struct CDNReadCredential: Codable { - private static let cdnCredentialLifetimeInSeconds: TimeInterval = .day - - let createDate: Date - let headers: HttpHeaders - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - self.headers = try container.decode(HttpHeaders.self, forKey: .headers) - - // createDate will default to current date, but can be overwritten during decodable initialization - self.createDate = try container.decodeIfPresent(Date.self, forKey: .createDate) ?? Date() - } - - var isExpired: Bool { - return abs(createDate.timeIntervalSinceNow) >= CDNReadCredential.cdnCredentialLifetimeInSeconds - } -} - public struct MediaTierReadCredential { public let cdn: Int32 - private let credential: CDNReadCredential - private let info: BackupRequestManagerImpl.BackupRemoteInfo + private let credential: BackupCDNReadCredential + private let metadata: BackupCDNMetadata fileprivate init( cdn: Int32, - credential: CDNReadCredential, - info: BackupRequestManagerImpl.BackupRemoteInfo + credential: BackupCDNReadCredential, + metadata: BackupCDNMetadata, ) { self.cdn = cdn self.credential = credential - self.info = info + self.metadata = metadata } var isExpired: Bool { - return credential.isExpired + return credential.isExpired(now: Date()) } var cdnAuthHeaders: HttpHeaders { @@ -545,29 +442,29 @@ public struct MediaTierReadCredential { } func mediaTierUrlPrefix() -> String { - return "backups/\(info.backupDir)/\(info.mediaDir)" + return "backups/\(metadata.backupDir)/\(metadata.mediaDir)" } } public struct BackupReadCredential { - private let credential: CDNReadCredential - private let info: BackupRequestManagerImpl.BackupRemoteInfo + private let credential: BackupCDNReadCredential + private let metadata: BackupCDNMetadata fileprivate init( - credential: CDNReadCredential, - info: BackupRequestManagerImpl.BackupRemoteInfo + credential: BackupCDNReadCredential, + metadata: BackupCDNMetadata ) { self.credential = credential - self.info = info + self.metadata = metadata } var isExpired: Bool { - return credential.isExpired + return credential.isExpired(now: Date()) } var cdn: Int32 { - return info.cdn + return metadata.cdn } var cdnAuthHeaders: HttpHeaders { @@ -575,6 +472,6 @@ public struct BackupReadCredential { } func backupLocationUrl() -> String { - return "backups/\(info.backupDir)/\(info.backupName)" + return "backups/\(metadata.backupDir)/\(metadata.backupName)" } } diff --git a/SignalServiceKit/Environment/AppSetup.swift b/SignalServiceKit/Environment/AppSetup.swift index 46ec7488fc..4a295ef5c7 100644 --- a/SignalServiceKit/Environment/AppSetup.swift +++ b/SignalServiceKit/Environment/AppSetup.swift @@ -369,6 +369,7 @@ public class AppSetup { db: db, networkManager: networkManager ), + backupCDNCache: BackupCDNCache(), backupKeyMaterial: backupKeyMaterial, dateProvider: dateProvider, db: db, diff --git a/SignalServiceKit/Network/API/Requests/OWSRequestFactory+Backups.swift b/SignalServiceKit/Network/API/Requests/OWSRequestFactory+Backups.swift index 19866d8063..dcad3b5b16 100644 --- a/SignalServiceKit/Network/API/Requests/OWSRequestFactory+Backups.swift +++ b/SignalServiceKit/Network/API/Requests/OWSRequestFactory+Backups.swift @@ -60,7 +60,7 @@ extension OWSRequestFactory { return request } - public static func fetchCDNCredentials(auth: BackupServiceAuth, cdn: Int32) -> TSRequest { + public static func fetchBackupCDNCredentials(auth: BackupServiceAuth, cdn: Int32) -> TSRequest { var request = TSRequest( url: URL(string: "v1/archives/auth/read?cdn=\(cdn)")!, method: "GET", diff --git a/SignalServiceKit/ZkParams/AuthCredentialStore.swift b/SignalServiceKit/ZkParams/AuthCredentialStore.swift index 605819a493..634752f371 100644 --- a/SignalServiceKit/ZkParams/AuthCredentialStore.swift +++ b/SignalServiceKit/ZkParams/AuthCredentialStore.swift @@ -9,14 +9,14 @@ import LibSignalClient class AuthCredentialStore { private let callLinkAuthCredentialStore: KeyValueStore private let groupAuthCredentialStore: KeyValueStore - private let backupAuthCredentialStore: KeyValueStore - private let mediaAuthCredentialStore: KeyValueStore + private let backupMessagesAuthCredentialStore: KeyValueStore + private let backupMediaAuthCredentialStore: KeyValueStore init() { self.callLinkAuthCredentialStore = KeyValueStore(collection: "CallLinkAuthCredential") self.groupAuthCredentialStore = KeyValueStore(collection: "GroupsV2Impl.authCredentialStoreStore") - self.backupAuthCredentialStore = KeyValueStore(collection: "BackupAuthCredential") - self.mediaAuthCredentialStore = KeyValueStore(collection: "MediaAuthCredential") + self.backupMessagesAuthCredentialStore = KeyValueStore(collection: "BackupAuthCredential") + self.backupMediaAuthCredentialStore = KeyValueStore(collection: "MediaAuthCredential") } private static func callLinkAuthCredentialKey(for redemptionTime: UInt64) -> String { @@ -98,7 +98,11 @@ class AuthCredentialStore { redemptionTime: UInt64, tx: DBReadTransaction ) -> BackupAuthCredential? { - let store = credentialType == .messages ? backupAuthCredentialStore : mediaAuthCredentialStore + let store: KeyValueStore = switch credentialType { + case .media: backupMediaAuthCredentialStore + case .messages: backupMessagesAuthCredentialStore + } + do { return try store.getData( Self.backupAuthCredentialKey(for: redemptionTime), @@ -118,7 +122,11 @@ class AuthCredentialStore { redemptionTime: UInt64, tx: DBWriteTransaction ) { - let store = credentialType == .messages ? backupAuthCredentialStore : mediaAuthCredentialStore + let store: KeyValueStore = switch credentialType { + case .media: backupMediaAuthCredentialStore + case .messages: backupMessagesAuthCredentialStore + } + store.setData( credential.serialize(), key: Self.backupAuthCredentialKey(for: redemptionTime), @@ -127,7 +135,11 @@ class AuthCredentialStore { } func removeAllBackupAuthCredentials(ofType credentialType: BackupAuthCredentialType, tx: DBWriteTransaction) { - let store = credentialType == .messages ? backupAuthCredentialStore : mediaAuthCredentialStore + let store: KeyValueStore = switch credentialType { + case .media: backupMediaAuthCredentialStore + case .messages: backupMessagesAuthCredentialStore + } + store.removeAll(transaction: tx) }