Created
October 16, 2024 12:27
-
-
Save dena-sohrabi/56f1c7cdf5cb6dde6f6ac38349de4be3 to your computer and use it in GitHub Desktop.
Encrypted Database (GRDB + SQLCipher)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import GRDB | |
// MARK: - DB main class | |
public final class AppDatabase: Sendable { | |
public let dbWriter: any DatabaseWriter | |
public init(_ dbWriter: any GRDB.DatabaseWriter) throws { | |
self.dbWriter = dbWriter | |
try migrator.migrate(dbWriter) | |
} | |
} | |
// MARK: - Migrations | |
public extension AppDatabase { | |
var migrator: DatabaseMigrator { | |
var migrator = DatabaseMigrator() | |
#if DEBUG | |
// MAKE SURE: it does not enable in production | |
// Speed up development by nuking the database when migrations change | |
// Refrence <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/migrations#The-eraseDatabaseOnSchemaChange-Option> | |
migrator.eraseDatabaseOnSchemaChange = true | |
#endif | |
migrator.registerMigration("v0") { _ in | |
// Create tables here | |
} | |
// Migrations for future application versions will be inserted here: | |
// migrator.registerMigration(...) { db in | |
// ... | |
// } | |
return migrator | |
} | |
} | |
// MARK: - Database Configuration | |
public extension AppDatabase { | |
/// - parameter base: A base configuration. | |
static func makeConfiguration(_ base: Configuration = Configuration()) -> Configuration { | |
var config = base | |
if let token = Auth.shared.getToken() { | |
config.prepareDatabase { db in | |
try db.usePassphrase(token) | |
} | |
} else { | |
config.prepareDatabase { db in | |
// Add a fake passphrase if the token does not exist; then, when it exists, use the token / change the password | |
try db.usePassphrase("123") | |
} | |
} | |
return config | |
} | |
static func authenticated() throws { | |
if let token = Auth.shared.getToken() { | |
try AppDatabase.shared.dbWriter.barrierWriteWithoutTransaction { db in | |
try db.changePassphrase(token) | |
// maybe dbPool.invalidateReadOnlyConnections()??? | |
} | |
} else { | |
Log.shared.warning("AppDatabase.authenticated called without token") | |
} | |
} | |
} | |
// MARK: - Database Access: Reads | |
public extension AppDatabase { | |
/// Provides a read-only access to the database. | |
var reader: any GRDB.DatabaseReader { | |
dbWriter | |
} | |
} | |
// MARK: - The database for the application | |
public extension AppDatabase { | |
/// The database for the application | |
static let shared = makeShared() | |
private static func makeShared() -> AppDatabase { | |
do { | |
// Create the "Application Support/Database" directory if needed | |
let fileManager = FileManager.default | |
let appSupportURL = try fileManager.url( | |
for: .applicationSupportDirectory, in: .userDomainMask, | |
appropriateFor: nil, create: true | |
) | |
let directoryURL = appSupportURL.appendingPathComponent("Database", isDirectory: true) | |
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true) | |
// Open or create the database | |
let databaseURL = directoryURL.appendingPathComponent("db.sqlite") | |
let config = AppDatabase.makeConfiguration() | |
let dbPool = try DatabasePool(path: databaseURL.path, configuration: config) | |
print("DB created in \(databaseURL) ") | |
// Create the AppDatabase | |
let appDatabase = try AppDatabase(dbPool) | |
return appDatabase | |
} catch { | |
fatalError("Unresolved error \(error)") | |
} | |
} | |
/// Creates an empty database for SwiftUI previews | |
static func empty() -> AppDatabase { | |
// Connect to an in-memory database | |
// Refrence https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/databaseconnections | |
let dbQueue = try! DatabaseQueue(configuration: AppDatabase.makeConfiguration()) | |
return try! AppDatabase(dbQueue) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment