mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
core: support down migrations to allow reverting to the previous version (#2072)
* core: support down migrations to allow reverting to the previous version * update schema * update simplexmq * rename errors * remove unused functions * migration UI, test migration * update migration UI * return current migrations in CRVersionInfo * update simplexmq * test down migrations * cleanup ios * show migrations in log
This commit is contained in:
committed by
GitHub
parent
f5c11b8faf
commit
c96ba30018
@@ -17,7 +17,7 @@ public func getChatCtrl(_ useKey: String? = nil) -> chat_ctrl {
|
||||
fatalError("chat controller not initialized")
|
||||
}
|
||||
|
||||
public func chatMigrateInit(_ useKey: String? = nil) -> (Bool, DBMigrationResult) {
|
||||
public func chatMigrateInit(_ useKey: String? = nil, confirmMigrations: MigrationConfirmation? = nil) -> (Bool, DBMigrationResult) {
|
||||
if let res = migrationResult { return res }
|
||||
let dbPath = getAppDatabasePath().path
|
||||
var dbKey = ""
|
||||
@@ -34,12 +34,14 @@ public func chatMigrateInit(_ useKey: String? = nil) -> (Bool, DBMigrationResult
|
||||
dbKey = key
|
||||
}
|
||||
}
|
||||
logger.debug("chatMigrateInit DB path: \(dbPath)")
|
||||
let confirm = confirmMigrations ?? defaultMigrationConfirmation()
|
||||
logger.debug("chatMigrateInit DB path: \(dbPath), confirm: \(confirm.rawValue)")
|
||||
// logger.debug("chatMigrateInit DB key: \(dbKey)")
|
||||
var cPath = dbPath.cString(using: .utf8)!
|
||||
var cKey = dbKey.cString(using: .utf8)!
|
||||
var cConfirm = confirm.rawValue.cString(using: .utf8)!
|
||||
// the last parameter of chat_migrate_init is used to return the pointer to chat controller
|
||||
let cjson = chat_migrate_init(&cPath, &cKey, &chatController)!
|
||||
let cjson = chat_migrate_init(&cPath, &cKey, &cConfirm, &chatController)!
|
||||
let dbRes = dbMigrationResult(fromCString(cjson))
|
||||
let encrypted = dbKey != ""
|
||||
let keychainErr = dbRes == .ok && useKeychain && encrypted && !setDatabaseKey(dbKey)
|
||||
@@ -207,12 +209,40 @@ func chatErrorString(_ err: ChatError) -> String {
|
||||
|
||||
public enum DBMigrationResult: Decodable, Equatable {
|
||||
case ok
|
||||
case invalidConfirmation
|
||||
case errorNotADatabase(dbFile: String)
|
||||
case error(dbFile: String, migrationError: String)
|
||||
case errorMigration(dbFile: String, migrationError: MigrationError)
|
||||
case errorSQL(dbFile: String, migrationSQLError: String)
|
||||
case errorKeychain
|
||||
case unknown(json: String)
|
||||
}
|
||||
|
||||
public enum MigrationConfirmation: String {
|
||||
case yesUp
|
||||
case yesUpDown
|
||||
case error
|
||||
}
|
||||
|
||||
public func defaultMigrationConfirmation() -> MigrationConfirmation {
|
||||
confirmDBUpgradesGroupDefault.get() ? .error : .yesUp
|
||||
}
|
||||
|
||||
public enum MigrationError: Decodable, Equatable {
|
||||
case upgrade(upMigrations: [UpMigration])
|
||||
case downgrade(downMigrations: [String])
|
||||
case migrationError(mtrError: MTRError)
|
||||
}
|
||||
|
||||
public struct UpMigration: Decodable, Equatable {
|
||||
public var upName: String
|
||||
// public var withDown: Bool
|
||||
}
|
||||
|
||||
public enum MTRError: Decodable, Equatable {
|
||||
case noDown(dbMigrations: [String])
|
||||
case different(appMigration: String, dbMigration: String)
|
||||
}
|
||||
|
||||
func dbMigrationResult(_ s: String) -> DBMigrationResult {
|
||||
let d = s.data(using: .utf8)!
|
||||
// TODO is there a way to do it without copying the data? e.g:
|
||||
|
||||
@@ -459,7 +459,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
case ntfMessages(user_: User?, connEntity: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo])
|
||||
case newContactConnection(user: User, connection: PendingContactConnection)
|
||||
case contactConnectionDeleted(user: User, connection: PendingContactConnection)
|
||||
case versionInfo(versionInfo: CoreVersionInfo)
|
||||
case versionInfo(versionInfo: CoreVersionInfo, chatMigrations: [UpMigration], agentMigrations: [UpMigration])
|
||||
case cmdOk(user: User?)
|
||||
case chatCmdError(user_: User?, chatError: ChatError)
|
||||
case chatError(user_: User?, chatError: ChatError)
|
||||
@@ -674,7 +674,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))")
|
||||
case let .newContactConnection(u, connection): return withUser(u, String(describing: connection))
|
||||
case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection))
|
||||
case let .versionInfo(versionInfo): return String(describing: versionInfo)
|
||||
case let .versionInfo(versionInfo, chatMigrations, agentMigrations): return "\(String(describing: versionInfo))\n\nchat migrations: \(chatMigrations.map(\.upName))\n\nagent migrations: \(agentMigrations.map(\.upName))"
|
||||
case .cmdOk: return noDetails
|
||||
case let .chatCmdError(u, chatError): return withUser(u, String(describing: chatError))
|
||||
case let .chatError(u, chatError): return withUser(u, String(describing: chatError))
|
||||
|
||||
@@ -29,6 +29,7 @@ let GROUP_DEFAULT_NETWORK_TCP_KEEP_CNT = "networkTCPKeepCnt"
|
||||
let GROUP_DEFAULT_INCOGNITO = "incognito"
|
||||
let GROUP_DEFAULT_STORE_DB_PASSPHRASE = "storeDBPassphrase"
|
||||
let GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE = "initialRandomDBPassphrase"
|
||||
public let GROUP_DEFAULT_CONFIRM_DB_UPGRADES = "confirmDBUpgrades"
|
||||
public let GROUP_DEFAULT_CALL_KIT_ENABLED = "callKitEnabled"
|
||||
|
||||
public let APP_GROUP_NAME = "group.chat.simplex.app"
|
||||
@@ -52,6 +53,7 @@ public func registerGroupDefaults() {
|
||||
GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE: false,
|
||||
GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES: true,
|
||||
GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE: false,
|
||||
GROUP_DEFAULT_CONFIRM_DB_UPGRADES: false,
|
||||
GROUP_DEFAULT_CALL_KIT_ENABLED: true
|
||||
])
|
||||
}
|
||||
@@ -121,6 +123,8 @@ public let storeDBPassphraseGroupDefault = BoolDefault(defaults: groupDefaults,
|
||||
|
||||
public let initialRandomDBPassphraseGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE)
|
||||
|
||||
public let confirmDBUpgradesGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_CONFIRM_DB_UPGRADES)
|
||||
|
||||
public let callKitEnabledGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_CALL_KIT_ENABLED)
|
||||
|
||||
public class DateDefault {
|
||||
|
||||
@@ -127,12 +127,16 @@ public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificati
|
||||
switch dbStatus {
|
||||
case .errorNotADatabase:
|
||||
title = NSLocalizedString("Encrypted message: no passphrase", comment: "notification")
|
||||
case .error:
|
||||
case .errorMigration:
|
||||
title = NSLocalizedString("Encrypted message: database migration error", comment: "notification")
|
||||
case .errorSQL:
|
||||
title = NSLocalizedString("Encrypted message: database error", comment: "notification")
|
||||
case .errorKeychain:
|
||||
title = NSLocalizedString("Encrypted message: keychain error", comment: "notification")
|
||||
case .unknown:
|
||||
title = NSLocalizedString("Encrypted message: unexpected error", comment: "notification")
|
||||
case .invalidConfirmation:
|
||||
title = NSLocalizedString("Encrypted message or another event", comment: "notification")
|
||||
case .ok:
|
||||
title = NSLocalizedString("Encrypted message or another event", comment: "notification")
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ extern void hs_init(int argc, char **argv[]);
|
||||
typedef void* chat_ctrl;
|
||||
|
||||
// the last parameter is used to return the pointer to chat controller
|
||||
extern char *chat_migrate_init(char *path, char *key, chat_ctrl *ctrl);
|
||||
extern char *chat_migrate_init(char *path, char *key, char *confirm, chat_ctrl *ctrl);
|
||||
extern char *chat_send_cmd(chat_ctrl ctl, char *cmd);
|
||||
extern char *chat_recv_msg(chat_ctrl ctl);
|
||||
extern char *chat_recv_msg_wait(chat_ctrl ctl, int wait);
|
||||
|
||||
Reference in New Issue
Block a user