Problème avec Vapor et retour d'un Future

Salut a tous,

Comment peut on retourner une erreur en fonction d’un futur sous Vapor ?

Avant de créer un utilisateur, je veux verifier si il est deja enregistré et si l’username choisit existe deja.
Sinon, retourner l’erreur correspondante.

Je n’arrive pas à trouver un moyen de tout imbriquer…

enum UserError {
    case usernameTaken
    case emailTaken
}

extension UserError: AbortError {
    var description: String {
        reason
    }
    
    var status: HTTPResponseStatus {
        switch self {
            case .usernameTaken: return .conflict
            case .emailTaken: return .conflict
        }
    }
    
    var reason: String {
        switch self {
            case .usernameTaken: return "Username already taken"
            case .emailTaken: return "Email already registered"
        }
    }
}


private func checkIfUserExists(_ username: String, _ email: String, req: Request) -> EventLoopFuture<UserError?> {
        
        // Si l'username existe deja -> Retourner l'erreur .usernameTaken
        User.query(on: req.db)
            .filter(\.$username == username)
            .first()
            .map { $0 != nil }
                
        return req.eventLoop.future(error: UserError.usernameTaken)
        
        // Si l'email existe deja -> Retourner l'erreur .emailTaken
        User.query(on: req.db)
            .filter(\.$email == email)
            .first()
            .map {
                if $0 != nil { return UserError.emailTaken }
            }
    }

Merci d’avance !
Cedric

@Draken - HELP!! :sweat_smile:
Une idée ?

Je ne sais même pas ce qu’est Vapor, ni un Futur !

:sob:

Le cours de Maxime « Créer un webservice en Swift avec Vapor 4 » sur Vapor/Fluent est très intéressant.
Malheureusement, j’ai beau regarder la partie sur les valeurs futur (map/flatmap/transform), jej e comprends pas commet faire…

ça fait partie de choses que je regarderais à tête reposé quand j’aurais du temps libre devant moi. Pour le moment, mon carnet de bal est rempli, pour les 6 prochains mois (minimum)…

1 « J'aime »

Salut @cedric06nice,

Je n’ai encore jamais fait ça mais, tu captures les erreurs avec catch ou throw et après tu fais une condition ou tu utilises un guard pour lancer l’erreur avec catch ou throw suivant si ta fonction propage ou pas les erreurs.

Plus d’info ici : https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html

Merci @ThonyF,

Je n’ai pas réussi a faire ce que je voulais en retournant directement une erreur spécifique et je n’arrive pas non plus à retourner un false au lieu d’un true…

Mais bon, le code suivant fonctionne donc je ne vais pas perdre plus de temps et l’utiliser jusqu’à ce que je sois plus compétent pour le modifier dans une version ultérieure… :wink:

Je met la partie de code ici si ça intéresse quelqu’un :

fileprivate func create(req: Request) throws -> EventLoopFuture<NewSession> {
        
        let userSignup = try req.content.decode(UserSignup.self)
        let user = try User.create(from: userSignup)
        
        return checkIfEmailExists(userSignup.email, req: req).flatMap { emailExists in
            guard emailExists else {
                return req.eventLoop.future(error: UserError.emailTaken)
            }
            
            return checkIfUsernameExists(userSignup.username, req: req).flatMap { usernameExists in
                guard usernameExists else {
                    return req.eventLoop.future(error: UserError.usernameTaken)
                }
                return user.save(on: req.db)
            }
        }.flatMapThrowing {
            NewSession(user: try user.asPublic())
        }
    }
    
    private func checkIfEmailExists(_ email: String, req: Request) -> EventLoopFuture<Bool> {
        User.query(on: req.db)
            .filter(\.$email == email)
            .first()
            .map { $0 == nil }  
            //  ->  Retourne TRUE si la valeur est NIL car je n'arrive pas a inverser la fonction
    }
    
    private func checkIfUsernameExists(_ username: String, req: Request) -> EventLoopFuture<Bool> {
        User.query(on: req.db)
            .filter(\.$username == username)
            .first()
            .map { $0 == nil }
            //  ->  Et là aussi...
    }