diff --git a/Sources/Secretive/App.swift b/Sources/Secretive/App.swift index d40521e..6df7033 100644 --- a/Sources/Secretive/App.swift +++ b/Sources/Secretive/App.swift @@ -16,6 +16,7 @@ struct Secretive: App { }() private let agentStatusChecker = AgentStatusChecker() private let justUpdatedChecker = JustUpdatedChecker() + private let settingsStore = SettingsStore() @AppStorage("defaultsHasRunSetup") var hasRunSetup = false @State private var showingSetup = false @@ -27,6 +28,7 @@ struct Secretive: App { .environmentObject(storeList) .environmentObject(Updater(checkOnLaunch: hasRunSetup)) .environmentObject(agentStatusChecker) + .environmentObject(settingsStore) .onAppear { if !hasRunSetup { showingSetup = true diff --git a/Sources/Secretive/Helpers/SettingsHelper.swift b/Sources/Secretive/Helpers/SettingsHelper.swift index 8b6ce64..7c3d0da 100644 --- a/Sources/Secretive/Helpers/SettingsHelper.swift +++ b/Sources/Secretive/Helpers/SettingsHelper.swift @@ -8,53 +8,56 @@ import Foundation -class SettingsStore { - static let service = "com.maxgoedjen.Secretive" +class SettingsStore: ObservableObject { + let service = "com.maxgoedjen.Secretive" } extension SettingsStore { - static func set(key: String, value: String) -> Bool { - let valueData = value.data(using: String.Encoding.utf8)! - - if let keyVal = get(key: key) { - if keyVal == value { - return true + subscript(key: String) -> String? { + set(value) { + guard let valueData = value?.data(using: String.Encoding.utf8)! else { + return } - let updateQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, - kSecAttrServer as String: service] - let attributes: [String: Any] = [kSecAttrAccount as String: key, - kSecValueData as String: valueData] - // FIXME: Make this non-blocking as described here: https://developer.apple.com/documentation/security/1393617-secitemupdate - let status = SecItemUpdate(updateQuery as CFDictionary, attributes as CFDictionary) - guard status == errSecSuccess else { - print("Couldn't update item in keychain. " + status.description) - return false - } - } else { - let addquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, - kSecAttrAccount as String: key, - kSecAttrServer as String: service, - kSecValueData as String: valueData] - // FIXME: Make this non-blocking as described here: https://developer.apple.com/documentation/security/1401659-secitemadd - let status = SecItemAdd(addquery as CFDictionary, nil) - guard status == errSecSuccess else { - print("Couldn't add item to keychain. " + status.description) - return false + if let keyVal = self[key] { + if keyVal == value { + return + } + + let updateQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, + kSecAttrServer as String: service] + let attributes: [String: Any] = [kSecAttrAccount as String: key, + kSecValueData as String: valueData] + // FIXME: Make this non-blocking as described here: https://developer.apple.com/documentation/security/1393617-secitemupdate + let status = SecItemUpdate(updateQuery as CFDictionary, attributes as CFDictionary) + guard status == errSecSuccess else { + print("Couldn't update item in keychain. " + status.description) + return + } + } else { + let addquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, + kSecAttrAccount as String: key, + kSecAttrServer as String: service, + kSecValueData as String: valueData] + // FIXME: Make this non-blocking as described here: https://developer.apple.com/documentation/security/1401659-secitemadd + let status = SecItemAdd(addquery as CFDictionary, nil) + guard status == errSecSuccess else { + print("Couldn't add item to keychain. " + status.description) + return + } } } - return true - } - - static func get(key: String) -> String? { - let getquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, - kSecAttrAccount as String: key, - kSecAttrServer as String: service, - kSecMatchLimit as String: kSecMatchLimitOne, - kSecReturnData as String: true] - var item: CFTypeRef? - let status = SecItemCopyMatching(getquery as CFDictionary, &item) - return status == errSecSuccess ? String(decoding: item as! Data, as: UTF8.self) : nil + get { + let getquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, + kSecAttrAccount as String: key, + kSecAttrServer as String: service, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecReturnData as String: true] + var item: CFTypeRef? + let status = SecItemCopyMatching(getquery as CFDictionary, &item) + + return status == errSecSuccess ? String(decoding: item as! Data, as: UTF8.self) : nil + } } }