|
|
|
|
@ -7,7 +7,7 @@ |
|
|
|
|
|
|
|
|
|
import Foundation |
|
|
|
|
|
|
|
|
|
public enum HTTPMethod: String, CaseIterable { |
|
|
|
|
public enum HTTPMethod: String, CaseIterable, Codable { |
|
|
|
|
case get = "GET" |
|
|
|
|
case post = "POST" |
|
|
|
|
case put = "PUT" |
|
|
|
|
@ -19,7 +19,7 @@ public enum ServiceError: Error { |
|
|
|
|
case cantConvertToUUID(id: String) |
|
|
|
|
case missingUserName |
|
|
|
|
case responseError(response: String) |
|
|
|
|
case missingToken |
|
|
|
|
// case missingToken |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate enum ServiceConf: String { |
|
|
|
|
@ -59,6 +59,7 @@ public class Services { |
|
|
|
|
public init(url: String) { |
|
|
|
|
self.baseURL = url |
|
|
|
|
self.keychainStore = KeychainStore(serverId: url) |
|
|
|
|
Logger.log("create keystore with id: \(url)") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate(set) var baseURL: String |
|
|
|
|
@ -163,13 +164,8 @@ public class Services { |
|
|
|
|
request.httpMethod = method.rawValue |
|
|
|
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type") |
|
|
|
|
if !(requiresToken == false) { |
|
|
|
|
// Logger.log("current token = \(token)") |
|
|
|
|
do { |
|
|
|
|
let token = try self.keychainStore.getToken() |
|
|
|
|
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization") |
|
|
|
|
} catch { |
|
|
|
|
throw ServiceError.missingToken |
|
|
|
|
} |
|
|
|
|
let token = try self.keychainStore.getToken() |
|
|
|
|
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return request |
|
|
|
|
@ -200,15 +196,13 @@ public class Services { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _request<T: Storable>(from apiCall: ApiCall<T>) throws -> URLRequest { |
|
|
|
|
guard let url = URL(string: apiCall.url) else { |
|
|
|
|
throw ServiceError.urlCreationError(url: apiCall.url) |
|
|
|
|
} |
|
|
|
|
let url = try self._url(from: apiCall) |
|
|
|
|
var request = URLRequest(url: url) |
|
|
|
|
request.httpMethod = apiCall.method |
|
|
|
|
request.httpMethod = apiCall.method.rawValue |
|
|
|
|
request.httpBody = apiCall.body.data(using: .utf8) |
|
|
|
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type") |
|
|
|
|
|
|
|
|
|
if let method = HTTPMethod(rawValue: apiCall.method), self._isTokenRequired(type: T.self, method: method) { |
|
|
|
|
if self._isTokenRequired(type: T.self, method: apiCall.method) { |
|
|
|
|
do { |
|
|
|
|
let token = try self.keychainStore.getToken() |
|
|
|
|
request.setValue("Token \(token)", forHTTPHeaderField: "Authorization") |
|
|
|
|
@ -220,6 +214,21 @@ public class Services { |
|
|
|
|
return request |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate func _url<T: Storable>(from apiCall: ApiCall<T>) throws -> URL { |
|
|
|
|
var stringURL: String = self.baseURL |
|
|
|
|
switch apiCall.method { |
|
|
|
|
case HTTPMethod.put, HTTPMethod.delete: |
|
|
|
|
stringURL += T.path(id: apiCall.dataId) |
|
|
|
|
default: |
|
|
|
|
stringURL += T.path() |
|
|
|
|
} |
|
|
|
|
if let url = URL(string: stringURL) { |
|
|
|
|
return url |
|
|
|
|
} else { |
|
|
|
|
throw ServiceError.urlCreationError(url: stringURL) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// MARK: - Authentication |
|
|
|
|
|
|
|
|
|
public func createAccount<U: UserPasswordBase, V: UserBase>(user: U) async throws -> V { |
|
|
|
|
@ -286,7 +295,6 @@ 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] { |
|
|
|
|
|