mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
a51bbd3abc
* Initial work on presenting alert on error
* Move Account-related error handling up the hierarchy
* Handle errors on logout
* Fix for temporary debugging
* Clean up WriteFreelyModel’s published vars
* Add error handling to top-level content view
* Set current error on API call failures
* Set current error on API call handlers
* Move User Defaults errors to ErrorConstants file
* Add default values for some error strings
* Handle purging post errors
* Add FIXME to track silent failure on fetching collections
As collections are fetched and added to the `list` property in the CollectionListModel’s initializer, it’s tricky to throw an error here: we call it as a property initializer in CollectionListView, which cannot throw.
Consider refactoring this logic such that we’re using, for example, a @FetchRequest in CollectionListView instead.
* Handle errors in (most) shared code
Two outliers to come back to are:
- the LocalStoreManager, where we can’t set a current error in the WriteFreelyModel in methods that can’t throw
- the CollectionListModel, where the initializer can’t throw because we use it as a property initializer in CollectionListView
* Add error handling to Mac app
* Revert "Add error handling to Mac app"
This reverts commit b1a8b8b29c
.
56 lines
2.2 KiB
Swift
56 lines
2.2 KiB
Swift
import Foundation
|
|
|
|
extension WriteFreelyModel {
|
|
|
|
func saveTokenToKeychain(_ token: String, username: String?, server: String) throws {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecValueData as String: token.data(using: .utf8)!,
|
|
kSecAttrAccount as String: username ?? "anonymous",
|
|
kSecAttrService as String: server
|
|
]
|
|
let status = SecItemAdd(query as CFDictionary, nil)
|
|
guard status == errSecDuplicateItem || status == errSecSuccess else {
|
|
throw KeychainError.couldNotStoreAccessToken
|
|
}
|
|
}
|
|
|
|
func purgeTokenFromKeychain(username: String?, server: String) throws {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrAccount as String: username ?? "anonymous",
|
|
kSecAttrService as String: server
|
|
]
|
|
let status = SecItemDelete(query as CFDictionary)
|
|
guard status == errSecSuccess || status == errSecItemNotFound else {
|
|
throw KeychainError.couldNotPurgeAccessToken
|
|
}
|
|
}
|
|
|
|
func fetchTokenFromKeychain(username: String?, server: String) throws -> String? {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrAccount as String: username ?? "anonymous",
|
|
kSecAttrService as String: server,
|
|
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
kSecReturnAttributes as String: true,
|
|
kSecReturnData as String: true
|
|
]
|
|
var secItem: CFTypeRef?
|
|
let status = SecItemCopyMatching(query as CFDictionary, &secItem)
|
|
guard status != errSecItemNotFound else {
|
|
throw KeychainError.couldNotFetchAccessToken
|
|
}
|
|
guard status == errSecSuccess else {
|
|
throw KeychainError.couldNotFetchAccessToken
|
|
}
|
|
guard let existingSecItem = secItem as? [String: Any],
|
|
let tokenData = existingSecItem[kSecValueData as String] as? Data,
|
|
let token = String(data: tokenData, encoding: .utf8) else {
|
|
throw KeychainError.couldNotFetchAccessToken
|
|
}
|
|
return token
|
|
}
|
|
|
|
}
|