If a single sync failure is encountered a sheet is presented which allows the user to update their credentials. If multiple sync failures are encountered an alert is shown listing the accounts which encountered errors. On iOS, this alert can take the user into Settings, but there is no obvious way to programatically pesent macOS preferences.
279 lines
7.3 KiB
Swift
279 lines
7.3 KiB
Swift
//
|
|
// EditAccountCredentialsModel.swift
|
|
// Multiplatform macOS
|
|
//
|
|
// Created by Stuart Breckenridge on 14/7/20.
|
|
// Copyright © 2020 Ranchero Software. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Account
|
|
import Secrets
|
|
import RSCore
|
|
|
|
class EditAccountCredentialsModel: ObservableObject {
|
|
|
|
@Published var userName: String = ""
|
|
@Published var password: String = ""
|
|
@Published var apiUrl: String = ""
|
|
@Published var accountIsUpdatingCredentials: Bool = false
|
|
@Published var accountCredentialsWereUpdated: Bool = false
|
|
@Published var error: AccountUpdateErrors = .none {
|
|
didSet {
|
|
if error == .none {
|
|
showError = false
|
|
} else {
|
|
showError = true
|
|
}
|
|
}
|
|
}
|
|
@Published var showError: Bool = false
|
|
|
|
func updateAccountCredentials(_ account: Account) {
|
|
switch account.type {
|
|
case .onMyMac:
|
|
return
|
|
case .feedbin:
|
|
updateFeedbin(account)
|
|
case .cloudKit:
|
|
return
|
|
case .feedWrangler:
|
|
updateFeedWrangler(account)
|
|
case .feedly:
|
|
updateFeedly(account)
|
|
case .freshRSS:
|
|
updateFreshRSS(account)
|
|
case .newsBlur:
|
|
updateNewsblur(account)
|
|
}
|
|
}
|
|
|
|
func retrieveCredentials(_ account: Account) {
|
|
switch account.type {
|
|
case .feedbin:
|
|
let credentials = try? account.retrieveCredentials(type: .basic)
|
|
userName = credentials?.username ?? ""
|
|
case .feedWrangler:
|
|
let credentials = try? account.retrieveCredentials(type: .feedWranglerBasic)
|
|
userName = credentials?.username ?? ""
|
|
case .feedly:
|
|
return
|
|
case .freshRSS:
|
|
let credentials = try? account.retrieveCredentials(type: .readerBasic)
|
|
userName = credentials?.username ?? ""
|
|
case .newsBlur:
|
|
let credentials = try? account.retrieveCredentials(type: .newsBlurBasic)
|
|
userName = credentials?.username ?? ""
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// MARK:- Update API
|
|
extension EditAccountCredentialsModel {
|
|
|
|
func updateFeedbin(_ account: Account) {
|
|
accountIsUpdatingCredentials = true
|
|
let credentials = Credentials(type: .basic, username: userName, secret: password)
|
|
|
|
Account.validateCredentials(type: .feedbin, credentials: credentials) { [weak self] result in
|
|
|
|
guard let self = self else { return }
|
|
|
|
self.accountIsUpdatingCredentials = false
|
|
|
|
switch result {
|
|
case .success(let validatedCredentials):
|
|
|
|
guard let validatedCredentials = validatedCredentials else {
|
|
self.error = .invalidUsernamePassword
|
|
return
|
|
}
|
|
|
|
do {
|
|
try account.removeCredentials(type: .basic)
|
|
try account.storeCredentials(validatedCredentials)
|
|
self.accountCredentialsWereUpdated = true
|
|
account.refreshAll(completion: { result in
|
|
switch result {
|
|
case .success:
|
|
break
|
|
case .failure(let error):
|
|
self.error = .other(error: error)
|
|
}
|
|
})
|
|
|
|
} catch {
|
|
self.error = .keyChainError
|
|
}
|
|
|
|
case .failure:
|
|
self.error = .networkError
|
|
}
|
|
}
|
|
}
|
|
|
|
func updateFeedWrangler(_ account: Account) {
|
|
accountIsUpdatingCredentials = true
|
|
let credentials = Credentials(type: .feedWranglerBasic, username: userName, secret: password)
|
|
|
|
Account.validateCredentials(type: .feedWrangler, credentials: credentials) { [weak self] result in
|
|
|
|
guard let self = self else { return }
|
|
|
|
self.accountIsUpdatingCredentials = false
|
|
|
|
switch result {
|
|
case .success(let validatedCredentials):
|
|
|
|
guard let validatedCredentials = validatedCredentials else {
|
|
self.error = .invalidUsernamePassword
|
|
return
|
|
}
|
|
|
|
do {
|
|
try account.removeCredentials(type: .feedWranglerBasic)
|
|
try account.removeCredentials(type: .feedWranglerToken)
|
|
try account.storeCredentials(credentials)
|
|
try account.storeCredentials(validatedCredentials)
|
|
self.accountCredentialsWereUpdated = true
|
|
account.refreshAll(completion: { result in
|
|
switch result {
|
|
case .success:
|
|
break
|
|
case .failure(let error):
|
|
self.error = .other(error: error)
|
|
}
|
|
})
|
|
|
|
} catch {
|
|
self.error = .keyChainError
|
|
}
|
|
|
|
case .failure:
|
|
self.error = .networkError
|
|
}
|
|
}
|
|
}
|
|
|
|
func updateFeedly(_ account: Account) {
|
|
accountIsUpdatingCredentials = true
|
|
let updateAccount = OAuthAccountAuthorizationOperation(accountType: .feedly)
|
|
updateAccount.delegate = self
|
|
#if os(macOS)
|
|
updateAccount.presentationAnchor = NSApplication.shared.windows.last
|
|
#endif
|
|
MainThreadOperationQueue.shared.add(updateAccount)
|
|
}
|
|
|
|
func updateFreshRSS(_ account: Account) {
|
|
accountIsUpdatingCredentials = true
|
|
let credentials = Credentials(type: .readerBasic, username: userName, secret: password)
|
|
|
|
Account.validateCredentials(type: .freshRSS, credentials: credentials) { [weak self] result in
|
|
|
|
guard let self = self else { return }
|
|
|
|
self.accountIsUpdatingCredentials = false
|
|
|
|
switch result {
|
|
case .success(let validatedCredentials):
|
|
|
|
guard let validatedCredentials = validatedCredentials else {
|
|
self.error = .invalidUsernamePassword
|
|
return
|
|
}
|
|
|
|
do {
|
|
try account.removeCredentials(type: .readerBasic)
|
|
try account.removeCredentials(type: .readerAPIKey)
|
|
try account.storeCredentials(credentials)
|
|
try account.storeCredentials(validatedCredentials)
|
|
self.accountCredentialsWereUpdated = true
|
|
account.refreshAll(completion: { result in
|
|
switch result {
|
|
case .success:
|
|
break
|
|
case .failure(let error):
|
|
self.error = .other(error: error)
|
|
}
|
|
})
|
|
|
|
} catch {
|
|
self.error = .keyChainError
|
|
}
|
|
|
|
case .failure:
|
|
self.error = .networkError
|
|
}
|
|
}
|
|
}
|
|
|
|
func updateNewsblur(_ account: Account) {
|
|
accountIsUpdatingCredentials = true
|
|
let credentials = Credentials(type: .newsBlurBasic, username: userName, secret: password)
|
|
|
|
Account.validateCredentials(type: .newsBlur, credentials: credentials) { [weak self] result in
|
|
|
|
guard let self = self else { return }
|
|
|
|
self.accountIsUpdatingCredentials = false
|
|
|
|
switch result {
|
|
case .success(let validatedCredentials):
|
|
|
|
guard let validatedCredentials = validatedCredentials else {
|
|
self.error = .invalidUsernamePassword
|
|
return
|
|
}
|
|
|
|
do {
|
|
try account.removeCredentials(type: .newsBlurBasic)
|
|
try account.removeCredentials(type: .newsBlurSessionId)
|
|
try account.storeCredentials(credentials)
|
|
try account.storeCredentials(validatedCredentials)
|
|
self.accountCredentialsWereUpdated = true
|
|
account.refreshAll(completion: { result in
|
|
switch result {
|
|
case .success:
|
|
break
|
|
case .failure(let error):
|
|
self.error = .other(error: error)
|
|
}
|
|
})
|
|
|
|
} catch {
|
|
self.error = .keyChainError
|
|
}
|
|
|
|
case .failure:
|
|
self.error = .networkError
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// MARK:- OAuthAccountAuthorizationOperationDelegate
|
|
extension EditAccountCredentialsModel: OAuthAccountAuthorizationOperationDelegate {
|
|
func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didCreate account: Account) {
|
|
accountIsUpdatingCredentials = false
|
|
accountCredentialsWereUpdated = true
|
|
account.refreshAll { [weak self] result in
|
|
switch result {
|
|
case .success:
|
|
break
|
|
case .failure(let error):
|
|
self?.error = .other(error: error)
|
|
}
|
|
}
|
|
}
|
|
|
|
func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didFailWith error: Error) {
|
|
accountIsUpdatingCredentials = false
|
|
self.error = .other(error: error)
|
|
}
|
|
}
|