Authentication working
* Updates to use new API style per discussion with Maurice * Credential validation functioning
This commit is contained in:
parent
de82f718d5
commit
0df86e5761
|
@ -252,6 +252,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
// MARK: - API
|
||||
|
||||
public func storeCredentials(_ credentials: Credentials) throws {
|
||||
// The delegate may need the credentials to determine the server
|
||||
delegate.credentials = credentials
|
||||
|
||||
guard let server = delegate.server else {
|
||||
throw CredentialsError.incompleteCredentials
|
||||
}
|
||||
|
@ -259,7 +262,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
switch credentials {
|
||||
case .basic(let username, _):
|
||||
self.username = username
|
||||
case .googleLogin(let username, _, _, _):
|
||||
case .googleBasicLogin(let username, _, _):
|
||||
self.username = username
|
||||
case .googleAuthLogin(let username, _, _):
|
||||
self.username = username
|
||||
}
|
||||
|
||||
|
@ -284,7 +289,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
self.username = nil
|
||||
}
|
||||
|
||||
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
switch type {
|
||||
case .onMyMac:
|
||||
LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
|
||||
|
|
|
@ -46,6 +46,6 @@ protocol AccountDelegate {
|
|||
// Called at the end of account’s init method.
|
||||
func accountDidInitialize(_ account: Account)
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void)
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ final class FeedbinAPICaller: NSObject {
|
|||
self.transport = transport
|
||||
}
|
||||
|
||||
func validateCredentials(completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||
func validateCredentials(completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
|
||||
let callURL = feedbinBaseURL.appendingPathComponent("authentication.json")
|
||||
let request = URLRequest(url: callURL, credentials: credentials)
|
||||
|
@ -50,12 +50,12 @@ final class FeedbinAPICaller: NSObject {
|
|||
transport.send(request: request) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
completion(.success(true))
|
||||
completion(.success(self.credentials))
|
||||
case .failure(let error):
|
||||
switch error {
|
||||
case TransportError.httpError(let status):
|
||||
if status == 401 {
|
||||
completion(.success(false))
|
||||
completion(.success(self.credentials))
|
||||
} else {
|
||||
completion(.failure(error))
|
||||
}
|
||||
|
|
|
@ -485,7 +485,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
|||
accountMetadata = account.metadata
|
||||
}
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
|
||||
let caller = FeedbinAPICaller(transport: transport)
|
||||
caller.credentials = credentials
|
||||
|
|
|
@ -35,41 +35,43 @@ final class GoogleReaderCompatibleAPICaller: NSObject {
|
|||
private var transport: Transport!
|
||||
|
||||
var credentials: Credentials?
|
||||
var apiAuthToken: String?
|
||||
weak var accountMetadata: AccountMetadata?
|
||||
|
||||
var server: String? {
|
||||
get {
|
||||
guard let localCredentials = credentials else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch localCredentials {
|
||||
case .googleBasicLogin(_, _, let apiUrl):
|
||||
return apiUrl.host
|
||||
case .googleAuthLogin(_, _, let apiUrl):
|
||||
return apiUrl.host
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init(transport: Transport) {
|
||||
super.init()
|
||||
self.transport = transport
|
||||
}
|
||||
|
||||
func validateCredentials(completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||
func validateCredentials(completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
guard let credentials = credentials else {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
return
|
||||
}
|
||||
|
||||
guard case .googleLogin(let username, let password, let apiUrl, _) = credentials else {
|
||||
guard case .googleBasicLogin(let username, _, let apiUrl) = credentials else {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
return
|
||||
}
|
||||
|
||||
guard var loginURL = URLComponents(url: apiUrl.appendingPathComponent("/accounts/ClientLogin"), resolvingAgainstBaseURL: false) else {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
return
|
||||
}
|
||||
|
||||
loginURL.queryItems = [
|
||||
URLQueryItem(name: "Email", value: username),
|
||||
URLQueryItem(name: "Passwd", value: password)
|
||||
]
|
||||
|
||||
guard let callURL = loginURL.url else {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
return
|
||||
}
|
||||
|
||||
let request = URLRequest(url: callURL, credentials: credentials)
|
||||
let request = URLRequest(url: apiUrl.appendingPathComponent("/accounts/ClientLogin"), credentials: credentials)
|
||||
|
||||
transport.send(request: request) { result in
|
||||
switch result {
|
||||
|
@ -97,20 +99,11 @@ final class GoogleReaderCompatibleAPICaller: NSObject {
|
|||
}
|
||||
|
||||
// Save Auth Token for later use
|
||||
self.apiAuthToken = authString
|
||||
self.credentials = .googleAuthLogin(username: username, apiKey: authString, url: apiUrl)
|
||||
|
||||
completion(.success(true))
|
||||
completion(.success(self.credentials))
|
||||
case .failure(let error):
|
||||
switch error {
|
||||
case TransportError.httpError(let status):
|
||||
if status == 401 {
|
||||
completion(.success(false))
|
||||
} else {
|
||||
completion(.failure(error))
|
||||
}
|
||||
default:
|
||||
completion(.failure(error))
|
||||
}
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,12 @@ final class GoogleReaderCompatibleAccountDelegate: AccountDelegate {
|
|||
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "GoogleReaderCompatible")
|
||||
|
||||
let supportsSubFolders = false
|
||||
let server: String? = "api.GoogleReaderCompatible.com"
|
||||
var server: String? {
|
||||
get {
|
||||
return caller.server
|
||||
}
|
||||
}
|
||||
|
||||
var opmlImportInProgress = false
|
||||
|
||||
var credentials: Credentials? {
|
||||
|
@ -485,7 +490,7 @@ final class GoogleReaderCompatibleAccountDelegate: AccountDelegate {
|
|||
accountMetadata = account.metadata
|
||||
}
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Bool, Error>) -> Void) {
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
|
||||
let caller = GoogleReaderCompatibleAPICaller(transport: transport)
|
||||
caller.credentials = credentials
|
||||
|
|
|
@ -182,8 +182,8 @@ final class LocalAccountDelegate: AccountDelegate {
|
|||
func accountDidInitialize(_ account: Account) {
|
||||
}
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: (Result<Bool, Error>) -> Void) {
|
||||
return completion(.success(false))
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, completion: (Result<Credentials?, Error>) -> Void) {
|
||||
return completion(.success(nil))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,38 +74,36 @@ class AccountsFeedbinWindowController: NSWindowController {
|
|||
self.progressIndicator.stopAnimation(self)
|
||||
|
||||
switch result {
|
||||
case .success(let authenticated):
|
||||
|
||||
if authenticated {
|
||||
|
||||
var newAccount = false
|
||||
if self.account == nil {
|
||||
self.account = AccountManager.shared.createAccount(type: .feedbin)
|
||||
newAccount = true
|
||||
}
|
||||
|
||||
do {
|
||||
try self.account?.removeBasicCredentials()
|
||||
try self.account?.storeCredentials(credentials)
|
||||
if newAccount {
|
||||
self.account?.refreshAll() { result in
|
||||
switch result {
|
||||
case .success:
|
||||
break
|
||||
case .failure(let error):
|
||||
NSApplication.shared.presentError(error)
|
||||
}
|
||||
case .success(let validatedCredentials):
|
||||
|
||||
guard let validatedCredentials = validatedCredentials else {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
|
||||
return
|
||||
}
|
||||
var newAccount = false
|
||||
if self.account == nil {
|
||||
self.account = AccountManager.shared.createAccount(type: .feedbin)
|
||||
newAccount = true
|
||||
}
|
||||
|
||||
do {
|
||||
try self.account?.removeBasicCredentials()
|
||||
try self.account?.storeCredentials(validatedCredentials)
|
||||
if newAccount {
|
||||
self.account?.refreshAll() { result in
|
||||
switch result {
|
||||
case .success:
|
||||
break
|
||||
case .failure(let error):
|
||||
NSApplication.shared.presentError(error)
|
||||
}
|
||||
}
|
||||
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
|
||||
} catch {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
|
||||
}
|
||||
|
||||
} else {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
|
||||
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
|
||||
} catch {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
|
||||
}
|
||||
|
||||
|
||||
case .failure:
|
||||
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
|
||||
|
|
|
@ -70,7 +70,7 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController {
|
|||
return
|
||||
}
|
||||
|
||||
let credentials = Credentials.googleLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue, apiUrl: apiURL, apiKey: nil)
|
||||
let credentials = Credentials.googleBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue, url: apiURL)
|
||||
Account.validateCredentials(type: .googleReaderCompatible, credentials: credentials) { [weak self] result in
|
||||
|
||||
guard let self = self else { return }
|
||||
|
@ -80,42 +80,39 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController {
|
|||
self.progressIndicator.stopAnimation(self)
|
||||
|
||||
switch result {
|
||||
case .success(let authenticated):
|
||||
case .success(let validatedCredentials):
|
||||
guard let validatedCredentials = validatedCredentials else {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
|
||||
return
|
||||
}
|
||||
|
||||
if authenticated {
|
||||
|
||||
var newAccount = false
|
||||
if self.account == nil {
|
||||
self.account = AccountManager.shared.createAccount(type: .googleReaderCompatible)
|
||||
newAccount = true
|
||||
}
|
||||
|
||||
do {
|
||||
try self.account?.removeBasicCredentials()
|
||||
try self.account?.storeCredentials(credentials)
|
||||
if newAccount {
|
||||
self.account?.refreshAll() { result in
|
||||
switch result {
|
||||
case .success:
|
||||
break
|
||||
case .failure(let error):
|
||||
NSApplication.shared.presentError(error)
|
||||
}
|
||||
|
||||
var newAccount = false
|
||||
if self.account == nil {
|
||||
self.account = AccountManager.shared.createAccount(type: .googleReaderCompatible)
|
||||
newAccount = true
|
||||
}
|
||||
|
||||
do {
|
||||
try self.account?.removeBasicCredentials()
|
||||
try self.account?.storeCredentials(validatedCredentials)
|
||||
if newAccount {
|
||||
self.account?.refreshAll() { result in
|
||||
switch result {
|
||||
case .success:
|
||||
break
|
||||
case .failure(let error):
|
||||
NSApplication.shared.presentError(error)
|
||||
}
|
||||
}
|
||||
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
|
||||
} catch {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
|
||||
}
|
||||
|
||||
} else {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
|
||||
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
|
||||
} catch {
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
|
||||
}
|
||||
|
||||
|
||||
case .failure:
|
||||
|
||||
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 261feb7537eb7c6dc425fd1c9e24b22dea8fc982
|
||||
Subproject commit 07ec7f9179dfdf7e89fc97a4a90c4690fa71581a
|
Loading…
Reference in New Issue