diff --git a/Sources/App/API/HeaderKey.swift b/Sources/App/API/HeaderKey.swift new file mode 100644 index 0000000..c637283 --- /dev/null +++ b/Sources/App/API/HeaderKey.swift @@ -0,0 +1,41 @@ +import Foundation +import Vapor + +enum HeaderKey: String { + case name + case password + case email + case token +} + +extension Request { + + /** + Get a header for a key, or abort with a `badRequest`. + */ + func header(_ key: HeaderKey) throws -> String { + guard let value = headers.first(name: key.rawValue) else { + throw Abort(.badRequest) + } + return value + } + + func optionalHeader(_ key: HeaderKey) -> String? { + headers.first(name: key.rawValue) + } + + /** + Get the password from the request header and hash it. + + Possible error responses: + - `400`: No password header found + - `424`: Failed to hash the password + */ + func hashedPassword() throws -> String { + let password = try header(.password) + guard let hash = try? self.password.hash(password) else { + throw Abort(.failedDependency) // 424 + } + return hash + } +} diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index 3151ce3..e212d61 100644 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -57,12 +57,11 @@ func registerPlayer(_ app: Application) { guard name.count < maximumPlayerNameLength, password.count < maximumPasswordLength else { - throw Abort(.notAcceptable) // 406 - } - - guard let hash = try? req.password.hash(password) else { - throw Abort(.failedDependency) // 424 + throw Abort(.notAcceptable) // 406 } + + let hash = try req.hashedPassword() // errors: 400, 424 + // Can throw conflict (409) return server.registerPlayer(named: name, hash: hash, in: req.db) }