From 217dd152d3e2b43988eed24a2c5c9bd087e20933 Mon Sep 17 00:00:00 2001 From: fmodf Date: Sat, 31 Aug 2024 12:59:18 +0200 Subject: [PATCH] wip --- .../AppData/Client/Client+MartinOMEMO.swift | 99 ++++++------------- .../AppData/Model/OMEMO.swift | 61 +++++++++++- 2 files changed, 89 insertions(+), 71 deletions(-) diff --git a/ConversationsClassic/AppData/Client/Client+MartinOMEMO.swift b/ConversationsClassic/AppData/Client/Client+MartinOMEMO.swift index 9e4e432..1b0a0e5 100644 --- a/ConversationsClassic/AppData/Client/Client+MartinOMEMO.swift +++ b/ConversationsClassic/AppData/Client/Client+MartinOMEMO.swift @@ -44,89 +44,49 @@ final class ClientMartinOMEMO { // MARK: - Session extension ClientMartinOMEMO: SignalSessionStoreProtocol { func sessionRecord(forAddress address: MartinOMEMO.SignalAddress) -> Data? { - do { - let data = try Database.shared.dbQueue.read { db in - try Row.fetchOne( - db, - sql: "SELECT key FROM omemo_sessions WHERE account = :account AND name = :name AND device_id = :deviceId", - arguments: ["account": credentials.bareJid, "name": address.name, "deviceId": address.deviceId] - ) - } - return data?["key"] - } catch { - logIt(.error, "Error fetching chats: \(error.localizedDescription)") + if let key = OMEMOSession.keyFor(account: credentials.bareJid, name: address.name, deviceId: address.deviceId) { + return Data(base64Encoded: key) + } else { return nil } } func allDevices(for name: String, activeAndTrusted: Bool) -> [Int32] { - do { - let sql = activeAndTrusted ? - """ - SELECT s.device_id - FROM omemo_sessions s - LEFT JOIN omemo_identities i - ON s.account = i.account - AND s.name = i.name - AND s.device_id = i.device_id - WHERE s.account = :account - AND s.name = :name - AND ((i.status >= 0 AND i.status % 2 = 0) OR i.status IS NULL) - """ - : - "SELECT device_id FROM omemo_sessions WHERE account = :account AND name = :name" - let data = try Database.shared.dbQueue.read { db in - try Row.fetchAll( - db, - sql: sql, - arguments: ["account": credentials.bareJid, "name": name] - ) - } - return data.map { $0["device_id"] } - } catch { - logIt(.error, "Error fetching chats: \(error.localizedDescription)") - return [] - } + activeAndTrusted ? + OMEMOSession.trustedDevicesIdsFor(account: credentials.bareJid, name: name) : + OMEMOSession.devicesIdsFor(account: credentials.bareJid, name: name) } func storeSessionRecord(_ data: Data, forAddress: MartinOMEMO.SignalAddress) -> Bool { do { try Database.shared.dbQueue.write { db in - try db.execute( - sql: "INSERT INTO omemo_sessions (account, name, device_id, key) VALUES (:account, :name, :deviceId, :key)", - arguments: ["account": credentials.bareJid, "name": forAddress.name, "deviceId": forAddress.deviceId, "key": data] + try OMEMOSession( + account: credentials.bareJid, + name: forAddress.name, + deviceId: Int(forAddress.deviceId), + key: data.base64EncodedString() ) + .insert(db) } return true } catch { - logIt(.error, "Error fetching chats: \(error.localizedDescription)") + logIt(.error, "Error storing session info: \(error.localizedDescription)") return false } } func containsSessionRecord(forAddress: MartinOMEMO.SignalAddress) -> Bool { - do { - let rec = try Database.shared.dbQueue.read { db in - try Row.fetchOne( - db, - sql: "SELECT key FROM omemo_sessions WHERE account = :account AND name = :name AND device_id = :deviceId", - arguments: ["account": credentials.bareJid, "name": forAddress.name, "deviceId": forAddress.deviceId] - ) - } - return rec != nil - } catch { - logIt(.error, "Error fetching chats: \(error.localizedDescription)") - return false - } + OMEMOSession.keyFor(account: credentials.bareJid, name: forAddress.name, deviceId: forAddress.deviceId) != nil } func deleteSessionRecord(forAddress: MartinOMEMO.SignalAddress) -> Bool { do { - try Database.shared.dbQueue.write { db in - try db.execute( - sql: "DELETE FROM omemo_sessions WHERE account = :account AND name = :name AND device_id = :deviceId", - arguments: ["account": credentials.bareJid, "name": forAddress.name, "deviceId": forAddress.deviceId] - ) + _ = try Database.shared.dbQueue.write { db in + try OMEMOSession + .filter(Column("account") == credentials.bareJid) + .filter(Column("name") == forAddress.name) + .filter(Column("deviceId") == forAddress.deviceId) + .deleteAll(db) } return true } catch { @@ -137,11 +97,11 @@ extension ClientMartinOMEMO: SignalSessionStoreProtocol { func deleteAllSessions(for name: String) -> Bool { do { - try Database.shared.dbQueue.write { db in - try db.execute( - sql: "DELETE FROM omemo_sessions WHERE account = :account AND name = :name", - arguments: ["account": credentials.bareJid, "name": name] - ) + _ = try Database.shared.dbQueue.write { db in + try OMEMOSession + .filter(Column("account") == credentials.bareJid) + .filter(Column("name") == name) + .deleteAll(db) } return true } catch { @@ -152,11 +112,10 @@ extension ClientMartinOMEMO: SignalSessionStoreProtocol { func sessionsWipe() { do { - try Database.shared.dbQueue.write { db in - try db.execute( - sql: "DELETE FROM omemo_sessions WHERE account = :account", - arguments: ["account": credentials.bareJid] - ) + _ = try Database.shared.dbQueue.write { db in + try OMEMOSession + .filter(Column("account") == credentials.bareJid) + .deleteAll(db) } } catch { logIt(.error, "Error fetching chats: \(error.localizedDescription)") diff --git a/ConversationsClassic/AppData/Model/OMEMO.swift b/ConversationsClassic/AppData/Model/OMEMO.swift index ff2be0d..8276f66 100644 --- a/ConversationsClassic/AppData/Model/OMEMO.swift +++ b/ConversationsClassic/AppData/Model/OMEMO.swift @@ -3,13 +3,72 @@ import GRDB import Martin // MARK: - Session -struct OMEMOSession: Codable & Equatable, DatabaseValueConvertible { +struct OMEMOSession: DBStorable { static let databaseTableName = "omemo_sessions" let account: String let name: String let deviceId: Int let key: String + + var id: String { + "\(account)_\(name)_\(deviceId)" + } +} + +extension OMEMOSession { + static func keyFor(account: String, name: String, deviceId: Int32) -> String? { + do { + return try Database.shared.dbQueue.read { db in + try OMEMOSession + .filter(Column("account") == account) + .filter(Column("name") == name) + .filter(Column("deviceId") == deviceId) + .fetchOne(db) + }?.key + } catch { + return nil + } + } + + static func devicesIdsFor(account: String, name: String) -> [Int32] { + do { + return try Database.shared.dbQueue.read { db in + try OMEMOSession + .filter(Column("account") == account) + .filter(Column("name") == name) + .fetchAll(db) + .map(\.deviceId) + }.map { Int32($0) } + } catch { + return [] + } + } + + static func trustedDevicesIdsFor(account: String, name: String) -> [Int32] { + do { + let sql = + """ + SELECT s.device_id + FROM omemo_sessions s + LEFT JOIN omemo_identities i + ON s.account = i.account + AND s.name = i.name + AND s.device_id = i.device_id + WHERE s.account = :account + AND s.name = :name + AND ((i.status >= 0 AND i.status % 2 = 0) OR i.status IS NULL) + """ + + let arguments: StatementArguments = ["account": account, "name": name] + + return try Database.shared.dbQueue.read { db in + try Int32.fetchAll(db, sql: sql, arguments: arguments) + } + } catch { + return [] + } + } } // MARK: - Identity