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.
This commit is contained in:
Jeremy Beker 2019-05-29 15:16:09 -04:00
parent 0df86e5761
commit aa6dfe8a08
No known key found for this signature in database
GPG Key ID: CD5EE767A4A34FD0
9 changed files with 60 additions and 29 deletions

View File

@ -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 private var fetchingAllUnreadCounts = false
var isUnreadCountsInitialized = false var isUnreadCountsInitialized = false
@ -262,9 +273,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
switch credentials { switch credentials {
case .basic(let username, _): case .basic(let username, _):
self.username = username self.username = username
case .googleBasicLogin(let username, _, _): case .googleBasicLogin(let username, _):
self.username = username self.username = username
case .googleAuthLogin(let username, _, _): case .googleAuthLogin(let username, _):
self.username = username self.username = username
} }
@ -289,14 +300,14 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
self.username = nil self.username = nil
} }
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) { public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result<Credentials?, Error>) -> Void) {
switch type { switch type {
case .onMyMac: case .onMyMac:
LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
case .feedbin: case .feedbin:
FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
case .googleReaderCompatible: case .googleReaderCompatible:
GoogleReaderCompatibleAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) GoogleReaderCompatibleAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, completion: completion)
default: default:
break break
} }

View File

@ -46,6 +46,6 @@ protocol AccountDelegate {
// Called at the end of accounts init method. // Called at the end of accounts init method.
func accountDidInitialize(_ account: Account) func accountDidInitialize(_ account: Account)
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void)
} }

View File

@ -21,6 +21,7 @@ final class AccountMetadata: Codable {
case username case username
case conditionalGetInfo case conditionalGetInfo
case lastArticleFetch case lastArticleFetch
case endpointURL
} }
var name: String? { var name: String? {
@ -62,6 +63,14 @@ final class AccountMetadata: Codable {
} }
} }
} }
var endpointURL: URL? {
didSet {
if endpointURL != oldValue {
valueDidChange(.endpointURL)
}
}
}
weak var delegate: AccountMetadataDelegate? weak var delegate: AccountMetadataDelegate?

View File

@ -485,7 +485,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
accountMetadata = account.metadata accountMetadata = account.metadata
} }
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) { static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result<Credentials?, Error>) -> Void) {
let caller = FeedbinAPICaller(transport: transport) let caller = FeedbinAPICaller(transport: transport)
caller.credentials = credentials caller.credentials = credentials

View File

@ -39,18 +39,17 @@ final class GoogleReaderCompatibleAPICaller: NSObject {
var server: String? { var server: String? {
get { get {
guard let localCredentials = credentials else { return APIBaseURL?.host
return nil }
} }
switch localCredentials { private var APIBaseURL: URL? {
case .googleBasicLogin(_, _, let apiUrl): get {
return apiUrl.host guard let accountMetadata = accountMetadata else {
case .googleAuthLogin(_, _, let apiUrl):
return apiUrl.host
default:
return nil return nil
} }
return accountMetadata.endpointURL
} }
} }
@ -60,18 +59,18 @@ final class GoogleReaderCompatibleAPICaller: NSObject {
self.transport = transport self.transport = transport
} }
func validateCredentials(completion: @escaping (Result<Credentials?, Error>) -> Void) { func validateCredentials(endpoint: URL, completion: @escaping (Result<Credentials?, Error>) -> Void) {
guard let credentials = credentials else { guard let credentials = credentials else {
completion(.failure(CredentialsError.incompleteCredentials)) completion(.failure(CredentialsError.incompleteCredentials))
return return
} }
guard case .googleBasicLogin(let username, _, let apiUrl) = credentials else { guard case .googleBasicLogin(let username, _) = credentials else {
completion(.failure(CredentialsError.incompleteCredentials)) completion(.failure(CredentialsError.incompleteCredentials))
return 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 transport.send(request: request) { result in
switch result { switch result {
@ -99,7 +98,7 @@ final class GoogleReaderCompatibleAPICaller: NSObject {
} }
// Save Auth Token for later use // 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)) completion(.success(self.credentials))
case .failure(let error): case .failure(let error):
@ -159,10 +158,14 @@ final class GoogleReaderCompatibleAPICaller: NSObject {
} }
func retrieveTags(completion: @escaping (Result<[GoogleReaderCompatibleTag]?, Error>) -> Void) { 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 callURL = baseURL.appendingPathComponent("/reader/api/0/tag/list?output=json")
let conditionalGet = accountMetadata?.conditionalGetInfo[ConditionalGetKeys.tags] //let conditionalGet = accountMetadata?.conditionalGetInfo[ConditionalGetKeys.tags]
let request = URLRequest(url: callURL, credentials: credentials, conditionalGet: conditionalGet) let request = URLRequest(url: callURL, credentials: credentials)
transport.send(request: request, resultType: [GoogleReaderCompatibleTag].self) { result in transport.send(request: request, resultType: [GoogleReaderCompatibleTag].self) { result in

View File

@ -490,11 +490,15 @@ final class GoogleReaderCompatibleAccountDelegate: AccountDelegate {
accountMetadata = account.metadata accountMetadata = account.metadata
} }
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Credentials?, Error>) -> Void) { static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void) {
guard let endpoint = endpoint else {
completion(.failure(TransportError.noURL))
return
}
let caller = GoogleReaderCompatibleAPICaller(transport: transport) let caller = GoogleReaderCompatibleAPICaller(transport: transport)
caller.credentials = credentials caller.credentials = credentials
caller.validateCredentials() { result in caller.validateCredentials(endpoint: endpoint) { result in
DispatchQueue.main.async { DispatchQueue.main.async {
completion(result) completion(result)
} }

View File

@ -182,7 +182,7 @@ final class LocalAccountDelegate: AccountDelegate {
func accountDidInitialize(_ account: Account) { func accountDidInitialize(_ account: Account) {
} }
static func validateCredentials(transport: Transport, credentials: Credentials, completion: (Result<Credentials?, Error>) -> Void) { static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: (Result<Credentials?, Error>) -> Void) {
return completion(.success(nil)) return completion(.success(nil))
} }

View File

@ -70,8 +70,8 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController {
return return
} }
let credentials = Credentials.googleBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue, url: apiURL) let credentials = Credentials.googleBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue)
Account.validateCredentials(type: .googleReaderCompatible, credentials: credentials) { [weak self] result in Account.validateCredentials(type: .googleReaderCompatible, credentials: credentials, endpoint: apiURL) { [weak self] result in
guard let self = self else { return } guard let self = self else { return }
@ -94,8 +94,12 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController {
} }
do { do {
self.account?.endpointURL = apiURL
try self.account?.removeBasicCredentials() try self.account?.removeBasicCredentials()
try self.account?.storeCredentials(validatedCredentials) try self.account?.storeCredentials(validatedCredentials)
if newAccount { if newAccount {
self.account?.refreshAll() { result in self.account?.refreshAll() { result in
switch result { switch result {

@ -1 +1 @@
Subproject commit 07ec7f9179dfdf7e89fc97a4a90c4690fa71581a Subproject commit f3bcd0312d6797e2722760c1de622e2957114802