diff --git a/Sources/App/Management/SQLiteDatabase.swift b/Sources/App/Management/SQLiteDatabase.swift index f11b9ed..7ebf005 100644 --- a/Sources/App/Management/SQLiteDatabase.swift +++ b/Sources/App/Management/SQLiteDatabase.swift @@ -59,14 +59,14 @@ final class SQLiteDatabase { Send a password reset email. Possible errors: - - `404`: Player name or email not found. + - `417`: Player name or email not found. */ func sendPasswordResetEmailIfPossible(name: PlayerName, in database: Database) async throws { guard let user = try await User.query(on: database).filter(\.$name == name).first() else { - throw Abort(.notFound) + throw Abort(.expectationFailed) } guard let email = user.recoveryEmail else { - throw Abort(.notFound) + throw Abort(.expectationFailed) } try await user.$resetRequest.load(on: database) if let request = user.resetRequest { @@ -115,7 +115,7 @@ final class SQLiteDatabase { Change the password of a user with a recovery token Possible errors: - - `404`: Reset token not found or expired + - `417`: Reset token not found or expired */ func updatePassword(password: String, forResetToken token: String, in database: Database) async throws { // 1. Find and validate the reset request @@ -146,7 +146,7 @@ final class SQLiteDatabase { .query(on: database) .filter(\.$name == name) .first() - .unwrap(or: Abort(.notFound)) + .unwrap(or: Abort(.unauthorized)) .passwordHash } diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index 38ae36e..7484263 100644 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -74,12 +74,12 @@ func registerPlayer(_ app: Application) { Possible responses: - `200`: Success, email will be sent - `400`: Missing name header - - `404`: Player name not found or no email registered + - `417`: Player name not found or no email registered */ func requestPlayerPasswordReset(_ app: Application) { app.post("player", "password", "reset") { request async throws -> HTTPResponseStatus in let name = try request.header(.name) // Error: 400 - try await server.sendPasswordResetEmailIfPossible(name: name, in: request.db) + try await server.sendPasswordResetEmailIfPossible(name: name, in: request.db) // 417 return .ok } } @@ -94,14 +94,14 @@ func requestPlayerPasswordReset(_ app: Application) { Possible responses: - `200`: Success, password changed - `400`: Missing token or password header - - `404`: Player name not found or no email registered + - `417`: Player name not found or no email registered - `424`: Password could not be hashed */ func resetPlayerPasswordWithEmailToken(_ app: Application) { app.post("player", "reset") { req async throws -> HTTPResponseStatus in - let token = try req.header(.token) + let token = try req.header(.token) // 400 let hash = try req.hashedPassword() // errors: 400, 424 - try await server.updatePassword(password: hash, forResetToken: token, in: req.db) + try await server.updatePassword(password: hash, forResetToken: token, in: req.db) // 417 return .ok } } @@ -111,10 +111,11 @@ func resetPlayerPasswordWithEmailToken(_ app: Application) { - Parameter name: The name of the player, included in the url - Parameter password: The password of the player, as a string in the request body - - Throws: - - 400: Missing name or password - - 403: The password or user name is invalid - - 424: The password could not be hashed + + Possible errors: + - `400`: Missing name or password + - `401`: The password or user name is invalid + - `424`: The password could not be hashed - Returns: Nothing */ func deletePlayer(_ app: Application) { @@ -125,23 +126,25 @@ func deletePlayer(_ app: Application) { } let hash = try await server.passwordHashForExistingPlayer(named: name, in: request.db) guard try request.password.verify(password, created: hash) else { - return .forbidden // 403 + return .unauthorized // 401 } try await server.deletePlayer(named: name, in: request.db) return .ok } } - /** - Log in as an existing player. - - Parameter name: The name of the player, included in the url - - Parameter password: The password of the player, as a string in the request body - - Throws: - - 400: Missing name or password - - 403: The password or user name is invalid - - 424: The password could not be hashed - - Returns: The session token for the user - */ +/** + Log in as an existing player. + - Parameter name: The name of the player, included in the url + - Parameter password: The password of the player, as a string in the request body + + Possible errors: + - `400`: Missing name or password + - `401`: The password or user name is invalid + - `424`: The password could not be hashed + + - Returns: The session token for the user + */ func loginPlayer(_ app: Application) { app.post("player", "login", ":name") { request async throws -> String in guard let name = request.parameters.get("name"), @@ -150,7 +153,7 @@ func loginPlayer(_ app: Application) { } let hash = try await server.passwordHashForExistingPlayer(named: name, in: request.db) guard try request.password.verify(password, created: hash) else { - throw Abort(.forbidden) // 403 + throw Abort(.unauthorized) // 401 } return server.startNewSessionForRegisteredPlayer(named: name) } @@ -269,21 +272,24 @@ func createTable(_ app: Application) { } } - /** - List the public tables. - - Parameter token: The session token of the player, as a string in the request body - - Throws: - - 400: Missing token - - 403: The session token is invalid - - Returns: A JSON object with a list of public tables (id, name, player list) - */ +/** + List the public tables. + + **Headers** + - `token`: The session token of the player, as a string in the request body + + **Possible errors** + - `400`: Missing token + - `401`: The session token is invalid + - Returns: A JSON object with a list of public tables (id, name, player list) + */ func getPublicTables(_ app: Application) { app.post("tables", "public") { req -> String in guard let token = req.body.string else { throw Abort(.badRequest) // 400 } guard server.isValid(sessionToken: token) else { - throw Abort(.forbidden) // 403 + throw Abort(.unauthorized) // 401 } let list = server.getPublicTableInfos() return try encodeJSON(list)