mirror of
https://github.com/bitwarden/ios.git
synced 2025-12-11 13:54:06 -06:00
146 lines
5.2 KiB
Swift
146 lines
5.2 KiB
Swift
import BitwardenKit
|
|
import CoreData
|
|
|
|
// MARK: - AuthenticatorStoreType
|
|
|
|
/// A type of data store.
|
|
///
|
|
public enum AuthenticatorBridgeStoreType {
|
|
/// The data store is stored only in memory and isn't persisted to the device. This is used for
|
|
/// unit testing.
|
|
case memory
|
|
|
|
/// The data store is persisted to the device.
|
|
case persisted
|
|
}
|
|
|
|
// MARK: - AuthenticatorDataStore
|
|
|
|
/// The CoreData model name used within `AuthenticatorBridgeDataStore`.
|
|
private let authenticatorBridgeModelName = "Bitwarden-Authenticator"
|
|
|
|
/// A data store that manages persisting data across app launches in Core Data.
|
|
///
|
|
public class AuthenticatorBridgeDataStore {
|
|
// MARK: Type Properties
|
|
|
|
/// The managed object model representing the entities in the database schema. CoreData throws
|
|
/// warnings if this is instantiated multiple times (e.g. in tests), which is fixed by making
|
|
/// it static.
|
|
private static let managedObjectModel: NSManagedObjectModel = {
|
|
#if SWIFT_PACKAGE
|
|
let bundle = Bundle.module
|
|
#else
|
|
let bundle = Bundle(for: AuthenticatorBridgeDataStore.self)
|
|
#endif
|
|
|
|
let modelURL = bundle.url(forResource: authenticatorBridgeModelName, withExtension: "momd")!
|
|
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL)!
|
|
return managedObjectModel
|
|
}()
|
|
|
|
// MARK: Properties
|
|
|
|
/// A managed object context which executes on a background queue.
|
|
private(set) lazy var backgroundContext: NSManagedObjectContext = {
|
|
let context = persistentContainer.newBackgroundContext()
|
|
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
|
return context
|
|
}()
|
|
|
|
/// The service used by the application to report non-fatal errors.
|
|
let errorReporter: ErrorReporter
|
|
|
|
/// The Core Data persistent container.
|
|
public let persistentContainer: NSPersistentContainer
|
|
|
|
// MARK: Initialization
|
|
|
|
/// Initialize a `AuthenticatorBridgeDataStore`.
|
|
///
|
|
/// - Parameters:
|
|
/// - errorReporter: The service used by the application to report non-fatal errors.
|
|
/// - groupIdentifier: The app group identifier for the shared resource.
|
|
/// - storeType: The type of store to create.
|
|
///
|
|
public init(
|
|
errorReporter: ErrorReporter,
|
|
groupIdentifier: String,
|
|
storeType: AuthenticatorBridgeStoreType = .persisted
|
|
) {
|
|
self.errorReporter = errorReporter
|
|
|
|
persistentContainer = NSPersistentContainer(
|
|
name: authenticatorBridgeModelName,
|
|
managedObjectModel: Self.managedObjectModel
|
|
)
|
|
let storeDescription: NSPersistentStoreDescription
|
|
switch storeType {
|
|
case .memory:
|
|
storeDescription = NSPersistentStoreDescription(url: URL(fileURLWithPath: "/dev/null"))
|
|
case .persisted:
|
|
let storeURL = FileManager.default
|
|
.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)!
|
|
.appendingPathComponent("\(authenticatorBridgeModelName).sqlite")
|
|
storeDescription = NSPersistentStoreDescription(url: storeURL)
|
|
}
|
|
persistentContainer.persistentStoreDescriptions = [storeDescription]
|
|
|
|
persistentContainer.loadPersistentStores { _, error in
|
|
if let error {
|
|
errorReporter.log(error: error)
|
|
}
|
|
}
|
|
|
|
persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
|
|
}
|
|
|
|
// MARK: Methods
|
|
|
|
/// Executes a batch delete request and merges the changes into the background and view contexts.
|
|
///
|
|
/// - Parameter request: The batch delete request to perform.
|
|
///
|
|
public func executeBatchDelete(_ request: NSBatchDeleteRequest) async throws {
|
|
try await backgroundContext.perform {
|
|
try self.backgroundContext.executeAndMergeChanges(
|
|
batchDeleteRequest: request,
|
|
additionalContexts: [self.persistentContainer.viewContext]
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Executes a batch insert request and merges the changes into the background and view contexts.
|
|
///
|
|
/// - Parameter request: The batch insert request to perform.
|
|
///
|
|
public func executeBatchInsert(_ request: NSBatchInsertRequest) async throws {
|
|
try await backgroundContext.perform {
|
|
try self.backgroundContext.executeAndMergeChanges(
|
|
batchInsertRequest: request,
|
|
additionalContexts: [self.persistentContainer.viewContext]
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Executes a batch delete and batch insert request and merges the changes into the background
|
|
/// and view contexts.
|
|
///
|
|
/// - Parameters:
|
|
/// - deleteRequest: The batch delete request to perform.
|
|
/// - insertRequest: The batch insert request to perform.
|
|
///
|
|
public func executeBatchReplace(
|
|
deleteRequest: NSBatchDeleteRequest,
|
|
insertRequest: NSBatchInsertRequest
|
|
) async throws {
|
|
try await backgroundContext.perform {
|
|
try self.backgroundContext.executeAndMergeChanges(
|
|
batchDeleteRequest: deleteRequest,
|
|
batchInsertRequest: insertRequest,
|
|
additionalContexts: [self.persistentContainer.viewContext]
|
|
)
|
|
}
|
|
}
|
|
}
|