From 7b8eed29c33a5cae5d1cba4a46c6e094e415c716 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 17 Feb 2021 17:46:02 +0400 Subject: [PATCH] Support read-only databases --- Telegram/SiriIntents/IntentHandler.swift | 42 ++++++----- .../WidgetKitWidget/TodayViewController.swift | 20 +----- .../Postbox/Sources/AccountManager.swift | 10 +-- submodules/Postbox/Sources/Database.swift | 9 ++- submodules/Postbox/Sources/Postbox.swift | 16 +++-- .../Postbox/Sources/SqliteValueBox.swift | 69 ++++++++++++++----- .../StandaloneAccountTransaction.swift | 4 +- submodules/TelegramCore/Sources/Account.swift | 8 +-- .../TelegramCore/Sources/AccountManager.swift | 2 +- .../TelegramUI/Sources/AppDelegate.swift | 2 +- .../Sources/NotificationContentContext.swift | 2 +- .../Sources/ShareExtensionContext.swift | 2 +- .../TelegramUI/Sources/UpgradedAccounts.swift | 2 +- 13 files changed, 110 insertions(+), 78 deletions(-) diff --git a/Telegram/SiriIntents/IntentHandler.swift b/Telegram/SiriIntents/IntentHandler.swift index 4bae30cbad..3012c350c7 100644 --- a/Telegram/SiriIntents/IntentHandler.swift +++ b/Telegram/SiriIntents/IntentHandler.swift @@ -55,7 +55,25 @@ enum IntentHandlingError { @available(iOSApplicationExtension 10.0, iOS 10.0, *) @objc(IntentHandler) -class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartAudioCallIntentHandling, INSearchCallHistoryIntentHandling { +class IntentHandler: INExtension { + override public func handler(for intent: INIntent) -> Any { + if #available(iOSApplicationExtension 12.0, iOS 12.0, *) { + if intent is SelectAvatarFriendsIntent { + return AvatarsIntentHandler() + } else if intent is SelectFriendsIntent { + return FriendsIntentHandler() + } else { + return DefaultIntentHandler() + } + } else { + return DefaultIntentHandler() + } + } +} + +@available(iOSApplicationExtension 10.0, iOS 10.0, *) +@objc(IntentHandler) +class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartAudioCallIntentHandling, INSearchCallHistoryIntentHandling { private let accountPromise = Promise() private let allAccounts = Promise<[(AccountRecordId, PeerId, Bool)]>() @@ -106,7 +124,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" initializeAccountManagement() - let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true) + let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false) self.accountManager = accountManager let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId) @@ -195,20 +213,6 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag self.searchDisposable.dispose() } - override public func handler(for intent: INIntent) -> Any { - if #available(iOSApplicationExtension 12.0, iOS 12.0, *) { - if intent is SelectAvatarFriendsIntent { - return AvatarsIntentHandler() - } else if intent is SelectFriendsIntent { - return FriendsIntentHandler() - } else { - return self - } - } else { - return self - } - } - enum ResolveResult { case success(INPerson) case disambiguation([INPerson]) @@ -789,7 +793,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag var accountResults: [Signal, Error>] = [] for (accountId, accountPeerId, _) in accounts { - accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> INObjectSection in + accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> INObjectSection in var accountTitle: String = "" if let peer = transaction.getPeer(accountPeerId) as? TelegramUser { if let username = peer.username, !username.isEmpty { @@ -958,7 +962,7 @@ private final class WidgetIntentHandler { var accountResults: [Signal, Error>] = [] for (accountId, accountPeerId, _) in accounts { - accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> INObjectSection in + accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> INObjectSection in var accountTitle: String = "" if let peer = transaction.getPeer(accountPeerId) as? TelegramUser { if let username = peer.username, !username.isEmpty { @@ -1041,7 +1045,7 @@ private final class WidgetIntentHandler { if !isActive { continue } - accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> [Friend] in + accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> [Friend] in var peers: [Peer] = [] for id in getRecentPeers(transaction: transaction) { diff --git a/Telegram/WidgetKitWidget/TodayViewController.swift b/Telegram/WidgetKitWidget/TodayViewController.swift index 0870151f88..03be983151 100644 --- a/Telegram/WidgetKitWidget/TodayViewController.swift +++ b/Telegram/WidgetKitWidget/TodayViewController.swift @@ -59,22 +59,6 @@ private let accountAuxiliaryMethods = AccountAuxiliaryMethods(updatePeerChatInpu return nil }) -private struct ApplicationSettings { - let logging: LoggingSettings -} - -private func applicationSettings(accountManager: AccountManager) -> Signal { - return accountManager.transaction { transaction -> ApplicationSettings in - let loggingSettings: LoggingSettings - if let value = transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings { - loggingSettings = value - } else { - loggingSettings = LoggingSettings.defaultSettings - } - return ApplicationSettings(logging: loggingSettings) - } -} - private func rootPathForBasePath(_ appGroupPath: String) -> String { return appGroupPath + "/telegram-data" } @@ -155,7 +139,7 @@ struct Provider: IntentTimelineProvider { var friendsByAccount: [Signal<[ParsedPeer], NoError>] = [] for (accountId, items) in itemsByAccount { - friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> [ParsedPeer] in + friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> [ParsedPeer] in guard let state = transaction.getState() as? AuthorizedAccountState else { return [] } @@ -313,7 +297,7 @@ struct AvatarsProvider: IntentTimelineProvider { var friendsByAccount: [Signal<[ParsedPeer], NoError>] = [] for (accountId, items) in itemsByAccount { - friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, transaction: { postbox, transaction -> [ParsedPeer] in + friendsByAccount.append(accountTransaction(rootPath: rootPath, id: AccountRecordId(rawValue: accountId), encryptionParameters: encryptionParameters, isReadOnly: true, transaction: { postbox, transaction -> [ParsedPeer] in guard let state = transaction.getState() as? AuthorizedAccountState else { return [] } diff --git a/submodules/Postbox/Sources/AccountManager.swift b/submodules/Postbox/Sources/AccountManager.swift index 189078b39e..3da8424277 100644 --- a/submodules/Postbox/Sources/AccountManager.swift +++ b/submodules/Postbox/Sources/AccountManager.swift @@ -65,7 +65,7 @@ final class AccountManagerImpl { } } - fileprivate init?(queue: Queue, basePath: String, isTemporary: Bool, temporarySessionId: Int64) { + fileprivate init?(queue: Queue, basePath: String, isTemporary: Bool, isReadOnly: Bool, temporarySessionId: Int64) { let startTime = CFAbsoluteTimeGetCurrent() self.queue = queue @@ -73,11 +73,11 @@ final class AccountManagerImpl { self.atomicStatePath = "\(basePath)/atomic-state" self.temporarySessionId = temporarySessionId let _ = try? FileManager.default.createDirectory(atPath: basePath, withIntermediateDirectories: true, attributes: nil) - guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, encryptionParameters: nil, upgradeProgress: { _ in }) else { + guard let guardValueBox = SqliteValueBox(basePath: basePath + "/guard_db", queue: queue, isTemporary: isTemporary, isReadOnly: false, encryptionParameters: nil, upgradeProgress: { _ in }) else { return nil } self.guardValueBox = guardValueBox - guard let valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: nil, upgradeProgress: { _ in }) else { + guard let valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: nil, upgradeProgress: { _ in }) else { return nil } self.valueBox = valueBox @@ -468,7 +468,7 @@ public final class AccountManager { return AccountManagerImpl.getCurrentRecords(basePath: basePath) } - public init(basePath: String, isTemporary: Bool) { + public init(basePath: String, isTemporary: Bool, isReadOnly: Bool) { self.queue = sharedQueue self.basePath = basePath var temporarySessionId: Int64 = 0 @@ -476,7 +476,7 @@ public final class AccountManager { self.temporarySessionId = temporarySessionId let queue = self.queue self.impl = QueueLocalObject(queue: queue, generate: { - if let value = AccountManagerImpl(queue: queue, basePath: basePath, isTemporary: isTemporary, temporarySessionId: temporarySessionId) { + if let value = AccountManagerImpl(queue: queue, basePath: basePath, isTemporary: isTemporary, isReadOnly: isReadOnly, temporarySessionId: temporarySessionId) { return value } else { preconditionFailure() diff --git a/submodules/Postbox/Sources/Database.swift b/submodules/Postbox/Sources/Database.swift index d8fdff2ca8..82f25ccc43 100644 --- a/submodules/Postbox/Sources/Database.swift +++ b/submodules/Postbox/Sources/Database.swift @@ -28,11 +28,16 @@ import sqlcipher public final class Database { internal var handle: OpaquePointer? = nil - public init?(_ location: String) { + public init?(_ location: String, readOnly: Bool) { if location != ":memory:" { let _ = open(location + "-guard", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR) } - let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX + let flags: Int32 + if readOnly { + flags = SQLITE_OPEN_READONLY + } else { + flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX + } let res = sqlite3_open_v2(location, &self.handle, flags, nil) if res != SQLITE_OK { postboxLog("sqlite3_open_v2: \(res)") diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 0ef34eb3b5..23fa9e34ac 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -1125,7 +1125,7 @@ func debugRestoreState(basePath:String, name: String) { private let sharedQueue = Queue(name: "org.telegram.postbox.Postbox") -public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool) -> Signal { +public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, encryptionParameters: ValueBoxEncryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, isReadOnly: Bool) -> Signal { let queue = sharedQueue return Signal { subscriber in queue.async { @@ -1138,7 +1138,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, let startTime = CFAbsoluteTimeGetCurrent() - guard var valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in + guard var valueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in subscriber.putNext(.upgrading(progress)) }) else { subscriber.putNext(.error) @@ -1161,7 +1161,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, postboxLog("Version \(userVersion) is newer than supported") assertionFailure("Version \(userVersion) is newer than supported") valueBox.drop() - guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in + guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in subscriber.putNext(.upgrading(progress)) }) else { subscriber.putNext(.error) @@ -1185,7 +1185,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, valueBox.internalClose() let _ = try? FileManager.default.removeItem(atPath: basePath + "/db") let _ = try? FileManager.default.moveItem(atPath: updatedPath, toPath: basePath + "/db") - guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in + guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in subscriber.putNext(.upgrading(progress)) }) else { subscriber.putNext(.error) @@ -1199,7 +1199,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, assertionFailure("Couldn't find any upgrade for \(userVersion)") postboxLog("Couldn't find any upgrade for \(userVersion)") valueBox.drop() - guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, encryptionParameters: encryptionParameters, upgradeProgress: { progress in + guard let updatedValueBox = SqliteValueBox(basePath: basePath + "/db", queue: queue, isTemporary: isTemporary, isReadOnly: isReadOnly, encryptionParameters: encryptionParameters, upgradeProgress: { progress in subscriber.putNext(.upgrading(progress)) }) else { subscriber.putNext(.error) @@ -1538,10 +1538,12 @@ public final class Postbox { self.messageHistoryMetadataTable.setShouldReindexUnreadCountsState(value: reindexUnreadVersion) } //#if DEBUG - self.messageHistoryMetadataTable.setShouldReindexUnreadCounts(value: true) + if !isTemporary { + self.messageHistoryMetadataTable.setShouldReindexUnreadCounts(value: true) + } //#endif - if self.messageHistoryMetadataTable.shouldReindexUnreadCounts() { + if !isTemporary && self.messageHistoryMetadataTable.shouldReindexUnreadCounts() { self.groupMessageStatsTable.removeAll() let startTime = CFAbsoluteTimeGetCurrent() let (totalStates, summaries) = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self) diff --git a/submodules/Postbox/Sources/SqliteValueBox.swift b/submodules/Postbox/Sources/SqliteValueBox.swift index 4931942b83..177517a796 100644 --- a/submodules/Postbox/Sources/SqliteValueBox.swift +++ b/submodules/Postbox/Sources/SqliteValueBox.swift @@ -162,6 +162,7 @@ public final class SqliteValueBox: ValueBox { fileprivate let basePath: String private let isTemporary: Bool + private let isReadOnly: Bool private let inMemory: Bool private let encryptionParameters: ValueBoxEncryptionParameters? private let databasePath: String @@ -200,14 +201,15 @@ public final class SqliteValueBox: ValueBox { private let queue: Queue - public init?(basePath: String, queue: Queue, isTemporary: Bool, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void, inMemory: Bool = false) { + public init?(basePath: String, queue: Queue, isTemporary: Bool, isReadOnly: Bool, encryptionParameters: ValueBoxEncryptionParameters?, upgradeProgress: (Float) -> Void, inMemory: Bool = false) { self.basePath = basePath self.isTemporary = isTemporary + self.isReadOnly = isReadOnly self.inMemory = inMemory self.encryptionParameters = encryptionParameters self.databasePath = basePath + "/db_sqlite" self.queue = queue - if let database = self.openDatabase(encryptionParameters: encryptionParameters, isTemporary: isTemporary, upgradeProgress: upgradeProgress) { + if let database = self.openDatabase(encryptionParameters: encryptionParameters, isTemporary: isTemporary, isReadOnly: isReadOnly, upgradeProgress: upgradeProgress) { self.database = database } else { return nil @@ -224,7 +226,7 @@ public final class SqliteValueBox: ValueBox { self.database = nil } - private func openDatabase(encryptionParameters: ValueBoxEncryptionParameters?, isTemporary: Bool, upgradeProgress: (Float) -> Void) -> Database? { + private func openDatabase(encryptionParameters: ValueBoxEncryptionParameters?, isTemporary: Bool, isReadOnly: Bool, upgradeProgress: (Float) -> Void) -> Database? { precondition(self.queue.isCurrent()) checkpoints.set(nil) @@ -261,18 +263,23 @@ public final class SqliteValueBox: ValueBox { #endif var database: Database - if let result = Database(self.inMemory ? ":memory:" : path) { + if let result = Database(self.inMemory ? ":memory:" : path, readOnly: isReadOnly) { database = result } else { postboxLog("Couldn't open DB") + if isReadOnly { + postboxLog("Readonly, exiting") + return nil + } + let tempPath = basePath + "_test\(arc4random())" enum TempError: Error { case generic } do { try FileManager.default.createDirectory(atPath: tempPath, withIntermediateDirectories: true, attributes: nil) - let testDatabase = Database(tempPath + "/test_db")! + let testDatabase = Database(tempPath + "/test_db", readOnly: false)! var resultCode = testDatabase.execute("PRAGMA journal_mode=WAL") if !resultCode { throw TempError.generic @@ -309,7 +316,7 @@ public final class SqliteValueBox: ValueBox { assert(resultCode) if self.isEncrypted(database) { - if isTemporary { + if isTemporary || isReadOnly { return nil } postboxLog("Encryption key is invalid") @@ -317,7 +324,7 @@ public final class SqliteValueBox: ValueBox { for fileName in dabaseFileNames { let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)") } - database = Database(path)! + database = Database(path, readOnly: false)! resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32") assert(resultCode) @@ -329,11 +336,15 @@ public final class SqliteValueBox: ValueBox { } } else { postboxLog("Encryption key is required") + if isReadOnly { + return nil + } + assert(false) for fileName in dabaseFileNames { let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)") } - database = Database(path)! + database = Database(path, readOnly: false)! resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32") assert(resultCode) @@ -344,6 +355,10 @@ public final class SqliteValueBox: ValueBox { let hexKey = hexString(encryptionParameters.key.data + encryptionParameters.salt.data) if FileManager.default.fileExists(atPath: path) { + if isReadOnly { + return nil + } + postboxLog("Reencrypting database") database = self.reencryptInPlace(database: database, encryptionParameters: encryptionParameters) @@ -353,7 +368,7 @@ public final class SqliteValueBox: ValueBox { for fileName in dabaseFileNames { let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)") } - database = Database(path)! + database = Database(path, readOnly: false)! resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32") assert(resultCode) @@ -373,10 +388,14 @@ public final class SqliteValueBox: ValueBox { postboxLog("Encryption setup failed") //assert(false) + if isReadOnly { + return nil + } + for fileName in dabaseFileNames { let _ = try? FileManager.default.removeItem(atPath: basePath + "/\(fileName)") } - database = Database(path)! + database = Database(path, readOnly: false)! resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32") assert(resultCode) @@ -459,8 +478,13 @@ public final class SqliteValueBox: ValueBox { public func begin() { precondition(self.queue.isCurrent()) - let resultCode = self.database.execute("BEGIN IMMEDIATE") - assert(resultCode) + if self.isReadOnly { + let resultCode = self.database.execute("BEGIN DEFERRED") + assert(resultCode) + } else { + let resultCode = self.database.execute("BEGIN IMMEDIATE") + assert(resultCode) + } } public func commit() { @@ -477,8 +501,13 @@ public final class SqliteValueBox: ValueBox { private func beginInternal(database: Database) { precondition(self.queue.isCurrent()) - let resultCode = database.execute("BEGIN IMMEDIATE") - assert(resultCode) + if self.isReadOnly { + let resultCode = database.execute("BEGIN DEFERRED") + assert(resultCode) + } else { + let resultCode = database.execute("BEGIN IMMEDIATE") + assert(resultCode) + } } private func commitInternal(database: Database) { @@ -2073,6 +2102,10 @@ public final class SqliteValueBox: ValueBox { public func drop() { precondition(self.queue.isCurrent()) self.clearStatements() + + if self.isReadOnly { + preconditionFailure() + } self.lock.lock() self.database = nil @@ -2084,7 +2117,7 @@ public final class SqliteValueBox: ValueBox { let _ = try? FileManager.default.removeItem(atPath: self.basePath + "/\(fileName)") } - self.database = self.openDatabase(encryptionParameters: self.encryptionParameters, isTemporary: self.isTemporary, upgradeProgress: { _ in }) + self.database = self.openDatabase(encryptionParameters: self.encryptionParameters, isTemporary: self.isTemporary, isReadOnly: false, upgradeProgress: { _ in }) tables.removeAll() } @@ -2119,6 +2152,10 @@ public final class SqliteValueBox: ValueBox { } private func reencryptInPlace(database: Database, encryptionParameters: ValueBoxEncryptionParameters) -> Database { + if self.isReadOnly { + preconditionFailure() + } + let targetPath = self.basePath + "/db_export" let _ = try? FileManager.default.removeItem(atPath: targetPath) @@ -2130,7 +2167,7 @@ public final class SqliteValueBox: ValueBox { } let _ = try? FileManager.default.removeItem(atPath: targetPath) - let updatedDatabase = Database(self.databasePath)! + let updatedDatabase = Database(self.databasePath, readOnly: false)! var resultCode = updatedDatabase.execute("PRAGMA cipher_plaintext_header_size=32") assert(resultCode) diff --git a/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift b/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift index fcd6797d88..970aacfee2 100644 --- a/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift +++ b/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift @@ -73,9 +73,9 @@ public enum AccountTransactionError { case couldNotOpen } -public func accountTransaction(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, transaction: @escaping (Postbox, Transaction) -> T) -> Signal { +public func accountTransaction(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, isReadOnly: Bool, transaction: @escaping (Postbox, Transaction) -> T) -> Signal { let path = "\(rootPath)/\(accountRecordIdPathName(id))" - let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true) + let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: isReadOnly) return postbox |> castError(AccountTransactionError.self) |> mapToSignal { value -> Signal in diff --git a/submodules/TelegramCore/Sources/Account.swift b/submodules/TelegramCore/Sources/Account.swift index d32d372346..617b021a97 100644 --- a/submodules/TelegramCore/Sources/Account.swift +++ b/submodules/TelegramCore/Sources/Account.swift @@ -160,7 +160,7 @@ public enum AccountPreferenceEntriesResult { public func accountPreferenceEntries(rootPath: String, id: AccountRecordId, keys: Set, encryptionParameters: ValueBoxEncryptionParameters) -> Signal { let path = "\(rootPath)/\(accountRecordIdPathName(id))" - let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true) + let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true) return postbox |> mapToSignal { value -> Signal in switch value { @@ -189,7 +189,7 @@ public enum AccountNoticeEntriesResult { public func accountNoticeEntries(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal { let path = "\(rootPath)/\(accountRecordIdPathName(id))" - let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true) + let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true) return postbox |> mapToSignal { value -> Signal in switch value { @@ -212,7 +212,7 @@ public enum LegacyAccessChallengeDataResult { public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters) -> Signal { let path = "\(rootPath)/\(accountRecordIdPathName(id))" - let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true) + let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: true, isReadOnly: true) return postbox |> mapToSignal { value -> Signal in switch value { @@ -231,7 +231,7 @@ public func accountLegacyAccessChallengeData(rootPath: String, id: AccountRecord public func accountWithId(accountManager: AccountManager, networkArguments: NetworkInitializationArguments, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, backupData: AccountBackupData?, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal { let path = "\(rootPath)/\(accountRecordIdPathName(id))" - let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false) + let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false, isReadOnly: false) return postbox |> mapToSignal { result -> Signal in diff --git a/submodules/TelegramCore/Sources/AccountManager.swift b/submodules/TelegramCore/Sources/AccountManager.swift index 732fc76040..9db982445a 100644 --- a/submodules/TelegramCore/Sources/AccountManager.swift +++ b/submodules/TelegramCore/Sources/AccountManager.swift @@ -214,7 +214,7 @@ public func temporaryAccount(manager: AccountManager, rootPath: String, encrypti return manager.allocatedTemporaryAccountId() |> mapToSignal { id -> Signal in let path = "\(rootPath)/\(accountRecordIdPathName(id))" - return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false) + return openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters, timestampForAbsoluteTimeBasedOperations: Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970), isTemporary: false, isReadOnly: false) |> mapToSignal { result -> Signal in switch result { case .upgrading: diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 21dd3208b6..9adaad4deb 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -664,7 +664,7 @@ final class SharedApplicationContext { }) let accountManagerSignal = Signal { subscriber in - let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: false) + let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: false, isReadOnly: false) return (upgradedAccounts(accountManager: accountManager, rootPath: rootPath, encryptionParameters: encryptionParameters) |> deliverOnMainQueue).start(next: { progress in if self.dataImportSplash == nil { diff --git a/submodules/TelegramUI/Sources/NotificationContentContext.swift b/submodules/TelegramUI/Sources/NotificationContentContext.swift index 175a7574aa..d09f5968b0 100644 --- a/submodules/TelegramUI/Sources/NotificationContentContext.swift +++ b/submodules/TelegramUI/Sources/NotificationContentContext.swift @@ -113,7 +113,7 @@ public final class NotificationViewControllerImpl { if sharedAccountContext == nil { initializeAccountManagement() - let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true) + let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false) var initialPresentationDataAndSettings: InitialPresentationDataAndSettings? let semaphore = DispatchSemaphore(value: 0) diff --git a/submodules/TelegramUI/Sources/ShareExtensionContext.swift b/submodules/TelegramUI/Sources/ShareExtensionContext.swift index 573d81fb55..a92283e215 100644 --- a/submodules/TelegramUI/Sources/ShareExtensionContext.swift +++ b/submodules/TelegramUI/Sources/ShareExtensionContext.swift @@ -202,7 +202,7 @@ public class ShareRootControllerImpl { let internalContext: InternalContext - let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true) + let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false) if let globalInternalContext = globalInternalContext { internalContext = globalInternalContext diff --git a/submodules/TelegramUI/Sources/UpgradedAccounts.swift b/submodules/TelegramUI/Sources/UpgradedAccounts.swift index 4497306741..1198e7b2fb 100644 --- a/submodules/TelegramUI/Sources/UpgradedAccounts.swift +++ b/submodules/TelegramUI/Sources/UpgradedAccounts.swift @@ -290,7 +290,7 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String, e |> mapToSignal { globalSettings, ids -> Signal in var importSignal: Signal = .complete() for id in ids { - let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionParameters: encryptionParameters, transaction: { _, transaction -> Void in + let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionParameters: encryptionParameters, isReadOnly: false, transaction: { _, transaction -> Void in transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings settings.synchronizeContacts = globalSettings._legacySynchronizeDeviceContacts