From aa6dfe8a0885f6a1cc60576496cca2898287aa9d Mon Sep 17 00:00:00 2001 From: Jeremy Beker Date: Wed, 29 May 2019 15:16:09 -0400 Subject: [PATCH] Rework to store endpoint URL in metadata Endpoint URL did not belong with credentials. This breaks it out and stores it in the account metadata. Updates validation code to take it as a parameter. --- Frameworks/Account/Account.swift | 19 ++++++++-- Frameworks/Account/AccountDelegate.swift | 2 +- Frameworks/Account/AccountMetadata.swift | 9 +++++ .../Feedbin/FeedbinAccountDelegate.swift | 2 +- .../GoogleReaderCompatibleAPICaller.swift | 37 ++++++++++--------- ...oogleReaderCompatibleAccountDelegate.swift | 8 +++- .../LocalAccount/LocalAccountDelegate.swift | 2 +- ...ogleReaderCompatibleWindowController.swift | 8 +++- submodules/RSWeb | 2 +- 9 files changed, 60 insertions(+), 29 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 32598e41a..f2802c5d1 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -121,6 +121,17 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } } + public var endpointURL: URL? { + get { + return metadata.endpointURL + } + set { + if newValue != metadata.endpointURL { + metadata.endpointURL = newValue + } + } + } + private var fetchingAllUnreadCounts = false var isUnreadCountsInitialized = false @@ -262,9 +273,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, switch credentials { case .basic(let username, _): self.username = username - case .googleBasicLogin(let username, _, _): + case .googleBasicLogin(let username, _): self.username = username - case .googleAuthLogin(let username, _, _): + case .googleAuthLogin(let username, _): self.username = username } @@ -289,14 +300,14 @@ 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) -> Void) { + public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result) -> Void) { switch type { case .onMyMac: LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) case .feedbin: FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) case .googleReaderCompatible: - GoogleReaderCompatibleAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) + GoogleReaderCompatibleAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, completion: completion) default: break } diff --git a/Frameworks/Account/AccountDelegate.swift b/Frameworks/Account/AccountDelegate.swift index 4d9a312b4..8c349203c 100644 --- a/Frameworks/Account/AccountDelegate.swift +++ b/Frameworks/Account/AccountDelegate.swift @@ -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) -> Void) + static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result) -> Void) } diff --git a/Frameworks/Account/AccountMetadata.swift b/Frameworks/Account/AccountMetadata.swift index 3229a4689..a741bfb12 100644 --- a/Frameworks/Account/AccountMetadata.swift +++ b/Frameworks/Account/AccountMetadata.swift @@ -21,6 +21,7 @@ final class AccountMetadata: Codable { case username case conditionalGetInfo case lastArticleFetch + case endpointURL } var name: String? { @@ -62,6 +63,14 @@ final class AccountMetadata: Codable { } } } + + var endpointURL: URL? { + didSet { + if endpointURL != oldValue { + valueDidChange(.endpointURL) + } + } + } weak var delegate: AccountMetadataDelegate? diff --git a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift index cf444ce4f..a684fa611 100644 --- a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift @@ -485,7 +485,7 @@ final class FeedbinAccountDelegate: AccountDelegate { accountMetadata = account.metadata } - static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result) -> Void) { + static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result) -> Void) { let caller = FeedbinAPICaller(transport: transport) caller.credentials = credentials diff --git a/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAPICaller.swift b/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAPICaller.swift index a5bdd5005..70c8ddde1 100644 --- a/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAPICaller.swift +++ b/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAPICaller.swift @@ -39,18 +39,17 @@ final class GoogleReaderCompatibleAPICaller: NSObject { 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 APIBaseURL?.host + } + } + + private var APIBaseURL: URL? { + get { + guard let accountMetadata = accountMetadata else { return nil } + + return accountMetadata.endpointURL } } @@ -60,18 +59,18 @@ final class GoogleReaderCompatibleAPICaller: NSObject { self.transport = transport } - func validateCredentials(completion: @escaping (Result) -> Void) { + func validateCredentials(endpoint: URL, completion: @escaping (Result) -> Void) { guard let credentials = credentials else { completion(.failure(CredentialsError.incompleteCredentials)) return } - guard case .googleBasicLogin(let username, _, let apiUrl) = credentials else { + guard case .googleBasicLogin(let username, _) = credentials else { completion(.failure(CredentialsError.incompleteCredentials)) return } - let request = URLRequest(url: apiUrl.appendingPathComponent("/accounts/ClientLogin"), credentials: credentials) + let request = URLRequest(url: endpoint.appendingPathComponent("/accounts/ClientLogin"), credentials: credentials) transport.send(request: request) { result in switch result { @@ -99,7 +98,7 @@ final class GoogleReaderCompatibleAPICaller: NSObject { } // Save Auth Token for later use - self.credentials = .googleAuthLogin(username: username, apiKey: authString, url: apiUrl) + self.credentials = .googleAuthLogin(username: username, apiKey: authString) completion(.success(self.credentials)) case .failure(let error): @@ -159,10 +158,14 @@ final class GoogleReaderCompatibleAPICaller: NSObject { } func retrieveTags(completion: @escaping (Result<[GoogleReaderCompatibleTag]?, Error>) -> Void) { + guard let baseURL = APIBaseURL else { + completion(.failure(CredentialsError.incompleteCredentials)) + return + } - let callURL = GoogleReaderCompatibleBaseURL.appendingPathComponent("tags.json") - let conditionalGet = accountMetadata?.conditionalGetInfo[ConditionalGetKeys.tags] - let request = URLRequest(url: callURL, credentials: credentials, conditionalGet: conditionalGet) + let callURL = baseURL.appendingPathComponent("/reader/api/0/tag/list?output=json") + //let conditionalGet = accountMetadata?.conditionalGetInfo[ConditionalGetKeys.tags] + let request = URLRequest(url: callURL, credentials: credentials) transport.send(request: request, resultType: [GoogleReaderCompatibleTag].self) { result in diff --git a/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAccountDelegate.swift b/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAccountDelegate.swift index b27193885..e865079d9 100644 --- a/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAccountDelegate.swift +++ b/Frameworks/Account/GoogleReaderCompatible/GoogleReaderCompatibleAccountDelegate.swift @@ -490,11 +490,15 @@ final class GoogleReaderCompatibleAccountDelegate: AccountDelegate { accountMetadata = account.metadata } - static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result) -> Void) { + static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result) -> Void) { + guard let endpoint = endpoint else { + completion(.failure(TransportError.noURL)) + return + } let caller = GoogleReaderCompatibleAPICaller(transport: transport) caller.credentials = credentials - caller.validateCredentials() { result in + caller.validateCredentials(endpoint: endpoint) { result in DispatchQueue.main.async { completion(result) } diff --git a/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift b/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift index cf06a8074..eb5fee0d9 100644 --- a/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift +++ b/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift @@ -182,7 +182,7 @@ final class LocalAccountDelegate: AccountDelegate { func accountDidInitialize(_ account: Account) { } - static func validateCredentials(transport: Transport, credentials: Credentials, completion: (Result) -> Void) { + static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: (Result) -> Void) { return completion(.success(nil)) } diff --git a/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift b/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift index 71072ae24..4ed008fe2 100644 --- a/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift @@ -70,8 +70,8 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController { return } - let credentials = Credentials.googleBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue, url: apiURL) - Account.validateCredentials(type: .googleReaderCompatible, credentials: credentials) { [weak self] result in + let credentials = Credentials.googleBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue) + Account.validateCredentials(type: .googleReaderCompatible, credentials: credentials, endpoint: apiURL) { [weak self] result in guard let self = self else { return } @@ -94,8 +94,12 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController { } do { + self.account?.endpointURL = apiURL + try self.account?.removeBasicCredentials() try self.account?.storeCredentials(validatedCredentials) + + if newAccount { self.account?.refreshAll() { result in switch result { diff --git a/submodules/RSWeb b/submodules/RSWeb index 07ec7f917..f3bcd0312 160000 --- a/submodules/RSWeb +++ b/submodules/RSWeb @@ -1 +1 @@ -Subproject commit 07ec7f9179dfdf7e89fc97a4a90c4690fa71581a +Subproject commit f3bcd0312d6797e2722760c1de622e2957114802