another.im-ios/ConversationsClassic/AppData/Model/OMEMO.swift
2024-08-31 15:52:44 +02:00

219 lines
6.1 KiB
Swift

import Foundation
import GRDB
import Martin
// MARK: - Session
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 []
}
}
static func wipe(account: String) {
do {
_ = try Database.shared.dbQueue.write { db in
try OMEMOSession
.filter(Column("account") == account)
.deleteAll(db)
}
} catch {
logIt(.error, "Failed to wipe OMEMO session: \(error)")
}
}
}
// MARK: - Identity
struct OMEMOIdentity: DBStorable {
static let databaseTableName = "omemo_identities"
let account: String
let name: String
let deviceId: Int
let fingerprint: String
let key: Data
let own: Bool
let status: Int
var id: String {
"\(account)_\(name)_\(deviceId)"
}
}
extension OMEMOIdentity {
static func wipe(account: String) {
do {
_ = try Database.shared.dbQueue.write { db in
try OMEMOIdentity
.filter(Column("account") == account)
.deleteAll(db)
}
} catch {
logIt(.error, "Failed to wipe OMEMO identity: \(error)")
}
}
static func getFor(account: String, name: String, deviceId: Int32) -> OMEMOIdentity? {
do {
return try Database.shared.dbQueue.read { db in
try OMEMOIdentity
.filter(Column("account") == account)
.filter(Column("name") == name)
.filter(Column("deviceId") == deviceId)
.fetchOne(db)
}
} catch {
return nil
}
}
static func existsFor(account: String, name: String, fingerprint: String) -> Bool {
do {
return try Database.shared.dbQueue.read { db in
try OMEMOIdentity
.filter(Column("account") == account)
.filter(Column("name") == name)
.filter(Column("fingerprint") == fingerprint)
.fetchOne(db) != nil
}
} catch {
return false
}
}
func updateStatus(_ status: Int) -> Bool {
do {
_ = try Database.shared.dbQueue.write { db in
try OMEMOIdentity
.filter(Column("account") == account)
.filter(Column("name") == name)
.filter(Column("deviceId") == deviceId)
.updateAll(db, Column("status").set(to: status))
}
return true
} catch {
logIt(.error, "Failed to update OMEMO identity status: \(error)")
return false
}
}
static func getAllFor(account: String, name: String) -> [OMEMOIdentity] {
do {
return try Database.shared.dbQueue.read { db in
try OMEMOIdentity
.filter(Column("account") == account)
.filter(Column("name") == name)
.fetchAll(db)
}
} catch {
return []
}
}
}
// MARK: - PreKey
struct OMEMOPreKey: DBStorable {
static let databaseTableName = "omemo_pre_keys"
let account: String
let id: Int
let key: Data
}
extension OMEMOPreKey {
static func wipe(account: String) {
do {
_ = try Database.shared.dbQueue.write { db in
try OMEMOPreKey
.filter(Column("account") == account)
.deleteAll(db)
}
} catch {
logIt(.error, "Failed to wipe OMEMO pre key: \(error)")
}
}
}
// MARK: - SignedPreKey
struct OMEMOSignedPreKey: DBStorable {
static let databaseTableName = "omemo_signed_pre_keys"
let account: String
let id: Int
let key: Data
}
extension OMEMOSignedPreKey {
static func wipe(account: String) {
do {
_ = try Database.shared.dbQueue.write { db in
try OMEMOSignedPreKey
.filter(Column("account") == account)
.deleteAll(db)
}
} catch {
logIt(.error, "Failed to wipe OMEMO signed pre key: \(error)")
}
}
}