mirror of https://github.com/oxen-io/session-ios
Removed YapDatabase and the migrations
Removed the YapDatabase CocoaPod Removed logic to migrate from YapDatabase to GRDB Removed the logic to check for legacy config messages during onboarding Added a database error for when a migration is no longer supportedpull/883/head
parent
0e952b40bb
commit
50bc2f9a5c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,85 +0,0 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import SessionUtilitiesKit
|
||||
|
||||
public final class ConfigurationMessage: ControlMessage {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case displayName
|
||||
case profilePictureUrl
|
||||
case profileKey
|
||||
}
|
||||
|
||||
public var displayName: String?
|
||||
public var profilePictureUrl: String?
|
||||
public var profileKey: Data?
|
||||
|
||||
public override var isSelfSendValid: Bool { true }
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
public init(
|
||||
displayName: String?,
|
||||
profilePictureUrl: String?,
|
||||
profileKey: Data?
|
||||
) {
|
||||
super.init()
|
||||
|
||||
self.displayName = displayName
|
||||
self.profilePictureUrl = profilePictureUrl
|
||||
self.profileKey = profileKey
|
||||
}
|
||||
|
||||
// MARK: - Codable
|
||||
|
||||
required init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
|
||||
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
displayName = try? container.decode(String.self, forKey: .displayName)
|
||||
profilePictureUrl = try? container.decode(String.self, forKey: .profilePictureUrl)
|
||||
profileKey = try? container.decode(Data.self, forKey: .profileKey)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
|
||||
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encodeIfPresent(displayName, forKey: .displayName)
|
||||
try container.encodeIfPresent(profilePictureUrl, forKey: .profilePictureUrl)
|
||||
try container.encodeIfPresent(profileKey, forKey: .profileKey)
|
||||
}
|
||||
|
||||
// MARK: - Proto Conversion
|
||||
|
||||
public override class func fromProto(_ proto: SNProtoContent, sender: String) -> ConfigurationMessage? {
|
||||
guard let configurationProto = proto.configurationMessage else { return nil }
|
||||
|
||||
let displayName = configurationProto.displayName
|
||||
let profilePictureUrl = configurationProto.profilePicture
|
||||
let profileKey = configurationProto.profileKey
|
||||
|
||||
return ConfigurationMessage(
|
||||
displayName: displayName,
|
||||
profilePictureUrl: profilePictureUrl,
|
||||
profileKey: profileKey
|
||||
)
|
||||
}
|
||||
|
||||
public override func toProto(_ db: Database) -> SNProtoContent? { return nil }
|
||||
|
||||
// MARK: - Description
|
||||
|
||||
public var description: String {
|
||||
"""
|
||||
LegacyConfigurationMessage(
|
||||
displayName: \(displayName ?? "null"),
|
||||
profilePictureUrl: \(profilePictureUrl ?? "null"),
|
||||
profileKey: \(profileKey?.toHexString() ?? "null")
|
||||
)
|
||||
"""
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
public final class LegacyConfigurationMessage: ControlMessage {
|
||||
public override var isSelfSendValid: Bool { true }
|
||||
|
||||
public override class func fromProto(_ proto: SNProtoContent, sender: String) -> LegacyConfigurationMessage? {
|
||||
guard let configurationProto = proto.configurationMessage else { return nil }
|
||||
|
||||
return LegacyConfigurationMessage()
|
||||
}
|
||||
|
||||
public override func toProto(_ db: Database) -> SNProtoContent? { return nil }
|
||||
public var description: String { "LegacyConfigurationMessage()" }
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum SSKLegacy {
|
||||
// MARK: - Collections and Keys
|
||||
|
||||
internal static let swarmCollectionPrefix = "LokiSwarmCollection-"
|
||||
internal static let lastSnodePoolRefreshDateKey = "lastSnodePoolRefreshDate"
|
||||
internal static let snodePoolCollection = "LokiSnodePoolCollection"
|
||||
internal static let onionRequestPathCollection = "LokiOnionRequestPathCollection"
|
||||
internal static let lastSnodePoolRefreshDateCollection = "LokiLastSnodePoolRefreshDateCollection"
|
||||
internal static let lastMessageHashCollection = "LokiLastMessageHashCollection"
|
||||
internal static let receivedMessagesCollection = "LokiReceivedMessagesCollection"
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
public typealias LegacyOnionRequestAPIPath = [Snode]
|
||||
|
||||
@objc(Snode)
|
||||
public final class Snode: NSObject, NSCoding {
|
||||
public let address: String
|
||||
public let port: UInt16
|
||||
public let publicKeySet: KeySet
|
||||
|
||||
// MARK: - Nested Types
|
||||
|
||||
public struct KeySet {
|
||||
public let ed25519Key: String
|
||||
public let x25519Key: String
|
||||
}
|
||||
|
||||
// MARK: - NSCoding
|
||||
|
||||
public init?(coder: NSCoder) {
|
||||
address = coder.decodeObject(forKey: "address") as! String
|
||||
port = coder.decodeObject(forKey: "port") as! UInt16
|
||||
|
||||
guard
|
||||
let idKey = coder.decodeObject(forKey: "idKey") as? String,
|
||||
let encryptionKey = coder.decodeObject(forKey: "encryptionKey") as? String
|
||||
else { return nil }
|
||||
|
||||
publicKeySet = KeySet(ed25519Key: idKey, x25519Key: encryptionKey)
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
fatalError("encode(with:) should never be called for legacy types")
|
||||
}
|
||||
|
||||
// Note: The 'isEqual' and 'hash' overrides are both needed to ensure the migration
|
||||
// doesn't try to insert duplicate SNode entries into the new database (which would
|
||||
// result in unique key constraint violations)
|
||||
override public func isEqual(_ other: Any?) -> Bool {
|
||||
guard let other = other as? Snode else { return false }
|
||||
|
||||
return address == other.address && port == other.port
|
||||
}
|
||||
|
||||
override public var hash: Int {
|
||||
return address.hashValue ^ port.hashValue
|
||||
}
|
||||
}
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import YapDatabase
|
||||
|
||||
public enum SUKLegacy {
|
||||
// MARK: - YapDatabase
|
||||
|
||||
private static let keychainService = "TSKeyChainService"
|
||||
private static let keychainDBCipherKeySpec = "OWSDatabaseCipherKeySpec"
|
||||
private static let sqlCipherKeySpecLength = 48
|
||||
|
||||
private static var database: Atomic<YapDatabase>?
|
||||
|
||||
// MARK: - Collections and Keys
|
||||
|
||||
internal static let userAccountRegisteredNumberKey = "TSStorageRegisteredNumberKey"
|
||||
internal static let userAccountCollection = "TSStorageUserAccountCollection"
|
||||
|
||||
internal static let identityKeyStoreSeedKey = "LKLokiSeed"
|
||||
internal static let identityKeyStoreEd25519SecretKey = "LKED25519SecretKey"
|
||||
internal static let identityKeyStoreEd25519PublicKey = "LKED25519PublicKey"
|
||||
internal static let identityKeyStoreIdentityKey = "TSStorageManagerIdentityKeyStoreIdentityKey"
|
||||
internal static let identityKeyStoreCollection = "TSStorageManagerIdentityKeyStoreCollection"
|
||||
|
||||
// MARK: - Database Functions
|
||||
|
||||
public static var legacyDatabaseFilepath: String {
|
||||
let sharedDirUrl: URL = URL(fileURLWithPath: OWSFileSystem.appSharedDataDirectoryPath())
|
||||
|
||||
return sharedDirUrl
|
||||
.appendingPathComponent("database")
|
||||
.appendingPathComponent("Signal.sqlite")
|
||||
.path
|
||||
}
|
||||
|
||||
private static let legacyDatabaseDeserializer: YapDatabaseDeserializer = {
|
||||
return { (collection: String, key: String, data: Data) -> Any in
|
||||
/// **Note:** The old `init(forReadingWith:)` method has been deprecated with `init(forReadingFrom:)`
|
||||
/// and Apple changed the default of `requiresSecureCoding` to be true, this results in some of the types from failing
|
||||
/// to decode, as a result we need to set it to false here
|
||||
let unarchiver: NSKeyedUnarchiver? = try? NSKeyedUnarchiver(forReadingFrom: data)
|
||||
unarchiver?.requiresSecureCoding = false
|
||||
|
||||
guard !data.isEmpty, let result = unarchiver?.decodeObject(forKey: "root") else {
|
||||
return UnknownDBObject()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}()
|
||||
|
||||
public static var hasLegacyDatabaseFile: Bool {
|
||||
return FileManager.default.fileExists(atPath: legacyDatabaseFilepath)
|
||||
}
|
||||
|
||||
@discardableResult public static func loadDatabaseIfNeeded() -> Bool {
|
||||
guard SUKLegacy.database == nil else { return true }
|
||||
|
||||
/// Ensure the databaseKeySpec exists
|
||||
var maybeKeyData: Data? = try? SSKDefaultKeychainStorage.shared.data(
|
||||
forService: keychainService,
|
||||
key: keychainDBCipherKeySpec
|
||||
)
|
||||
defer { if maybeKeyData != nil { maybeKeyData!.resetBytes(in: 0..<maybeKeyData!.count) } }
|
||||
|
||||
guard maybeKeyData != nil, maybeKeyData?.count == sqlCipherKeySpecLength else { return false }
|
||||
|
||||
// Setup the database options
|
||||
let options: YapDatabaseOptions = YapDatabaseOptions()
|
||||
options.corruptAction = .fail
|
||||
options.enableMultiProcessSupport = true
|
||||
options.cipherUnencryptedHeaderLength = kSqliteHeaderLength // Needed for iOS to support SQLite writes
|
||||
options.legacyCipherCompatibilityVersion = 3 // Old DB was SQLCipher V3
|
||||
options.cipherKeySpecBlock = {
|
||||
/// To avoid holding the keySpec in memory too long we load it as needed, since we have already confirmed
|
||||
/// it's existence we can force-try here (the database will crash if it's invalid anyway)
|
||||
var keySpec: Data = try! SSKDefaultKeychainStorage.shared.data(
|
||||
forService: keychainService,
|
||||
key: keychainDBCipherKeySpec
|
||||
)
|
||||
defer { keySpec.resetBytes(in: 0..<keySpec.count) }
|
||||
|
||||
return keySpec
|
||||
}
|
||||
|
||||
let maybeDatabase: YapDatabase? = YapDatabase(
|
||||
path: legacyDatabaseFilepath,
|
||||
serializer: nil,
|
||||
deserializer: legacyDatabaseDeserializer,
|
||||
options: options
|
||||
)
|
||||
|
||||
guard let database: YapDatabase = maybeDatabase else { return false }
|
||||
|
||||
// Store the database instance atomically
|
||||
SUKLegacy.database = Atomic(database)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public static func newDatabaseConnection() -> YapDatabaseConnection? {
|
||||
SUKLegacy.loadDatabaseIfNeeded()
|
||||
|
||||
return self.database?.wrappedValue.newConnection()
|
||||
}
|
||||
|
||||
public static func clearLegacyDatabaseInstance() {
|
||||
self.database = nil
|
||||
}
|
||||
|
||||
public static func deleteLegacyDatabaseFilesAndKey() throws {
|
||||
OWSFileSystem.deleteFile(legacyDatabaseFilepath)
|
||||
OWSFileSystem.deleteFile("\(legacyDatabaseFilepath)-shm")
|
||||
OWSFileSystem.deleteFile("\(legacyDatabaseFilepath)-wal")
|
||||
try SSKDefaultKeychainStorage.shared.remove(service: keychainService, key: keychainDBCipherKeySpec)
|
||||
}
|
||||
|
||||
// MARK: - UnknownDBObject
|
||||
|
||||
@objc(LegacyUnknownDBObject)
|
||||
public class UnknownDBObject: NSObject, NSCoding {
|
||||
override public init() {}
|
||||
public required init?(coder: NSCoder) {}
|
||||
public func encode(with coder: NSCoder) { fatalError("Shouldn't be encoding this type") }
|
||||
}
|
||||
|
||||
// MARK: - LagacyKeyPair
|
||||
|
||||
@objc(LegacyKeyPair)
|
||||
public class KeyPair: NSObject, NSCoding {
|
||||
private static let keyLength: Int = 32
|
||||
private static let publicKeyKey: String = "TSECKeyPairPublicKey"
|
||||
private static let privateKeyKey: String = "TSECKeyPairPrivateKey"
|
||||
|
||||
public let publicKey: Data
|
||||
public let privateKey: Data
|
||||
|
||||
public init(
|
||||
publicKeyData: Data,
|
||||
privateKeyData: Data
|
||||
) {
|
||||
publicKey = publicKeyData
|
||||
privateKey = privateKeyData
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
var pubKeyLength: Int = 0
|
||||
var privKeyLength: Int = 0
|
||||
|
||||
guard
|
||||
let pubKeyBytes: UnsafePointer<UInt8> = coder.decodeBytes(forKey: KeyPair.publicKeyKey, returnedLength: &pubKeyLength),
|
||||
let privateKeyBytes: UnsafePointer<UInt8> = coder.decodeBytes(forKey: KeyPair.privateKeyKey, returnedLength: &privKeyLength),
|
||||
pubKeyLength == KeyPair.keyLength,
|
||||
privKeyLength == KeyPair.keyLength
|
||||
else {
|
||||
// Fail if the keys aren't the correct length
|
||||
return nil
|
||||
}
|
||||
|
||||
publicKey = Data(bytes: pubKeyBytes, count: pubKeyLength)
|
||||
privateKey = Data(bytes: privateKeyBytes, count: privKeyLength)
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) { fatalError("Shouldn't be encoding this type") }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue