NetNewsWire/Multiplatform/iOS/Settings/Accounts/SettingsCredentialsAccountM...

282 lines
6.9 KiB
Swift

//
// 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
}
}
}
}