Bonjour,
Bienvenue dans ce tutoriel pour apprendre à utiliser le framework web Adonis ! Si tu souhaites en savoir plus sur Adonis en 1 coup œil, je t'invite à lire cette page.
Dans cette partie, on va voir le système de routing, de controller
et un moyen pour authentifier l'utilisateur.
Rappel
Ce tutoriel est la partie 3 d'une série de tutoriels qui ont pour objectif de te faire découvrir Adonis au travers la création d'un blog.
Pour lire la partie précédente, c'est là Création d'un utilisateur - Créer un blog avec Adonis
Tu trouveras aussi sur GiHub l'ensemble du code source du projet !
Sommaire
Ce tutoriel est découpé en différente partie pour t'aider et pour éviter d'avoir des articles trop longs où l'on pourrait se perdre !
Nous allons donc voir ensemble :
- Objectifs et mise en route - Créer un blog avec Adonis
- Création d'un utilisateur - Créer un blog avec Adonis
- Création de l'authentification pour l'utilisateur - Créer un blog avec Adonis
- Création et visualisation des articles - Créer un blog avec Adonis
- Gestion des articles - Créer un blog avec Adonis
Finalement, tu auras un blog fonctionnel !
Création de l'authentification
Nous allons voir ensemble comment créer une route avec Adonis puis l'ajout d'un controller
à cette dernière pour faciliter la gestion des fonctionnalités de notre application.
Création d'une route
Pour commencer à créer des routes, rendons-nous dans le fichier start/routes.ts
Dans un premier temps, on va créer la route permettant d'afficher à l'utilisateur le formulaire pour s'authentifier puis dans un second temps, on fera la route qui permet d'authentifier l'utilisateur.
Dans notre fichier, on va commencer par créer la route /login
et s'assurer que tout fonctionne.
Route.get('login', () => {
return 'Bienvenue sur la page de login'
})
Rends-toi à cette adresse et tu vas voir ce message dans ton navigateur ! N'oublie pas de démarrer le serveur !
Super, mais comment on affiche de l'HTML à notre utilisateur ? Pour cela, on va utiliser le template engine edge. Nous allons donc créer une page puis demander au serveur de la générer puis de l'envoyer à l'utilisateur.
Commençons par créer la vue :
node ace make:view login
Un nouveau fichier vient alors de faire son apparition dans ressources/views
. Dans ce fichier, on va y créer un simple formulaire permettant à l'utilisateur de renseigner ses identifiants pour se connecter :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Login</title>
</head>
<body>
<form action="/login" method="post">
<div>
<label for="pseudo">Votre pseudo</label>
<input type="text" name="pseudo" id="pseudo">
</div>
<div>
<label for="password">Votre password</label>
<input type="text" name="password" id="password">
</div>
<button type="submit">Se connecter</button>
</form>
</body>
</html>
L'action de ce formulaire nous indique que la requête sera sur login
et la méthode nous indique POST
. C'est donc comme cela que nous allons devoir définir nos routes !
Ensuite, nous allons indiquer à notre route de rendre cette page puis de la renvoyer à l'utilisateur. Changeons un peu notre code dans le fichier start/routes.ts
:
Route.get('login', ({ view }) => {
return view.render('login')
})
Rends-toi à cette adresse pour visualiser notre formulaire de connexion !
Pour en savoir plus : Routing, Controllers, Edge
Authentifier un utilisateur
Installation du module
Pour commencer à authentifier notre utilisateur, on va devoir installer et configurer un module :
npm i @adonisjs/auth
Puis
node ace configure @adonisjs/auth
On indique que l'on souhaite utiliser Lucid pour trouver les utilisateurs. Ensuite, on va utiliser le web guard pour gérer l'authentification et enfin, on indique User
comme modèle pour l'authentification. Puis on indique ne pas vouloir créer une migration comme cela a déjà été fait dans la partie précédente.
Dans le fichier config/auth.ts
, il faut changer l'uids qui est à email
par pseudo
. En effet, dans la migration de notre utilisateur, nous avons indiqué que le pseudo devait être unique. Cela va permettre de le récupérer en base de données lors de l'authentification.
Authentification
Dans nos routes, nous allons créer une nouvelle route qui correspond à ce que l'on a mis dans le formulaire d'authentification.
Route.post('login',async ({ request, auth, response }) => {
return 'Post sur login'
})
Dans cette fonction, nous allons devoir récupérer de la requête le pseudo et le mot de passe provenant du formulaire. Puis, nous allons devoir authentifier l'utilisateur à l'aide de ses identifiants. Si les identifiants sont bons, alors on redirige l'utilisateur vers la page principale. Cependant, si les identifiants ne sont pas bons, alors on l'indique à l'utilisateur.
On récupère les entrées de l'utilisateur :
const pseudo = request.input('pseudo')
const password = request.input('password')
Ensuite, nous essayons d'authentifier l'utilisateur. Dépendant du résultat, on redirige l'utilisateur sur /
ou il est renvoyé sur la page login
:
try {
await auth.attempt(pseudo, password)
response.redirect('/')
} catch (error) {
response.redirect().back()
}
Rends-toi à cette adresse pour tester ! Pour rappel, notre unique utilisateur a pour pseudo demo
et pour mot de passe azerty
! Tout se passe bien et tu es redirigé sur la page d'accueil. Cependant, si tu commets une erreur délibérée sur le mot de passe, alors rien ne te signale ce qui ne vas pas. Pas pratique !
Aussi, rien ne nous assure que les données entrées par l'utilisateur soient correctes. Ainsi, nous allons vérifier en amont ces données pour nous assurer de leur forme, type, format et intégrité.
Aussi, nous aimerions prévenir l'utilisateur des raisons qui peuvent faire qu'il n'arrive pas à s'authentifier ! Et pour cela, on va utiliser les sessions.
Et pour cela, nous allons utiliser un Validator
.
Validation des entrées
Commençons par créer le validator :
node ace make:validator login
Ensuite, nous allons définir dans ce dernier la structure et le format des données que l'on souhaite avoir :
public schema = schema.create({
pseudo: schema.string({ trim: true }, [
rules.exists({ table: 'users', column: 'pseudo' }),
]),
password: schema.string(),
})
On indique que l'on souhaite une chaine de caractères nommée pseudo
dont la valeur doit correspondre à une des entrées de la table users
de la colonne pseudo
. On indique que l'on souhaite une seconde chaine de caractères nommée password
.
Parfait, essayons à nouveau de nous connecter mais en omettant le pseudo ! On n'est pas authentifié mais rien n'a vraiment changé sur la page pour l'utilisateur ! Et c'est normal ! Il faut maintenant indiquer à notre controller
d'utiliser le validator
:
- const pseudo = request.input('pseudo')
- const password = request.input('password')
---
+ import LoginValidator from 'App/Validators/LoginValidator'
//...
+ const { pseudo, password } = await request.validate(LoginValidator)
Ensuite, nous allons devoir donner à l'utilisateur des indications en fonction des erreurs qu'il commet !
Flash messages
Ce qui est pratique avec le validator
, c'est qu'il gère pour nous les messages d'erreurs. Cependant, nous allons devoir les afficher dans la vue. Pour cela, ouvrons le fichier login.edge
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Login</title>
</head>
<body>
<form action="/login" method="post">
<div>
<label for="pseudo">Votre pseudo</label>
+ <input type="text" name="pseudo" id="pseudo" value="{{ flashMessages.get('pseudo') ?? '' }}">
+ @if(flashMessages.has('errors.pseudo'))
+ <div>{{ flashMessages.get('errors.pseudo') }}</div>
+ @endif
</div>
<div>
<label for="password">Votre password</label>
+ <input type="text" name="password" id="password" value="{{ flashMessages.get('password') ?? '' }}">
+ @if(flashMessages.has('errors.password'))
+ <div>{{ flashMessages.get('errors.password') }}</div>
+ @endif
</div>
<button type="submit">Se connecter</button>
</form>
</body>
</html>
Comme on peut le voir, on ajoute à notre template une div
qui contient le message contenu dans la session via flashMessages
. Cependant, on ne souhaite faire cela que s'il y a un message à afficher, c'est pour cela qu'on entoure cette div
de la condition de présence d'une erreur.
Aussi, on affecte à l'input sa précédente valeur. Cela permet de ne pas vider le formulaire en cas d'erreur de l'utilisateur lorsque nous le redirigeons via la méthode back
.
Mais que faire en cas d'erreur dans l'authentification ? Pour cela, nous allons nous même enregistrer un message flash dans la fonction store
du controller
login
.
try {
await auth.attempt(pseudo, password)
response.redirect('/')
} catch (error) {
+ session.flash('auth', 'Authentication impossible')
response.redirect().back()
}
On crée un nouveau message nommé "auth" qui contient "Authentification impossible".
Pour que l'utilisateur soit en mesure de le voir, il nous faut faire comme dans le fichier login.edge
:
<button type="submit">Se connecter</button>
+@if(flashMessages.has('auth'))
+<div>{{ flashMessages.get('auth') }}</div>
+@endif
Rends-toi à cette adresse pour essayer cela ! N'oublie pas de te tromper pour voir apparaitre les messages !
On remarque cependant que les messages du validator
ne sont pas en français ! Pour les personnaliser, on peut se rendre dans le fichier LoginValidator.ts
:
public messages = {
'pseudo.string': 'Le pseudo doit être une chaîne de caractères',
'pseudo.required': 'Le pseudo est requis',
'pseudo.exists': "Le pseudo n'existe pas",
'password.string': 'Le mot de passe doit être une chaîne de caractères',
'password.required': 'Le mot de passe est requis',
}
Les clés sont une correspondance avec la règle qui est appliquée et la vérification qui est effectuée. Retentons notre formulaire et voilà, les messages sont en français !
Pour en savoir plus : Authentication, Web guard, Validator, Flash, Conditionals
Création des controllers
Les fonctions qui se trouvent après le nom de nos routes dans le fichier start/routes.ts
est en réalité des controllers
. C'est à dire que ces fonctions vont gérer les requêtes des clients. Mais pour simplifier et faire que chaque fichier est son utilité, on préfère les extraire et les mettre dans un fichier à part.
Commençons par créer un controller
:
node ace make:controller login
Ensuite, nous allons devoir migrer nos 2 fonctions dans ce controller
de la ressource login
.
Pour ce faire, commençons par éditer le fichier LoginController.ts
.
Dans une fonction nommée create
, nous allons y mettre la gestion de la vue et dans une fonction nommée store
, nous allons y mettre l'authentification de l'utilisateur. Le choix du nom de ces fonctions n'est pas au hasard et fait partie des conventions utilisées par Adonis, plus de détails ici.
// Gestion de la vue pour l'utilisateur
public async create({ view }: HttpContextContract) {
return view.render('login')
}
// Gestion de l'authentification
public async store({ request, auth, response, session }: HttpContextContract) {
const { pseudo, password } = await request.validate(LoginValidator)
try {
await auth.use('web').attempt(pseudo, password)
response.redirect('/articles')
} catch (error) {
session.flash('auth', 'Authentication impossible')
response.redirect().back()
}
}
Ensuite, nous allons indiquer simplement dans notre fichier de gestion des routes, quel est le controller
qui gère la route. Pour cela, nous allons remplacer nos fonctions par une simple chaine de caractères.
Route.get('login', 'LoginController.create')
Route.post('login', 'LoginController.store')
Cette chaine de caractères indique le nom du controller
à utiliser LoginController
et la fonction à exécuter, create
dans le cas d'une requête de type GET
et store
dans le cas d'une requête POST
.
Pour en savoir plus : Controllers
Conclusion
Et voilà pour cette troisième partie. On a vu la création d'une route, de son controller
associé. On a aussi abordé les notions de vue et d'authentification de l'utilisateur.
Dans la suite, on va commencer à modeler nos articles pour les visionner sur notre blog !
N'hésite pas à commenter si tu as des questions, si ça t'a plus ou même pour me faire des retours !
Et tu peux aussi me retrouver sur Twitter ou sur LinkedIn !
On se donne rendez-vous ici, Création et visualisation des articles - Créer un blog avec Adonis pour la suite du tutoriel et visualiser nos premier articles.
Top comments (0)