Convert validateCredentials to async await.
This commit is contained in:
parent
1ad010d4f8
commit
61af38fabf
|
@ -128,11 +128,11 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||
self.refreshProgress.completeTask()
|
||||
self.caller.retrieveItemIDs(type: .allForAccount) { result in
|
||||
self.refreshProgress.completeTask()
|
||||
|
||||
|
||||
switch result {
|
||||
|
||||
|
||||
case .success(let articleIDs):
|
||||
|
||||
|
||||
Task { @MainActor in
|
||||
try? await account.markAsRead(Set(articleIDs))
|
||||
self.refreshArticleStatus(for: account) { _ in
|
||||
|
@ -145,40 +145,33 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case .failure(let error):
|
||||
DispatchQueue.main.async {
|
||||
|
||||
Task { @MainActor in
|
||||
self.refreshProgress.clear()
|
||||
|
||||
let wrappedError = AccountError.wrappedError(error: error, account: account)
|
||||
if wrappedError.isCredentialsError, let basicCredentials = try? account.retrieveCredentials(type: .readerBasic), let endpoint = account.endpointURL {
|
||||
self.caller.credentials = basicCredentials
|
||||
|
||||
self.caller.validateCredentials(endpoint: endpoint) { result in
|
||||
switch result {
|
||||
case .success(let apiCredentials):
|
||||
if let apiCredentials = apiCredentials {
|
||||
DispatchQueue.main.async {
|
||||
try? account.storeCredentials(apiCredentials)
|
||||
self.caller.credentials = apiCredentials
|
||||
self.refreshAll(for: account, completion: completion)
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(wrappedError))
|
||||
}
|
||||
}
|
||||
case .failure:
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(wrappedError))
|
||||
}
|
||||
do {
|
||||
if let apiCredentials = try await self.caller.validateCredentials(endpoint: endpoint) {
|
||||
try? account.storeCredentials(apiCredentials)
|
||||
self.caller.credentials = apiCredentials
|
||||
self.refreshAll(for: account, completion: completion)
|
||||
}
|
||||
else {
|
||||
completion(.failure(wrappedError))
|
||||
}
|
||||
} catch {
|
||||
completion(.failure(wrappedError))
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -186,9 +179,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func syncArticleStatus(for account: Account) async throws {
|
||||
|
@ -838,35 +829,15 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider) async throws -> Credentials? {
|
||||
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
|
||||
self.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, secretsProvider: secretsProvider) { result in
|
||||
|
||||
switch result {
|
||||
case .success(let credentials):
|
||||
continuation.resume(returning: credentials)
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, secretsProvider: SecretsProvider, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
guard let endpoint = endpoint else {
|
||||
completion(.failure(TransportError.noURL))
|
||||
return
|
||||
|
||||
guard let endpoint else {
|
||||
throw TransportError.noURL
|
||||
}
|
||||
|
||||
let caller = ReaderAPICaller(transport: transport, secretsProvider: secretsProvider)
|
||||
caller.credentials = credentials
|
||||
caller.validateCredentials(endpoint: endpoint) { result in
|
||||
DispatchQueue.main.async {
|
||||
completion(result)
|
||||
}
|
||||
}
|
||||
|
||||
return try await caller.validateCredentials(endpoint: endpoint)
|
||||
}
|
||||
|
||||
// MARK: Suspend and Resume (for iOS)
|
||||
|
|
|
@ -15,7 +15,7 @@ enum CreateReaderAPISubscriptionResult {
|
|||
case notFound
|
||||
}
|
||||
|
||||
final class ReaderAPICaller: NSObject {
|
||||
@MainActor final class ReaderAPICaller: NSObject {
|
||||
|
||||
enum ItemIDType {
|
||||
case unread
|
||||
|
@ -93,55 +93,51 @@ final class ReaderAPICaller: NSObject {
|
|||
transport.cancelAll()
|
||||
}
|
||||
|
||||
func validateCredentials(endpoint: URL, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||
guard let credentials = credentials else {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
return
|
||||
func validateCredentials(endpoint: URL) async throws -> Credentials? {
|
||||
|
||||
guard let credentials else {
|
||||
throw CredentialsError.incompleteCredentials
|
||||
}
|
||||
|
||||
|
||||
var request = URLRequest(url: endpoint.appendingPathComponent(ReaderAPIEndpoints.login.rawValue), credentials: credentials)
|
||||
addVariantHeaders(&request)
|
||||
|
||||
transport.send(request: request) { result in
|
||||
switch result {
|
||||
case .success(let (_, data)):
|
||||
guard let resultData = data else {
|
||||
completion(.failure(TransportError.noData))
|
||||
break
|
||||
}
|
||||
|
||||
// Convert the return data to UTF8 and then parse out the Auth token
|
||||
guard let rawData = String(data: resultData, encoding: .utf8) else {
|
||||
completion(.failure(TransportError.noData))
|
||||
break
|
||||
}
|
||||
|
||||
var authData: [String: String] = [:]
|
||||
rawData.split(separator: "\n").forEach({ (line: Substring) in
|
||||
let items = line.split(separator: "=").map{String($0)}
|
||||
if items.count == 2 {
|
||||
authData[items[0]] = items[1]
|
||||
}
|
||||
})
|
||||
|
||||
guard let authString = authData["Auth"] else {
|
||||
completion(.failure(CredentialsError.incompleteCredentials))
|
||||
break
|
||||
}
|
||||
|
||||
// Save Auth Token for later use
|
||||
self.credentials = Credentials(type: .readerAPIKey, username: credentials.username, secret: authString)
|
||||
|
||||
completion(.success(self.credentials))
|
||||
case .failure(let error):
|
||||
if let transportError = error as? TransportError, case .httpError(let code) = transportError, code == 404 {
|
||||
completion(.failure(ReaderAPIAccountDelegateError.urlNotFound))
|
||||
} else {
|
||||
completion(.failure(error))
|
||||
do {
|
||||
let (_, data) = try await transport.send(request: request)
|
||||
|
||||
guard let data else {
|
||||
throw TransportError.noData
|
||||
}
|
||||
|
||||
// Convert the return data to UTF8 and then parse out the Auth token
|
||||
guard let rawData = String(data: data, encoding: .utf8) else {
|
||||
throw TransportError.noData
|
||||
}
|
||||
|
||||
var authData: [String: String] = [:]
|
||||
rawData.split(separator: "\n").forEach({ (line: Substring) in
|
||||
let items = line.split(separator: "=").map{String($0)}
|
||||
if items.count == 2 {
|
||||
authData[items[0]] = items[1]
|
||||
}
|
||||
})
|
||||
|
||||
guard let authString = authData["Auth"] else {
|
||||
throw CredentialsError.incompleteCredentials
|
||||
}
|
||||
|
||||
// Save Auth Token for later use
|
||||
self.credentials = Credentials(type: .readerAPIKey, username: credentials.username, secret: authString)
|
||||
|
||||
return self.credentials
|
||||
|
||||
} catch {
|
||||
if let transportError = error as? TransportError, case .httpError(let code) = transportError, code == 404 {
|
||||
throw ReaderAPIAccountDelegateError.urlNotFound
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func requestAuthorizationToken(endpoint: URL, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
|
|
Loading…
Reference in New Issue