diff --git a/LeStorage/Codables/FailedAPICall.swift b/LeStorage/Codables/FailedAPICall.swift index 9674e17..a4ab422 100644 --- a/LeStorage/Codables/FailedAPICall.swift +++ b/LeStorage/Codables/FailedAPICall.swift @@ -29,11 +29,15 @@ class FailedAPICall: ModelObject, Storable { /// The server error var error: String - init(callId: String, type: String, apiCall: String, error: String) { + /// The authentication header + var authentication: String? + + init(callId: String, type: String, apiCall: String, error: String, authentication: String?) { self.callId = callId self.type = type self.apiCall = apiCall self.error = error + self.authentication = authentication } } diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index a987f7f..1f2cf08 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.swift @@ -107,6 +107,10 @@ public class Services { } } default: + /* + request ended with status code = 401 + {"detail":"Informations d'authentification non fournies."} + */ Logger.log("Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")") var errorString: String = String(data: task.0, encoding: .utf8) ?? "" if let message = self.errorMessageFromResponse(data: task.0) { @@ -115,7 +119,7 @@ public class Services { if let apiCallId, let type = (T.self as? any Storable.Type) { try Store.main.rescheduleApiCall(id: apiCallId, type: type) - Store.main.logFailedAPICall(apiCallId, collectionName: type.resourceName(), error: errorString) + Store.main.logFailedAPICall(apiCallId, request: request, collectionName: type.resourceName(), error: errorString) } else { Store.main.logFailedAPICall(request: request, error: errorString) } diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index 325f3ed..16025c0 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -192,9 +192,9 @@ public class Store { } /// Deletes the dependencies of a collection - public func deleteDependencies(items: any Sequence) throws { - try self.collection().deleteDependencies(items) - } +// public func deleteDependencies(items: any Sequence) throws { +// try self.collection().deleteDependencies(items) +// } // MARK: - Api call rescheduling @@ -278,7 +278,7 @@ public class Store { /// If configured for, logs and send to the server a failed API call /// Logs a failed API call that has failed at least 5 times - func logFailedAPICall(_ apiCallId: String, collectionName: String, error: String) { + func logFailedAPICall(_ apiCallId: String, request: URLRequest, collectionName: String, error: String) { guard let failedAPICallsCollection = self._failedAPICallsCollection, let collection = self._collections[collectionName], @@ -290,8 +290,9 @@ public class Store { if !failedAPICallsCollection.contains(where: { $0.callId == apiCallId }) && apiCall.attemptsCount > 6 { do { + let authValue = request.allHTTPHeaderFields?["Authorization"] let string = try apiCall.jsonString() - let failedAPICall = FailedAPICall(callId: apiCall.id, type: collectionName, apiCall: string, error: error) + let failedAPICall = FailedAPICall(callId: apiCall.id, type: collectionName, apiCall: string, error: error, authentication: authValue) try failedAPICallsCollection.addOrUpdate(instance: failedAPICall) } catch { Logger.error(error) @@ -309,8 +310,10 @@ public class Store { return } + let authValue = request.allHTTPHeaderFields?["Authorization"] + do { - let failedAPICall = FailedAPICall(callId: request.hashValue.formatted(), type: url, apiCall: bodyString, error: error) + let failedAPICall = FailedAPICall(callId: request.hashValue.formatted(), type: url, apiCall: bodyString, error: error, authentication: authValue) try failedAPICallsCollection.addOrUpdate(instance: failedAPICall) } catch { Logger.error(error) diff --git a/README.md b/README.md index a32a49d..7b0ab72 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ - Pass `synchronized: true` when registering the collection - For each of your `ModelObject`, make sure that `resourceName()` returns the resource path of the endpoint, for example "cars" - Synchronization is expected to be done with a rest_framework API on a django server - - On Django, when using cascading delete foreign, you'll want to avoid sending useless delete API calls to django, so override the `deleteDependencies` function of your ModelObject and call `Store.main.deleteDependencies` for the objects you also want to delete to reproduce the cascading effect + - On Django, when using cascading delete foreign, you'll want to avoid sending useless delete API calls to django, so override the `deleteDependencies` function of your ModelObject and call `deleteDependencies` on the collection for the objects you also want to delete to reproduce the cascading effect - On your Django serializers, you want to define the following on your foreign keys to avoid having a URL instead of just the id: `car_id = serializers.PrimaryKeyRelatedField(queryset=Car.objects.all())`