Create individual functions for routes

This commit is contained in:
Christoph Hagen 2022-10-11 11:51:00 +02:00
parent 75211f67ca
commit fc4afb70b1

View File

@ -15,25 +15,46 @@ func encodeJSON<T>(_ response: T) throws -> String where T: Encodable {
} }
func routes(_ app: Application) throws { func routes(_ app: Application) throws {
registerPlayer(app)
requestPlayerPasswordReset(app)
resetPlayerPasswordWithEmailToken(app)
deletePlayer(app)
loginPlayer(app)
resumeSession(app)
logoutPlayer(app)
getTableForPlayer(app)
openWebsocket(app)
createTable(app)
getPublicTables(app)
joinTable(app)
leaveTable(app)
performActionForPlayer(app)
playCard(app)
}
// MARK: Players & Sessions // MARK: Players & Sessions
/**
Create a new player.
Headers:
- `name`: The username of the player
- `password`: The password of the player
- `email`: Optional email address for password reset
Possible responses:
- `200`: On success, with the session token for the registered user in the reponse body
- `400`: Missing name or password
- `406`: Password or name too long
- `409`: A player with the same name already exists
- `424`: The password could not be hashed
*/
func registerPlayer(_ app: Application) {
app.post("player", "register") { req -> EventLoopFuture<SessionToken> in
let name = try req.header(.name)
let password = try req.header(.password)
let mail = req.optionalHeader(.email)?.trimmed.nonEmpty
/**
Create a new 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
- 406: Password or name too long
- 409: A player with the same name already exists
- 424: The password could not be hashed
- Returns: The session token for the registered user
*/
app.post("player", "register", ":name") { req -> EventLoopFuture<SessionToken> in
guard let name = req.parameters.get("name"),
let password = req.body.string else {
throw Abort(.badRequest) // 400
}
guard name.count < maximumPlayerNameLength, guard name.count < maximumPlayerNameLength,
password.count < maximumPasswordLength else { password.count < maximumPasswordLength else {
throw Abort(.notAcceptable) // 406 throw Abort(.notAcceptable) // 406
@ -45,17 +66,19 @@ func routes(_ app: Application) throws {
// Can throw conflict (409) // Can throw conflict (409)
return server.registerPlayer(named: name, hash: hash, in: req.db) return server.registerPlayer(named: name, hash: hash, in: req.db)
} }
}
/**
Delete a player.
/** - Parameter name: The name of the player, included in the url
Delete a player. - Parameter password: The password of the player, as a string in the request body
- Parameter name: The name of the player, included in the url - Throws:
- Parameter password: The password of the player, as a string in the request body - 400: Missing name or password
- Throws: - 403: The password or user name is invalid
- 400: Missing name or password - 424: The password could not be hashed
- 403: The password or user name is invalid - Returns: Nothing
- 424: The password could not be hashed */
- Returns: Nothing func deletePlayer(_ app: Application) {
*/
app.post("player", "delete", ":name") { req -> EventLoopFuture<String> in app.post("player", "delete", ":name") { req -> EventLoopFuture<String> in
guard let name = req.parameters.get("name"), guard let name = req.parameters.get("name"),
let password = req.body.string else { let password = req.body.string else {
@ -68,6 +91,7 @@ func routes(_ app: Application) throws {
server.deletePlayer(named: name, in: req.db) server.deletePlayer(named: name, in: req.db)
}.map { "" } }.map { "" }
} }
}
/** /**
Log in as an existing player. Log in as an existing player.
@ -79,6 +103,7 @@ func routes(_ app: Application) throws {
- 424: The password could not be hashed - 424: The password could not be hashed
- Returns: The session token for the user - Returns: The session token for the user
*/ */
func loginPlayer(_ app: Application) {
app.post("player", "login", ":name") { req -> EventLoopFuture<String> in app.post("player", "login", ":name") { req -> EventLoopFuture<String> in
guard let name = req.parameters.get("name"), guard let name = req.parameters.get("name"),
let password = req.body.string else { let password = req.body.string else {
@ -91,6 +116,7 @@ func routes(_ app: Application) throws {
server.startNewSessionForRegisteredPlayer(named: name) server.startNewSessionForRegisteredPlayer(named: name)
} }
} }
}
/** /**
Log in using a session token. Log in using a session token.
@ -100,6 +126,7 @@ func routes(_ app: Application) throws {
- 401: The token is invalid - 401: The token is invalid
- Returns: The player name associated with the session token - Returns: The player name associated with the session token
*/ */
func resumeSession(_ app: Application) {
app.post("player", "resume") { req -> String in app.post("player", "resume") { req -> String in
guard let token = req.body.string else { guard let token = req.body.string else {
throw Abort(.badRequest) // 400 throw Abort(.badRequest) // 400
@ -109,6 +136,7 @@ func routes(_ app: Application) throws {
} }
return player return player
} }
}
/** /**
Log out. Log out.
@ -119,6 +147,7 @@ func routes(_ app: Application) throws {
- Returns: Nothing - Returns: Nothing
- Note: The request always succeeds when correctly formed, even for invalid and expired tokens - Note: The request always succeeds when correctly formed, even for invalid and expired tokens
*/ */
func logoutPlayer(_ app: Application) {
app.post("player", "logout") { req -> String in app.post("player", "logout") { req -> String in
guard let token = req.body.string else { guard let token = req.body.string else {
throw Abort(.badRequest) // 400 throw Abort(.badRequest) // 400
@ -126,6 +155,7 @@ func routes(_ app: Application) throws {
server.endSession(forSessionToken: token) server.endSession(forSessionToken: token)
return "" return ""
} }
}
/** /**
Get the current table of the player, if one exists. Get the current table of the player, if one exists.
@ -135,6 +165,7 @@ func routes(_ app: Application) throws {
- 401: Invalid token - 401: Invalid token
- Returns: The table info, or an empty string - Returns: The table info, or an empty string
*/ */
func getTableForPlayer(_ app: Application) {
app.post("player", "table") { req -> String in app.post("player", "table") { req -> String in
guard let token = req.body.string else { guard let token = req.body.string else {
throw Abort(.badRequest) // 400 throw Abort(.badRequest) // 400
@ -147,12 +178,14 @@ func routes(_ app: Application) throws {
} }
return try encodeJSON(info) return try encodeJSON(info)
} }
}
/** /**
Start a new websocket connection for the client to receive table updates from the server Start a new websocket connection for the client to receive table updates from the server
- Returns: Nothing - Returns: Nothing
- Note: The first (and only) message from the client over the connection must be a valid session token. - Note: The first (and only) message from the client over the connection must be a valid session token.
*/ */
func openWebsocket(_ app: Application) {
app.webSocket("session", "start") { req, socket in app.webSocket("session", "start") { req, socket in
socket.onText { socket, text in socket.onText { socket, text in
guard server.startSession(socket: socket, sessionToken: text) else { guard server.startSession(socket: socket, sessionToken: text) else {
@ -161,6 +194,7 @@ func routes(_ app: Application) throws {
} }
} }
} }
}
// MARK: Tables // MARK: Tables
@ -173,12 +207,13 @@ func routes(_ app: Application) throws {
- 400: Missing token, table name or invalid visibility - 400: Missing token, table name or invalid visibility
- 401: The session token is invalid - 401: The session token is invalid
*/ */
func createTable(_ app: Application) {
app.post("table", "create", ":visibility", ":name") { req -> EventLoopFuture<String> in app.post("table", "create", ":visibility", ":name") { req -> EventLoopFuture<String> in
guard let visibility = req.parameters.get("visibility"), guard let visibility = req.parameters.get("visibility"),
let tableName = req.parameters.get("name"), let tableName = req.parameters.get("name"),
let token = req.body.string else { let token = req.body.string else {
throw Abort(.badRequest) // 400 throw Abort(.badRequest) // 400
} }
let isPublic: Bool let isPublic: Bool
if visibility == "private" { if visibility == "private" {
isPublic = false isPublic = false
@ -194,6 +229,7 @@ func routes(_ app: Application) throws {
return server.createTable(named: tableName, player: player, isPublic: isPublic, in: req.db) return server.createTable(named: tableName, player: player, isPublic: isPublic, in: req.db)
.flatMapThrowing(encodeJSON) .flatMapThrowing(encodeJSON)
} }
}
/** /**
List the public tables. List the public tables.
@ -203,6 +239,7 @@ func routes(_ app: Application) throws {
- 403: The session token is invalid - 403: The session token is invalid
- Returns: A JSON object with a list of public tables (id, name, player list) - 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 app.post("tables", "public") { req -> String in
guard let token = req.body.string else { guard let token = req.body.string else {
throw Abort(.badRequest) // 400 throw Abort(.badRequest) // 400
@ -213,6 +250,7 @@ func routes(_ app: Application) throws {
let list = server.getPublicTableInfos() let list = server.getPublicTableInfos()
return try encodeJSON(list) return try encodeJSON(list)
} }
}
/** /**
Join a table. Join a table.
@ -226,6 +264,8 @@ func routes(_ app: Application) throws {
- 417: The table is already full and can't be joined - 417: The table is already full and can't be joined
- Returns: Nothing - Returns: Nothing
*/ */
func joinTable(_ app: Application) {
app.post("table", "join", ":table") { req -> EventLoopFuture<String> in app.post("table", "join", ":table") { req -> EventLoopFuture<String> in
guard let string = req.parameters.get("table"), guard let string = req.parameters.get("table"),
let table = UUID(uuidString: string), let table = UUID(uuidString: string),
@ -235,6 +275,7 @@ func routes(_ app: Application) throws {
return server.join(tableId: table, playerToken: token, in: req.db) return server.join(tableId: table, playerToken: token, in: req.db)
.flatMapThrowing(encodeJSON) .flatMapThrowing(encodeJSON)
} }
}
/** /**
Leave the current table. Leave the current table.
@ -244,18 +285,21 @@ func routes(_ app: Application) throws {
- 401: The session token is invalid - 401: The session token is invalid
- Returns: Nothing - Returns: Nothing
*/ */
func leaveTable(_ app: Application) {
app.post("table", "leave") { req -> EventLoopFuture<String> in app.post("table", "leave") { req -> EventLoopFuture<String> in
guard let token = req.body.string else { guard let token = req.body.string else {
throw Abort(.badRequest) throw Abort(.badRequest)
} }
return server.leaveTable(playerToken: token, in: req.db).map { "" } return server.leaveTable(playerToken: token, in: req.db).map { "" }
} }
}
func performActionForPlayer(_ app: Application) {
app.post("player", "action", ":action") { req -> String in app.post("player", "action", ":action") { req -> String in
guard let token = req.body.string, guard let token = req.body.string,
let actionString = req.parameters.get("action") else { let actionString = req.parameters.get("action") else {
throw Abort(.badRequest) throw Abort(.badRequest)
} }
let result: PlayerActionResult let result: PlayerActionResult
if let action = PlayerAction(rawValue: actionString) { if let action = PlayerAction(rawValue: actionString) {
result = server.performAction(playerToken: token, action: action) result = server.performAction(playerToken: token, action: action)
@ -279,7 +323,9 @@ func routes(_ app: Application) throws {
throw Abort(.preconditionFailed) // 412 throw Abort(.preconditionFailed) // 412
} }
} }
}
func playCard(_ app: Application) {
app.post("player", "card", ":card") { req -> String in app.post("player", "card", ":card") { req -> String in
guard let token = req.body.string, guard let token = req.body.string,
let cardId = req.parameters.get("card"), let cardId = req.parameters.get("card"),