312 lines
8.4 KiB
JavaScript
312 lines
8.4 KiB
JavaScript
const express = require("express");
|
|
const { register, login, verifyEmail, verifyCode, forgotPassword, sendPasswordSetupLink, resetPassword, me, changePassword, setInitialPassword, deleteAccount, oauthCallback } = require("../controllers/auth.controller");
|
|
const authMiddleware = require("../middlewares/auth.middleware");
|
|
const validate = require("../middlewares/validate.middleware");
|
|
const verifyCaptcha = require("../middlewares/captcha.middleware");
|
|
const { registerSchema, loginSchema } = require("../validations/auth.validation");
|
|
const { passport, googleEnabled, facebookEnabled } = require("../config/passport");
|
|
const getFrontendUrl = require("../utils/frontendUrl");
|
|
|
|
const router = express.Router();
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/register:
|
|
* post:
|
|
* summary: Inscription d'un utilisateur
|
|
* tags:
|
|
* - Auth
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* firstname:
|
|
* type: string
|
|
* lastname:
|
|
* type: string
|
|
* email:
|
|
* type: string
|
|
* password:
|
|
* type: string
|
|
* responses:
|
|
* 201:
|
|
* description: Utilisateur créé
|
|
*/
|
|
router.post("/register", verifyCaptcha, validate(registerSchema), register);
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/login:
|
|
* post:
|
|
* summary: Connexion utilisateur
|
|
* tags:
|
|
* - Auth
|
|
* requestBody:
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: Connexion réussie
|
|
*/
|
|
|
|
router.post("/login", verifyCaptcha, validate(loginSchema), login);
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/me:
|
|
* get:
|
|
* summary: Informations de l'utilisateur connecté
|
|
* tags:
|
|
* - Auth
|
|
* security:
|
|
* - bearerAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: Profil utilisateur
|
|
*/
|
|
|
|
router.get("/me", authMiddleware, me);
|
|
/**
|
|
* @swagger
|
|
* /api/auth/verify-email/{token}:
|
|
* get:
|
|
* summary: Vérification de l'adresse email
|
|
* tags:
|
|
* - Auth
|
|
* parameters:
|
|
* - in: path
|
|
* name: token
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* description: Token de validation envoyé par email
|
|
* responses:
|
|
* 200:
|
|
* description: Email vérifié avec succès.
|
|
* 400:
|
|
* description: Lien de validation invalide ou expiré.
|
|
* 500:
|
|
* description: Erreur serveur.
|
|
*/
|
|
|
|
router.get("/verify-email/:token",verifyEmail);
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/forgot-password:
|
|
* post:
|
|
* summary: Demande de réinitialisation du mot de passe
|
|
* tags:
|
|
* - Auth
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - email
|
|
* properties:
|
|
* email:
|
|
* type: string
|
|
* format: email
|
|
* example: jean.dupont@gmail.com
|
|
* captchaToken:
|
|
* type: string
|
|
* description: Jeton Cloudflare Turnstile (exigé si TURNSTILE_SECRET_KEY est configurée)
|
|
* responses:
|
|
* 200:
|
|
* description: Si un compte existe avec cet email, un lien de réinitialisation a été envoyé.
|
|
* 400:
|
|
* description: Email requis, ou vérification anti-robot manquante.
|
|
* 500:
|
|
* description: Erreur serveur.
|
|
*/
|
|
|
|
// Page publique : le captcha empêche d'envoyer des emails en masse vers
|
|
// n'importe quelle adresse.
|
|
router.post("/forgot-password", verifyCaptcha, forgotPassword);
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/password-setup-link:
|
|
* post:
|
|
* summary: Envoie à l'utilisateur connecté un lien pour définir son mot de passe
|
|
* tags:
|
|
* - Auth
|
|
* security:
|
|
* - bearerAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: Lien envoyé à l'adresse du compte.
|
|
*/
|
|
router.post("/password-setup-link", authMiddleware, sendPasswordSetupLink);
|
|
/**
|
|
* @swagger
|
|
* /api/auth/reset-password/{token}:
|
|
* post:
|
|
* summary: Réinitialisation du mot de passe
|
|
* tags:
|
|
* - Auth
|
|
* parameters:
|
|
* - in: path
|
|
* name: token
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* description: Token de réinitialisation reçu par email
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - password
|
|
* properties:
|
|
* password:
|
|
* type: string
|
|
* format: password
|
|
* example: NouveauPassword123
|
|
* responses:
|
|
* 200:
|
|
* description: Mot de passe réinitialisé avec succès.
|
|
* 400:
|
|
* description: Lien invalide, expiré ou mot de passe invalide.
|
|
* 500:
|
|
* description: Erreur serveur.
|
|
*/
|
|
router.post("/reset-password/:token", resetPassword);
|
|
|
|
router.post("/verify-code", verifyCode);
|
|
router.patch("/change-password", authMiddleware, changePassword);
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/initial-password:
|
|
* post:
|
|
* summary: Remplace le mot de passe provisoire d'un employé à sa première connexion
|
|
* tags:
|
|
* - Auth
|
|
* security:
|
|
* - bearerAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - password
|
|
* - confirmPassword
|
|
* properties:
|
|
* password:
|
|
* type: string
|
|
* confirmPassword:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: Mot de passe enregistré, l'accès complet est rétabli.
|
|
* 400:
|
|
* description: Mot de passe invalide, non confirmé, identique au provisoire ou déjà défini.
|
|
*/
|
|
router.post("/initial-password", authMiddleware, setInitialPassword);
|
|
router.delete("/account", authMiddleware, deleteAccount);
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/google:
|
|
* get:
|
|
* summary: Démarre la connexion via Google (redirection OAuth 2.0)
|
|
* tags:
|
|
* - Auth
|
|
* responses:
|
|
* 302:
|
|
* description: Redirection vers l'écran de consentement Google.
|
|
* 503:
|
|
* description: Connexion Google non configurée sur ce serveur.
|
|
*/
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/google/callback:
|
|
* get:
|
|
* summary: Retour de Google, émet le JWT et redirige vers le front
|
|
* tags:
|
|
* - Auth
|
|
* responses:
|
|
* 302:
|
|
* description: Redirection vers FRONTEND_URL/auth/callback avec le token.
|
|
*/
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/facebook:
|
|
* get:
|
|
* summary: Démarre la connexion via Facebook (redirection OAuth 2.0)
|
|
* tags:
|
|
* - Auth
|
|
* responses:
|
|
* 302:
|
|
* description: Redirection vers l'écran de consentement Facebook.
|
|
* 503:
|
|
* description: Connexion Facebook non configurée sur ce serveur.
|
|
*/
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/auth/facebook/callback:
|
|
* get:
|
|
* summary: Retour de Facebook, émet le JWT et redirige vers le front
|
|
* tags:
|
|
* - Auth
|
|
* responses:
|
|
* 302:
|
|
* description: Redirection vers FRONTEND_URL/auth/callback avec le token.
|
|
*/
|
|
|
|
function mountOAuthRoutes({ path, strategy, label, enabled, scope }) {
|
|
if (!enabled) {
|
|
// Sans identifiants configurés, on répond explicitement plutôt que de
|
|
// laisser passport planter au démarrage.
|
|
const notConfigured = (req, res) =>
|
|
res.status(503).json({ message: `La connexion ${label} n'est pas configurée sur ce serveur.` });
|
|
|
|
router.get(path, notConfigured);
|
|
router.get(`${path}/callback`, notConfigured);
|
|
return;
|
|
}
|
|
|
|
router.get(path, passport.authenticate(strategy, { scope, session: false }));
|
|
|
|
router.get(
|
|
`${path}/callback`,
|
|
passport.authenticate(strategy, {
|
|
session: false,
|
|
failureRedirect: `${getFrontendUrl()}/auth/callback?error=${encodeURIComponent(
|
|
`Connexion ${label} refusée.`
|
|
)}`,
|
|
}),
|
|
oauthCallback
|
|
);
|
|
}
|
|
|
|
mountOAuthRoutes({
|
|
path: "/google",
|
|
strategy: "google",
|
|
label: "Google",
|
|
enabled: googleEnabled,
|
|
scope: ["profile", "email"],
|
|
});
|
|
|
|
mountOAuthRoutes({
|
|
path: "/facebook",
|
|
strategy: "facebook",
|
|
label: "Facebook",
|
|
enabled: facebookEnabled,
|
|
scope: ["email"],
|
|
});
|
|
|
|
module.exports = router; |