Authentication working

* Updates to use new API style per discussion with Maurice
* Credential validation functioning
This commit is contained in:
Jeremy Beker 2019-05-29 10:54:52 -04:00
parent de82f718d5
commit 0df86e5761
No known key found for this signature in database
GPG Key ID: CD5EE767A4A34FD0
10 changed files with 99 additions and 101 deletions

View File

@ -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)

View File

@ -46,6 +46,6 @@ protocol AccountDelegate {
// Called at the end of accounts 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)
}

View File

@ -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))
}

View File

@ -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

View File

@ -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))
}
}

View File

@ -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

View File

@ -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))
}
}

View File

@ -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")

View File

@ -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