// // SettingsCredentialsAccountModel.swift // Multiplatform iOS // // Created by Rizwan on 21/07/20. // Copyright © 2020 Ranchero Software. All rights reserved. // import Foundation import Account import Secrets class SettingsCredentialsAccountModel: ObservableObject { var account: Account? = nil var accountType: AccountType @Published var shouldDismiss: Bool = false @Published var email: String = "" @Published var password: String = "" @Published var apiUrl: String = "" @Published var busy: Bool = false @Published var accountCredentialsError: AccountCredentialsError? { didSet { accountCredentialsError != AccountCredentialsError.none ? (showError = true) : (showError = false) } } @Published var showError: Bool = false @Published var showPassword: Bool = false init(account: Account) { self.account = account self.accountType = account.type if let credentials = try? account.retrieveCredentials(type: .basic) { self.email = credentials.username self.password = credentials.secret } } init(accountType: AccountType) { self.accountType = accountType } var isUpdate: Bool { return account != nil } var isValid: Bool { if apiUrlEnabled { return !email.isEmpty && !password.isEmpty && !apiUrl.isEmpty } return !email.isEmpty && !password.isEmpty } var accountName: String { switch accountType { case .onMyMac: return Account.defaultLocalAccountName case .cloudKit: return "iCloud" case .feedbin: return "Feedbin" case .feedly: return "Feedly" case .feedWrangler: return "Feed Wrangler" case .newsBlur: return "NewsBlur" default: return "" } } var emailText: String { return accountType == .newsBlur ? NSLocalizedString("Username or Email", comment: "") : NSLocalizedString("Email", comment: "") } var apiUrlEnabled: Bool { return accountType == .freshRSS } func addAccount() { switch accountType { case .feedbin: addFeedbinAccount() case .feedWrangler: addFeedWranglerAccount() case .newsBlur: addNewsBlurAccount() case .freshRSS: addFreshRSSAccount() default: return } } } extension SettingsCredentialsAccountModel { // MARK:- Feedbin func addFeedbinAccount() { busy = true accountCredentialsError = AccountCredentialsError.none let emailAddress = email.trimmingCharacters(in: .whitespaces) let credentials = Credentials(type: .basic, username: emailAddress, secret: password) Account.validateCredentials(type: .feedbin, credentials: credentials) { (result) in self.busy = false switch result { case .success(let authenticated): if (authenticated != nil) { var newAccount = false let workAccount: Account if self.account == nil { workAccount = AccountManager.shared.createAccount(type: .feedbin) newAccount = true } else { workAccount = self.account! } do { do { try workAccount.removeCredentials(type: .basic) } catch {} try workAccount.storeCredentials(credentials) if newAccount { workAccount.refreshAll() { result in } } self.shouldDismiss = true } catch { self.accountCredentialsError = AccountCredentialsError.keyChain } } else { self.accountCredentialsError = AccountCredentialsError.invalidCredentials } case .failure: self.accountCredentialsError = AccountCredentialsError.noNetwork } } } // MARK: FeedWrangler func addFeedWranglerAccount() { busy = true let credentials = Credentials(type: .feedWranglerBasic, username: email, secret: password) Account.validateCredentials(type: .feedWrangler, credentials: credentials) { [weak self] result in guard let self = self else { return } self.busy = false switch result { case .success(let validatedCredentials): guard let validatedCredentials = validatedCredentials else { self.accountCredentialsError = .invalidCredentials return } let account = AccountManager.shared.createAccount(type: .feedWrangler) do { try account.removeCredentials(type: .feedWranglerBasic) try account.removeCredentials(type: .feedWranglerToken) try account.storeCredentials(credentials) try account.storeCredentials(validatedCredentials) self.shouldDismiss = true account.refreshAll(completion: { result in switch result { case .success: break case .failure(let error): self.accountCredentialsError = .other(error: error) } }) } catch { self.accountCredentialsError = .keyChain } case .failure: self.accountCredentialsError = .noNetwork } } } // MARK:- NewsBlur func addNewsBlurAccount() { busy = true let credentials = Credentials(type: .newsBlurBasic, username: email, secret: password) Account.validateCredentials(type: .newsBlur, credentials: credentials) { [weak self] result in guard let self = self else { return } self.busy = false switch result { case .success(let validatedCredentials): guard let validatedCredentials = validatedCredentials else { self.accountCredentialsError = .invalidCredentials return } let account = AccountManager.shared.createAccount(type: .newsBlur) do { try account.removeCredentials(type: .newsBlurBasic) try account.removeCredentials(type: .newsBlurSessionId) try account.storeCredentials(credentials) try account.storeCredentials(validatedCredentials) self.shouldDismiss = true account.refreshAll(completion: { result in switch result { case .success: break case .failure(let error): self.accountCredentialsError = .other(error: error) } }) } catch { self.accountCredentialsError = .keyChain } case .failure: self.accountCredentialsError = .noNetwork } } } // MARK:- Fresh RSS func addFreshRSSAccount() { busy = true let credentials = Credentials(type: .readerBasic, username: email, secret: password) Account.validateCredentials(type: .freshRSS, credentials: credentials, endpoint: URL(string: apiUrl)!) { [weak self] result in guard let self = self else { return } self.busy = false switch result { case .success(let validatedCredentials): guard let validatedCredentials = validatedCredentials else { self.accountCredentialsError = .invalidCredentials return } let account = AccountManager.shared.createAccount(type: .freshRSS) do { try account.removeCredentials(type: .readerBasic) try account.removeCredentials(type: .readerAPIKey) try account.storeCredentials(credentials) try account.storeCredentials(validatedCredentials) self.shouldDismiss = true account.refreshAll(completion: { result in switch result { case .success: break case .failure(let error): self.accountCredentialsError = .other(error: error) } }) } catch { self.accountCredentialsError = .keyChain } case .failure: self.accountCredentialsError = .noNetwork } } } }