diff --git a/LeStorage/Codables/FailedAPICall.swift b/LeStorage/Codables/FailedAPICall.swift index 4dbe87b..98708b2 100644 --- a/LeStorage/Codables/FailedAPICall.swift +++ b/LeStorage/Codables/FailedAPICall.swift @@ -9,14 +9,17 @@ import Foundation class FailedAPICall: ModelObject, Storable { - static func resourceName() -> String { return "failed_api_calls" } - static func tokenExemptedMethods() -> [HTTPMethod] { return HTTPMethod.allCases } + static func resourceName() -> String { return "failed-api-calls" } + static func tokenExemptedMethods() -> [HTTPMethod] { return [] } var id: String = Store.randomId() /// The creation date of the call var date: Date = Date() + /// The user having the issue + var user: String + /// The id of the API call var callId: String @@ -29,7 +32,8 @@ class FailedAPICall: ModelObject, Storable { /// The server error var error: String - init(callId: String, type: String, apiCall: String, error: String) { + init(user: String, callId: String, type: String, apiCall: String, error: String) { + self.user = user self.callId = callId self.type = type self.apiCall = apiCall diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index 7f5c815..3eb45df 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.swift @@ -89,7 +89,7 @@ public class Services { fileprivate func _runRequest(_ request: URLRequest, apiCallId: String? = nil) async throws -> T { Logger.log("Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")") let task: (Data, URLResponse) = try await URLSession.shared.data(for: request) - Logger.log("response = \(String(describing: String(data: task.0, encoding: .utf8)))") + Logger.log("response = \(String(data: task.0, encoding: .utf8) ?? "")") if let response = task.1 as? HTTPURLResponse { let statusCode = response.statusCode @@ -104,12 +104,11 @@ public class Services { } default: Logger.log("Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")") - var errorString = String(describing: String(data: task.0, encoding: .utf8)) - if let nfe: NonFieldError = try? JSONDecoder().decode(NonFieldError.self, from: task.0) { - if let reason = nfe.non_field_errors.first { - errorString = reason - } + var errorString: String = String(data: task.0, encoding: .utf8) ?? "" + if let message = self.errorMessageFromResponse(data: task.0) { + errorString = message } + if let apiCallId, let type = (T.self as? any Storable.Type) { try Store.main.rescheduleApiCall(id: apiCallId, type: type) @@ -287,6 +286,18 @@ public class Services { try self.keychainStore.deleteToken() } + + fileprivate func errorMessageFromResponse(data: Data) -> String? { + do { + if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let stringsArray = jsonObject.values.first as? [String] { + return stringsArray.first + } + } catch { + print("Failed to parse JSON: \(error.localizedDescription)") + } + return nil + } + } struct AuthResponse: Codable { @@ -303,9 +314,6 @@ struct Token: Codable { struct Email: Codable { var email: String } -struct NonFieldError: Codable { - var non_field_errors: [String] -} public protocol UserBase: Codable { var id: String { get } diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index 7f4f629..60d1c7c 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -271,15 +271,15 @@ public class Store { func logFailedAPICall(_ apiCallId: String, collectionName: String, error: String) { - guard let failedAPICallsCollection = self._failedAPICallsCollection, let collection = self._collections[collectionName], let apiCall = try? collection.apiCallById(apiCallId) else { + guard let failedAPICallsCollection = self._failedAPICallsCollection, let collection = self._collections[collectionName], let apiCall = try? collection.apiCallById(apiCallId), let userId = Store.main.userId else { return } if !failedAPICallsCollection.contains(where: { $0.callId == apiCallId }) && apiCall.attemptsCount > 5 { - + do { let string = try apiCall.jsonString() - let failedAPICall = FailedAPICall(callId: apiCall.id, type: collectionName, apiCall: string, error: error) + let failedAPICall = FailedAPICall(user: userId, callId: apiCall.id, type: collectionName, apiCall: string, error: error) try failedAPICallsCollection.addOrUpdate(instance: failedAPICall) } catch { Logger.error(error)