diff --git a/Sources/App/CapServer.swift b/Sources/App/CapServer.swift index 23efa5e..f976e5b 100644 --- a/Sources/App/CapServer.swift +++ b/Sources/App/CapServer.swift @@ -163,11 +163,10 @@ final class CapServer { Automatically creates the image name with the current image count. - Parameter data: The image data - Parameter cap: The id of the cap. - - Returns: The new image count for the cap - Throws: `CapError.unknownId`, if the cap doesn't exist. `CapError.dataInconsistency` if an image already exists for the current count. */ - func save(image data: Data, for cap: Int) throws -> Int { - guard var count = caps[cap]?.count else { + func save(image data: Data, for cap: Int) throws { + guard caps[cap] != nil else { throw CapError.unknownId } var id = 0 @@ -177,10 +176,8 @@ final class CapServer { f = file(of: cap, version: id) } try data.write(to: f) - count += 1 - caps[cap]!.count = count + caps[cap]!.count += 1 log("Added image \(id) for cap \(cap)") - return count } func switchMainImage(to version: Int, for cap: Int) throws { @@ -192,4 +189,34 @@ final class CapServer { caps[cap]?.mainImage = version log("Switched cap \(cap) to version \(version)") } + + func addOrUpdate(_ cap: Cap) throws { + if let existingCap = caps[cap.id] { + try update(existingCap, with: cap) + } else { + try add(cap) + } + } + + private func add(_ cap: Cap) throws { + guard cap.mainImage == 0, cap.count == 0 else { + throw CapError.invalidData + } + caps[cap.id] = cap + } + + private func update(_ existingCap: Cap, with cap: Cap) throws { + var updatedCap = existingCap + if cap.name != "" { + updatedCap.name = cap.name + } + let url = file(of: cap.id, version: cap.mainImage) + if fm.fileExists(atPath: url.path) { + updatedCap.mainImage = cap.mainImage + } + if let color = cap.color { + updatedCap.color = color + } + caps[cap.id] = updatedCap + } } diff --git a/Sources/App/Error.swift b/Sources/App/Error.swift index 2c7f221..6e93861 100644 --- a/Sources/App/Error.swift +++ b/Sources/App/Error.swift @@ -15,6 +15,7 @@ enum CapError: Error { case dataInconsistency case invalidFile case invalidConfiguration + case invalidData var response: HTTPResponseStatus { switch self { @@ -22,6 +23,8 @@ enum CapError: Error { case .unknownId: return .notFound /// 400 case .invalidBody: return .badRequest + /// 406 + case .invalidData: return .notAcceptable /// 409 case .dataInconsistency: return .conflict /// 412 diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index c75d979..94e9b24 100755 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -1,5 +1,8 @@ import Vapor +/// The decoder to extract caps from JSON payloads given to the `cap` route. +private let decoder = JSONDecoder() + private func authorize(_ request: Request) throws { let key = try request.query.get(String.self, at: "key") guard server.hasAuthorization(for: key) else { @@ -7,27 +10,21 @@ private func authorize(_ request: Request) throws { } } -/// Register your application's routes here. -/// -/// [Learn More →](https://docs.vapor.codes/3.0/getting-started/structure/#routesswift) func routes(_ app: Application) throws { - - // Set the name of a cap - app.postCatching("name", ":n") { request in + + // Add or change a cap + app.postCatching("cap") { request in try authorize(request) - guard let cap = request.parameters.get("n", as: Int.self) else { - log("Invalid parameter for cap") - throw Abort(.badRequest) - } - guard let buffer = request.body.data, let name = String(data: Data(buffer: buffer), encoding: .utf8) else { + guard let buffer = request.body.data else { log("Invalid body data") throw CapError.invalidBody } - try server.set(name: name, for: cap) + let cap = try decoder.decode(Cap.self, from: buffer) + try server.addOrUpdate(cap) } // Upload an image - app.postCatching("images", ":n") { request -> Data in + app.postCatching("images", ":n") { request in try authorize(request) guard let cap = request.parameters.get("n", as: Int.self) else { log("Invalid parameter for cap") @@ -38,21 +35,6 @@ func routes(_ app: Application) throws { throw CapError.invalidBody } let data = Data(buffer: buffer) - let newCount = try server.save(image: data, for: cap) - return "\(newCount)".data(using: .utf8)! - } - - // Set a different version as the main image - app.getCatching("switch", ":n", ":v") { request in - try authorize(request) - guard let cap = request.parameters.get("n", as: Int.self), cap >= 0 else { - log("Invalid parameter for cap") - throw Abort(.badRequest) - } - guard let version = request.parameters.get("v", as: Int.self), version >= 0 else { - log("Invalid parameter for cap version") - throw Abort(.badRequest) - } - try server.switchMainImage(to: version, for: cap) + try server.save(image: data, for: cap) } }