Hi there, if I want to make sure both the email and username is unique, what’s the best way to chain the futures together? I have this, which works, but I find it kind of ugly! Also I wonder if it’s more efficient to just do one query rather than two? But then I need the future to respond with an error code instead of a Bool?
/// Creates a user
func create(req: Request) throws -> EventLoopFuture<NewSession> {
try UserSignup.validate(content: req)
let userSignup = try req.content.decode(UserSignup.self)
let user = try User.create(from: userSignup)
var token: Token!
return checkIfEmaiInUse(userSignup.email, req: req)
.flatMap { exists in
guard !exists else {
return req.eventLoop.future(error: UserError.emailTaken)
}
return checkIfUsernameInUse(userSignup.username, req: req).flatMap { usernameExists in
guard !usernameExists else {
return req.eventLoop.future(error: UserError.usernameTaken)
}
return user.save(on: req.db)
}
}.flatMap {
guard let newToken = try? user.createToken(source: .signup) else {
return req.eventLoop.future(error: Abort(.internalServerError))
}
token = newToken
return token.save(on: req.db)
}.flatMapThrowing {
NewSession(token: token.value, user: try user.asPublic())
}
}
private func checkIfEmaiInUse(_ email: String,
req: Request) -> EventLoopFuture<Bool> {
User.query(on: req.db)
.filter(\.$email == email)
.first()
.map { $0 != nil }
}
private func checkIfUsernameInUse(_ username: String,
req: Request) -> EventLoopFuture<Bool> {
User.query(on: req.db)
.filter(\.$username == username)
.first()
.map { $0 != nil }
}