Vapor - BasicGroup dans le contrôler

Hello tout le monde,

Le fichier routes s’est considérablement aminci depuis les cours !

Voilà à quoi il ressemble depuis la génération par Vapor :

import Fluent
import Vapor

func routes(_ app: Application) throws {
    try app.register(collection: TodoController())
    
    try app.register(collection: UserController())
}

Du coup, je suppose que je dois créer le groupe soumis à une authentification basic dans le contrôler mais je galère un peu et le site Vapor.code est HS … :slight_smile:

Quelqu’un pourrait m’aider ?

Voici l’état actuel de mon code :

import Fluent
import Vapor

struct UserController: RouteCollection {
    func boot(routes: RoutesBuilder) throws {
        let users = routes.grouped("users")
        users.post(use: create)
// Bout de code qui pose problème ... !!
        users.group(User.Authenticator()).grouped(User.guardMiddleware()) { user in
            users.login(use: login)
        }
    }

    func create(req: Request) throws -> EventLoopFuture<User> {
        let receivedData = try req.content.decode(User.Create.self)
        let user = try User(name: receivedData.name,
                        email: receivedData.email,
                        passwordHash: Bcrypt.hash(receivedData.password))
        return user.save(on: req.db).transform(to: user)
    }
    
    func login(req:Request) throws -> EventLoopFuture<UserToken> {
        let user = try req.auth.require(User.self)
    }
}

extension User {
    struct Create: Content {
        var name: String
        var email: String
        var password: String
    }
}

extension User: ModelAuthenticatable {
    static var usernameKey = \User.$email
    static var passwordHashKey = \User.$passwordHash
    
    func verify(password: String) throws -> Bool {
        return try Bcrypt.verify(password, created: self.passwordHash)
    }
}

Merci d’avance !

Salut @Tazooou

De ce que je vois, tu dois déjà déclarer ton instance genre :

let protected = app.grouped(UserAuthenticator()) protected.get("me") { req -> String in try req.auth.require(User.self).name }

Le je ne vois pas de déclaration, tu utilises l’authenticator sans l’appeler en amont.
Puis ensuite tu peu l’appeler avec un try req.auth.require(User.self).name pour vérifier que la requête est bien authentifiée, sinon ça te renvoie une erreur. ça se fait effectivement au niveau de la route.

Tu auras plus d’informations sur le site officiel de Vapor (qui fonctionne très bien chez moi) :
https://docs.vapor.codes/4.0/authentication/

Question : As-tu testé de passer en async/await au niveau de Vapor? Je te le recommande, le code est simplifier je trouve. La doc est à jour dessus aussi.

Salut @Mrt1,

Ça refonctionne chez moi. J’ai pu parcourir la documentation, je vais essayer de corriger tout ça en prenant en compte tes remarques.
Pour le Async/Await, j’attends de finir le cours et d’être un peu plus à l’aise avec le code. Mais oui, ça a l’air de simplifier un peu les choses !

1 « J'aime »

Hello,

Je galère toujours avec cette déclaration …

let protected = app.grouped(UserAuthenticator()).grouped(User.guardMiddleware())

Etant donné que dans mon fichier routes il ne reste plus que 2 lignes qui appellent juste les contrôler, je n’ai plus accès à UserAuthenticator()
Et si je passe cette déclaration dans mon UserController, je n’ai pas accès à la variable « app »
Je vais reprendre la doc depuis le début sinon je repartirai sur l’organisation proposer par Maxime.

Je pense qu’il faut définir cette ligne :

let protected = app.grouped(UserAuthenticator()).grouped(User.guardMiddleware())

Dans le fichier route.swift. Comme sur le cours de Maxime.
ça te permet de lancer les controller sous la ‹ protection › du Middleware du fichier route.
Tu protèges la route, donc je trouve ça assez logique de le mettre dans ce fichier.

@Tazooou,

Je dis juste ça comme ça, mais c’est User.authenticator() et non UserAuthenticator()

Effectivement @ThonyF tu as raison !

Bizarre que dans le premier lien que j’ai donné sur la doc de Vapor, ce ne soit pas avec un « . » (une erreur de la doc peut-être?).
Alors que dans la partie authentification dans la partie Fluent sur Vapor, on a bien le « . »

https://docs.vapor.codes/4.0/authentication/#model-authenticatable

Merci de ta vigilance :wink:

En effet, je me suis fait avoir par la doc … :smiley:

Bon le code a l’air de marcher mais il me convient pas des masses :
On est obligé de repasser sur les anciennes déclarations alors que Vapor recommande de passer par les collections dans son exemple …
Je vais laisser comme ça pour le moment et je vais poursuivre le cours et continuer de parcourir la doc pour voir si je trouve quelque chose de plus propre.

Merci beaucoup pour votre aide !!

func routes(_ app: Application) throws {
    let protected = app.grouped(User.authenticator()).grouped(User.guardMiddleware())
    let userController = UserController()
    protected.post("login", use: userController.login(req:))
    
    try app.register(collection: TodoController())
    
    try app.register(collection: UserController())
}
1 « J'aime »

Je n’ai pas fait de vapor depuis un moment, mais qu’est-ce qui t’empêche de déplacer le code de protection dans ton UserController ?
Ca ressemblerait à ça :

func boot(routes: RoutesBuilder) throws {
    let protected = routes.grouped(User.authenticator()).grouped(User.guardMiddleware())
    protected.post("login", use:login)
}

Comme ça ton routeur ressemblerait à ça :

func routes(_ app: Application) throws {    
    try app.register(collection: TodoController())
    try app.register(collection: UserController())
}

C’est exactement ce que je voulais :slight_smile:
Je ne pensais pas qu’on pouvait substituer le app.
Merci beaucoup pour ton aide !!!

1 « J'aime »