Convert registration to async

This commit is contained in:
Christoph Hagen 2022-10-12 14:34:43 +02:00
parent 8b89ebcccb
commit 7ef5da08d0
3 changed files with 30 additions and 21 deletions

View File

@ -32,11 +32,22 @@ final class SQLiteDatabase {
self.mailConfiguration = mail self.mailConfiguration = mail
} }
func registerPlayer(named name: PlayerName, hash: PasswordHash, in database: Database) -> EventLoopFuture<SessionToken> { func registerPlayer(named name: PlayerName, hash: PasswordHash, email: String?, in database: Database) async throws -> SessionToken {
User.query(on: database).filter(\.$name == name).first() if let email {
.guard({ $0 == nil }, else: Abort(.conflict)).flatMap { _ in let user = try await User
let user = User(name: name, hash: hash) .query(on: database)
return user.create(on: database).map { .filter(\.$recoveryEmail == email)
.first()
if user != nil {
throw Abort(.conflict)
}
}
if try await User.query(on: database).filter(\.$name == name).first() != nil {
throw Abort(.conflict)
}
let user = User(name: name, hash: hash, email: email)
try await user.create(on: database)
// Create a new token and store it for the user // Create a new token and store it for the user
let token = SessionToken.newToken() let token = SessionToken.newToken()
self.sessionTokenForPlayer[name] = token self.sessionTokenForPlayer[name] = token
@ -44,7 +55,6 @@ final class SQLiteDatabase {
return token return token
} }
} }
}
private func sendEmail(name: PlayerName, email: String, token: String) { private func sendEmail(name: PlayerName, email: String, token: String) {
let recipient = Mail.User(name: name, email: email) let recipient = Mail.User(name: name, email: email)

View File

@ -63,11 +63,12 @@ final class User: Model {
init() { } init() { }
/// Creates a new user. /// Creates a new user.
init(id: UUID? = nil, name: String, hash: String) { init(id: UUID? = nil, name: String, hash: String, email: String? = nil) {
self.id = id self.id = id
self.name = name self.name = name
self.passwordHash = hash self.passwordHash = hash
self.points = 0 self.points = 0
self.recoveryEmail = email
} }
} }

View File

@ -50,20 +50,18 @@ func routes(_ app: Application) throws {
- `424`: The password could not be hashed - `424`: The password could not be hashed
*/ */
func registerPlayer(_ app: Application) { func registerPlayer(_ app: Application) {
app.post("player", "register") { req -> EventLoopFuture<SessionToken> in app.post("player", "register") { request async throws -> SessionToken in
let name = try req.header(.name) let name = try request.header(.name)
let password = try req.header(.password) let hash = try request.hashedPassword() // errors: 400, 424
let mail = req.optionalHeader(.email)?.trimmed.nonEmpty let mail = request.optionalHeader(.email)?.trimmed.nonEmpty
guard name.count < maximumPlayerNameLength, guard name.count < maximumPlayerNameLength else {
password.count < maximumPasswordLength else {
throw Abort(.notAcceptable) // 406 throw Abort(.notAcceptable) // 406
} }
let hash = try req.hashedPassword() // errors: 400, 424
// Can throw conflict (409) // Can throw conflict (409)
return server.registerPlayer(named: name, hash: hash, in: req.db) // if either the player exists, or the email is already in use
return try await server.registerPlayer(named: name, hash: hash, email: mail, in: request.db)
} }
} }
/** /**