Adds a service to delete accounts

sync
Laurent 1 year ago
parent f5d3972eba
commit a8bd538857
  1. 110
      LeStorage/Services.swift
  2. 1
      LeStorage/Utils/Errors.swift

@ -14,37 +14,50 @@ public enum HTTPMethod: String, CaseIterable, Codable {
case delete = "DELETE" case delete = "DELETE"
} }
fileprivate enum ServiceConf: String { struct ServiceCall {
case createAccount = "users/" var path: String
case requestToken = "token-auth/" var method: HTTPMethod
case logout = "api-token-logout/" var requiresToken: Bool
case getUser = "user-by-token/" }
case changePassword = "change-password/"
case postDeviceToken = "device-token/" let createAccountCall: ServiceCall = ServiceCall(path: "users", method: .post, requiresToken: false)
let requestTokenCall: ServiceCall = ServiceCall(path: "token-auth/", method: .post, requiresToken: false)
var method: HTTPMethod { let logoutCall: ServiceCall = ServiceCall(path: "api-token-logout/", method: .post, requiresToken: true)
switch self { let getUserCall: ServiceCall = ServiceCall(path: "user-by-token/", method: .get, requiresToken: true)
case .createAccount, .requestToken, .logout, .postDeviceToken: let changePasswordCall: ServiceCall = ServiceCall(path: "change-password/", method: .put, requiresToken: true)
return .post let postDeviceTokenCall: ServiceCall = ServiceCall(path: "device-token/", method: .post, requiresToken: true)
case .changePassword:
return .put //fileprivate enum ServiceConf: String {
default: // case createAccount = "users/"
return .get // case requestToken = "token-auth/"
} // case logout = "api-token-logout/"
} // case getUser = "user-by-token/"
// case changePassword = "change-password/"
var requiresToken: Bool? { // case postDeviceToken = "device-token/"
switch self { //
case .createAccount, .requestToken: // var method: HTTPMethod {
return false // switch self {
case .getUser, .changePassword, .logout, .postDeviceToken: // case .createAccount, .requestToken, .logout, .postDeviceToken:
return true // return .post
// case .changePassword:
// return .put
// default: // default:
// return nil // return .get
} // }
} // }
//
} // var requiresToken: Bool? {
// switch self {
// case .createAccount, .requestToken:
// return false
// case .getUser, .changePassword, .logout, .postDeviceToken:
// return true
//// default:
//// return nil
// }
// }
//
//}
/// A class used to send HTTP request to the django server /// A class used to send HTTP request to the django server
public class Services { public class Services {
@ -87,8 +100,8 @@ public class Services {
/// - serviceConf: A instance of ServiceConf /// - serviceConf: A instance of ServiceConf
/// - payload: a codable value stored in the body of the request /// - payload: a codable value stored in the body of the request
/// - apiCallId: an optional id referencing an ApiCall /// - apiCallId: an optional id referencing an ApiCall
fileprivate func _runRequest<T: Encodable, U: Decodable>(serviceConf: ServiceConf, payload: T, apiCallId: String? = nil) async throws -> U { fileprivate func _runRequest<T: Encodable, U: Decodable>(serviceCall: ServiceCall, payload: T, apiCallId: String? = nil) async throws -> U {
var request = try self._baseRequest(conf: serviceConf) var request = try self._baseRequest(call: serviceCall)
request.httpBody = try jsonEncoder.encode(payload) request.httpBody = try jsonEncoder.encode(payload)
return try await _runRequest(request, apiCallId: apiCallId) return try await _runRequest(request, apiCallId: apiCallId)
} }
@ -189,8 +202,8 @@ public class Services {
/// Returns the base URLRequest for a ServiceConf instance /// Returns the base URLRequest for a ServiceConf instance
/// - Parameters: /// - Parameters:
/// - conf: a ServiceConf instance /// - conf: a ServiceConf instance
fileprivate func _baseRequest(conf: ServiceConf) throws -> URLRequest { fileprivate func _baseRequest(call: ServiceCall) throws -> URLRequest {
return try self._baseRequest(servicePath: conf.rawValue, method: conf.method, requiresToken: conf.requiresToken) return try self._baseRequest(servicePath: call.path, method: call.method, requiresToken: call.requiresToken)
} }
/// Returns a base request for a path and method /// Returns a base request for a path and method
@ -292,7 +305,7 @@ public class Services {
/// - Parameters: /// - Parameters:
/// - user: A user instance to send to the server /// - user: A user instance to send to the server
public func createAccount<U: UserPasswordBase, V: UserBase>(user: U) async throws -> V { public func createAccount<U: UserPasswordBase, V: UserBase>(user: U) async throws -> V {
return try await _runRequest(serviceConf: .createAccount, payload: user) return try await _runRequest(serviceCall: createAccountCall, payload: user)
} }
/// Requests a token for a username and password /// Requests a token for a username and password
@ -300,7 +313,7 @@ public class Services {
/// - username: the account's username /// - username: the account's username
/// - password: the account's password /// - password: the account's password
public func requestToken(username: String, password: String) async throws -> String { public func requestToken(username: String, password: String) async throws -> String {
var postRequest = try self._baseRequest(conf: .requestToken) var postRequest = try self._baseRequest(call: requestTokenCall)
let deviceId = StoreCenter.main.deviceId() let deviceId = StoreCenter.main.deviceId()
let credentials = Credentials(username: username, password: password, deviceId: deviceId) let credentials = Credentials(username: username, password: password, deviceId: deviceId)
postRequest.httpBody = try jsonEncoder.encode(credentials) postRequest.httpBody = try jsonEncoder.encode(credentials)
@ -328,7 +341,7 @@ public class Services {
/// - password: the account's password /// - password: the account's password
public func login<U: UserBase>(username: String, password: String) async throws -> U { public func login<U: UserBase>(username: String, password: String) async throws -> U {
_ = try await requestToken(username: username, password: password) _ = try await requestToken(username: username, password: password)
let postRequest = try self._baseRequest(conf: .getUser) let postRequest = try self._baseRequest(call: getUserCall)
let user: U = try await self._runRequest(postRequest) let user: U = try await self._runRequest(postRequest)
// StoreCenter.main.setUserUUID(uuidString: user.id) // StoreCenter.main.setUserUUID(uuidString: user.id)
// StoreCenter.main.setUserName(user.username) // StoreCenter.main.setUserName(user.username)
@ -342,7 +355,7 @@ public class Services {
/// - password: the account's password /// - password: the account's password
public func logout() async throws { public func logout() async throws {
let deviceId: String = StoreCenter.main.deviceId() let deviceId: String = StoreCenter.main.deviceId()
let _: Empty = try await self._runRequest(serviceConf: .logout, payload: Logout(deviceId: deviceId)) let _: Empty = try await self._runRequest(serviceCall: logoutCall, payload: Logout(deviceId: deviceId))
} }
/// A login method that actually requests a token from the server, and stores the appropriate data for later usage /// A login method that actually requests a token from the server, and stores the appropriate data for later usage
@ -352,8 +365,8 @@ public class Services {
public func postDeviceToken(deviceToken: Data) async throws { public func postDeviceToken(deviceToken: Data) async throws {
let tokenString = deviceToken.map { String(format: "%02x", $0) }.joined() let tokenString = deviceToken.map { String(format: "%02x", $0) }.joined()
let token = DeviceToken(value: tokenString) let token = DeviceToken(value: tokenString)
Logger.log("Send device token = \(tokenString)") // Logger.log("Send device token = \(tokenString)")
let _: DeviceToken = try await self._runRequest(serviceConf: .postDeviceToken, payload: token) let _: DeviceToken = try await self._runRequest(serviceCall: postDeviceTokenCall, payload: token)
} }
/// A method that sends a request to change a user's password /// A method that sends a request to change a user's password
@ -374,7 +387,7 @@ public class Services {
} }
let params = ChangePasswordParams(old_password: oldPassword, new_password1: password1, new_password2: password2) let params = ChangePasswordParams(old_password: oldPassword, new_password1: password1, new_password2: password2)
let response: Token = try await self._runRequest(serviceConf: .changePassword, payload: params) let response: Token = try await self._runRequest(serviceCall: changePasswordCall, payload: params)
self._storeToken(username: username, token: response.token) self._storeToken(username: username, token: response.token)
} }
@ -389,6 +402,21 @@ public class Services {
Logger.log("response = \(response)") Logger.log("response = \(response)")
} }
/// A login method that actually requests a token from the server, and stores the appropriate data for later usage
/// - Parameters:
/// - username: the account's username
/// - password: the account's password
public func deleteAccount() async throws {
guard let userId = StoreCenter.main.userId else {
throw ServiceError.missingUserId
}
let path = "users/\(userId)/"
let deleteAccount = ServiceCall(path: path, method: .delete, requiresToken: true)
let request = try self._baseRequest(call: deleteAccount)
let _: Empty = try await self._runRequest(request)
}
/// Deletes the locally stored token /// Deletes the locally stored token
func deleteToken() throws { func deleteToken() throws {
try self.keychainStore.deleteValue() try self.keychainStore.deleteValue()

@ -24,6 +24,7 @@ public enum ServiceError: Error {
case urlCreationError(url: String) case urlCreationError(url: String)
case cantConvertToUUID(id: String) case cantConvertToUUID(id: String)
case missingUserName case missingUserName
case missingUserId
case responseError(response: String) case responseError(response: String)
} }

Loading…
Cancel
Save