// // KeyStore.swift // OTP // // Created by Shadowfacts on 8/23/21. // import Foundation import OTPKit import Security import Combine class KeyStore: ObservableObject { static let shared = try! KeyStore() private lazy var documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! private lazy var storeArchiveURL = documentsDirectory.appendingPathComponent("KeyStore").appendingPathExtension("plist") private let encoder = PropertyListEncoder() private let decoder = PropertyListDecoder() @Published private(set) var data: KeyData! { didSet { let data = try! encoder.encode(data) try! data.write(to: storeArchiveURL, options: .completeFileProtectionUntilFirstUserAuthentication) } } var entries: [KeyData.Entry] { data.entries } var folders: [KeyData.Folder] { data.folders } var sortedFolders: [KeyData.Folder] { data.folders.sorted(by: { (a, b) in a.name < b.name }) } private init() throws { if let data = try? Data(contentsOf: storeArchiveURL) { self.data = try decoder.decode(KeyData.self, from: data) } else { self.data = KeyData() } } func updateFromStore(_ newStore: KeyData, replaceExisting: Bool) { if replaceExisting { data = newStore } else { data.addOrUpdateEntries(newStore.entries) } } func addKey(_ key: TOTPKey) { data.addKey(key) } func updateKey(entryID id: UUID, newKey: TOTPKey) { data.updateKey(entryID: id, newKey: newKey) } func removeKey(entryID id: UUID) { data.removeKey(entryID: id) } func clearEntries() { data.clearEntries() } func addFolder() { data.addFolder() } func updateFolder(_ newFolder: KeyData.Folder) { data.updateFolder(newFolder) } func removeFolder(id: UUID) { data.removeFolder(id: id) } func moveEntryToFolder(entryID: UUID, folderID: UUID?) { data.moveEntryToFolder(entryID: entryID, folderID: folderID) } }