bv-express 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +5 -0
- package/README.md +140 -0
- package/index.js +1 -0
- package/jest.config.js +0 -0
- package/package.json +36 -0
- package/src/app.js +78 -0
- package/src/config/db.js +11 -0
- package/src/middlewares/authMiddleware.js +27 -0
- package/src/middlewares/logger.js +6 -0
- package/src/middlewares/roleMiddleware.js +9 -0
- package/src/server.js +8 -0
- package/src/v1/controllers/authController.js +64 -0
- package/src/v1/controllers/userController.js +34 -0
- package/src/v1/models/userModel.js +34 -0
- package/src/v1/routes/authRoutes.js +56 -0
- package/src/v1/routes/userRoutes.js +49 -0
- package/tests/auth.test.js +52 -0
package/.env.example
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# đïž BV Express
|
|
2
|
+
|
|
3
|
+
API Express avec l'intégration du builder bvbuilder
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## đ Table des matiĂšres
|
|
8
|
+
|
|
9
|
+
- [Installation & Configuration](#-installation--configuration)
|
|
10
|
+
- [Lancement du Projet](#-lancement-du-projet)
|
|
11
|
+
- [Fonctionnalités Principales](#-fonctionnalités-principales)
|
|
12
|
+
- [Documentation API](#-documentation-api-swagger)
|
|
13
|
+
- [Tests](#-tests)
|
|
14
|
+
- [Structure du Projet](#-structure-du-projet)
|
|
15
|
+
- [Technologies Utilisées](#-technologies-utilisées)
|
|
16
|
+
- [Contribution](#-contribution)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## đ Installation & Configuration
|
|
21
|
+
|
|
22
|
+
### Prérequis
|
|
23
|
+
|
|
24
|
+
- Node.js (version 14 ou supérieure)
|
|
25
|
+
- npm
|
|
26
|
+
- Mysql
|
|
27
|
+
|
|
28
|
+
### Installation des dépendances
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Configuration des variables d'environnement
|
|
35
|
+
|
|
36
|
+
Le projet nécessite un fichier `.env` pour fonctionner correctement .
|
|
37
|
+
|
|
38
|
+
1. Copiez le fichier d'exemple :
|
|
39
|
+
```bash
|
|
40
|
+
cp .env.example .env
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. Ăditez le fichier `.env` avec vos propres paramĂštres :
|
|
44
|
+
```env
|
|
45
|
+
# Exemple de configuration
|
|
46
|
+
PORT=3000
|
|
47
|
+
DB_HOST=localhost
|
|
48
|
+
DB_USER=
|
|
49
|
+
DB_PASS=
|
|
50
|
+
DB_NAME=moto
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## đ Lancement du Projet
|
|
56
|
+
|
|
57
|
+
### Mode Développement
|
|
58
|
+
Avec rechargement automatique Ă chaque modification :
|
|
59
|
+
```bash
|
|
60
|
+
npm run dev
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Mode Production
|
|
64
|
+
```bash
|
|
65
|
+
npm start
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
L'API sera accessible par défaut sur `http://localhost:3000`
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ⚠Fonctionnalités Principales
|
|
73
|
+
|
|
74
|
+
- ** Authentification JWT** : Sécurisation des accÚs par jeton JSON Web Token
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## đ Documentation API (Swagger)
|
|
78
|
+
|
|
79
|
+
Accédez à la documentation interactive pour tester les endpoints et consulter les schémas de données :
|
|
80
|
+
|
|
81
|
+
đ **[http://localhost:3000/api-docs](http://localhost:3000/api-docs)**
|
|
82
|
+
|
|
83
|
+
La documentation Swagger vous permet de :
|
|
84
|
+
- Visualiser tous les endpoints disponibles
|
|
85
|
+
- Tester les requĂȘtes directement depuis l'interface
|
|
86
|
+
- Consulter les schĂ©mas de requĂȘte et de rĂ©ponse
|
|
87
|
+
- Voir les codes de statut et messages d'erreur
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## đ§Ș Tests
|
|
92
|
+
|
|
93
|
+
Le projet intÚgre des tests unitaires pour garantir la fiabilité des fonctionnalités :
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm test
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Pour exécuter les tests avec la couverture de code :
|
|
100
|
+
```bash
|
|
101
|
+
npm run test:coverage
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## đ Structure du Projet
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
bbv-express/
|
|
110
|
+
âââ src/
|
|
111
|
+
â âââ controllers/ # Logique mĂ©tier des routes
|
|
112
|
+
â âââ models/ # ModĂšles de donnĂ©es
|
|
113
|
+
â âââ routes/ # DĂ©finition des routes API
|
|
114
|
+
â âââ middlewares/ # Middlewares (auth, validation, etc.)
|
|
115
|
+
â âââ config/ # Configuration de l'application
|
|
116
|
+
âââ tests/ # Tests unitaires et d'intĂ©gration
|
|
117
|
+
âââ .env # Configuration
|
|
118
|
+
âââ .env.example # Exemple de configuration
|
|
119
|
+
âââ .gitignore
|
|
120
|
+
âââ package.json
|
|
121
|
+
âââ README.md
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## đ ïž Technologies UtilisĂ©es
|
|
127
|
+
|
|
128
|
+
- **Node.js** - Environnement d'exécution JavaScript
|
|
129
|
+
- **Bvbuilder** - Permet de build, model,controller, route et table via commande
|
|
130
|
+
- **Express.js** - Framework web minimaliste
|
|
131
|
+
- **MySql** - Base de données SQL
|
|
132
|
+
- **JWT** - Authentification par jetons
|
|
133
|
+
- **Swagger** - Documentation API interactive
|
|
134
|
+
- **Jest** - Framework de tests
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## đ§ Contact
|
|
139
|
+
|
|
140
|
+
Pour toute question ou suggestion, n'hésitez pas à me contacter.
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('Happy developing âš')
|
package/jest.config.js
ADDED
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bv-express",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node src/server.js",
|
|
8
|
+
"dev": "nodemon src/server.js",
|
|
9
|
+
"test": "jest --watchAll --verbose"
|
|
10
|
+
},
|
|
11
|
+
"private": false,
|
|
12
|
+
"keywords": [],
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"type": "commonjs",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/Xenozn/bv-express.git"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"bcryptjs": "^3.0.3",
|
|
22
|
+
"cors": "^2.8.5",
|
|
23
|
+
"dotenv": "^17.2.3",
|
|
24
|
+
"express": "^5.2.1",
|
|
25
|
+
"jsonwebtoken": "^9.0.3",
|
|
26
|
+
"mysql2": "^3.16.0",
|
|
27
|
+
"swagger-jsdoc": "^6.2.8",
|
|
28
|
+
"swagger-ui-express": "^5.0.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"bvbuilder": "^1.0.2",
|
|
32
|
+
"jest": "^30.2.0",
|
|
33
|
+
"nodemon": "^3.1.11",
|
|
34
|
+
"supertest": "^7.2.2"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/app.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
require('dotenv').config();
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('node:fs'); // Ajouté pour lire les dossiers
|
|
5
|
+
|
|
6
|
+
const logger = require('./middlewares/logger');
|
|
7
|
+
const swaggerUi = require('swagger-ui-express');
|
|
8
|
+
const swaggerJsdoc = require('swagger-jsdoc');
|
|
9
|
+
|
|
10
|
+
const app = express();
|
|
11
|
+
|
|
12
|
+
// --- CONFIGURATION SWAGGER ---
|
|
13
|
+
const swaggerOptions = {
|
|
14
|
+
definition: {
|
|
15
|
+
openapi: '3.0.0',
|
|
16
|
+
info: {
|
|
17
|
+
title: 'BV Express API Documentation',
|
|
18
|
+
version: '1.0.0',
|
|
19
|
+
description: 'Documentation interactive de mon API',
|
|
20
|
+
},
|
|
21
|
+
servers: [{ url: 'http://localhost:3000' }],
|
|
22
|
+
|
|
23
|
+
components: {
|
|
24
|
+
securitySchemes: {
|
|
25
|
+
bearerAuth: {
|
|
26
|
+
type: 'http',
|
|
27
|
+
scheme: 'bearer',
|
|
28
|
+
bearerFormat: 'JWT',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
security: [
|
|
34
|
+
{
|
|
35
|
+
bearerAuth: [],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
apis: [path.join(__dirname, './v*/routes/*.js')],
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const swaggerDocs = swaggerJsdoc(swaggerOptions);
|
|
44
|
+
|
|
45
|
+
// --- MIDDLEWARES ---
|
|
46
|
+
app.use(express.json());
|
|
47
|
+
app.use(logger);
|
|
48
|
+
|
|
49
|
+
// --- CHARGEMENT AUTOMATIQUE DES ROUTES ---
|
|
50
|
+
const versions = fs.readdirSync(__dirname).filter(file => {
|
|
51
|
+
const filePath = path.join(__dirname, file);
|
|
52
|
+
return fs.statSync(filePath).isDirectory() && /^v\d+$/.test(file);
|
|
53
|
+
});
|
|
54
|
+
// Dans ton app.js, remplace la boucle par celle-ci :
|
|
55
|
+
versions.forEach(version => {
|
|
56
|
+
const routesPath = path.join(__dirname, version, 'routes');
|
|
57
|
+
|
|
58
|
+
if (fs.existsSync(routesPath)) {
|
|
59
|
+
fs.readdirSync(routesPath).forEach(file => {
|
|
60
|
+
if (!file.endsWith('.js')) return;
|
|
61
|
+
|
|
62
|
+
let routeName = file.replace('Routes.js', '').toLowerCase();
|
|
63
|
+
if (routeName !== 'auth' && !routeName.endsWith('s')) {
|
|
64
|
+
routeName += 's';
|
|
65
|
+
}
|
|
66
|
+
const route = require(`./${version}/routes/${file}`);
|
|
67
|
+
app.use(`/api/${version}/${routeName}`, route);
|
|
68
|
+
|
|
69
|
+
console.log(`â
Route chargée : /api/${version}/${routeName}`);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// --- DOCS ---
|
|
76
|
+
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
|
|
77
|
+
|
|
78
|
+
module.exports = app;
|
package/src/config/db.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const mysql = require('mysql2');
|
|
2
|
+
require('dotenv').config();
|
|
3
|
+
|
|
4
|
+
const pool = mysql.createPool({
|
|
5
|
+
host: process.env.DB_HOST,
|
|
6
|
+
user: process.env.DB_USER,
|
|
7
|
+
password: process.env.DB_PASS,
|
|
8
|
+
database: process.env.DB_NAME
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
module.exports = pool.promise();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
|
2
|
+
const authMiddleware = (req, res, next) => {
|
|
3
|
+
const token = req.headers['authorization']?.split(' ')[1];
|
|
4
|
+
|
|
5
|
+
if (!token) {
|
|
6
|
+
return res.status(403).json({ message: "Token requis" });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const decoded = jwt.verify(
|
|
11
|
+
token,
|
|
12
|
+
process.env.JWT_SECRET || 'secret_par_defaut'
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
req.userId = decoded.id;
|
|
16
|
+
req.userRole = decoded.role;
|
|
17
|
+
|
|
18
|
+
next();
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('JWT error details:', error);
|
|
21
|
+
return res.status(401).json({
|
|
22
|
+
message: "Token invalide",
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
module.exports = authMiddleware;
|
package/src/server.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const User = require('../models/userModel'); // Import du modĂšle
|
|
2
|
+
const bcrypt = require('bcryptjs');
|
|
3
|
+
const jwt = require('jsonwebtoken');
|
|
4
|
+
|
|
5
|
+
// --- REGISTER ---
|
|
6
|
+
exports.register = async (req, res) => {
|
|
7
|
+
const { email, password, nom, prenom } = req.body;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const existingUser = await User.findByEmail(email);
|
|
11
|
+
if (existingUser) {
|
|
12
|
+
return res.status(400).json({ message: "Utilisateur déjà existant" });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
16
|
+
const forcedRole = 'user';
|
|
17
|
+
|
|
18
|
+
const userId = await User.create({
|
|
19
|
+
email,
|
|
20
|
+
password: hashedPassword,
|
|
21
|
+
nom,
|
|
22
|
+
prenom,
|
|
23
|
+
role: forcedRole
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
res.status(201).json({
|
|
27
|
+
message: "Utilisateur créé !",
|
|
28
|
+
user: { id: userId, email, nom, prenom, role: forcedRole }
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
} catch (error) {
|
|
32
|
+
res.status(500).json({ status: "error", message: error.message });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// --- LOGIN ---
|
|
37
|
+
exports.login = async (req, res) => {
|
|
38
|
+
const { email, password } = req.body;
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const user = await User.findByEmail(email);
|
|
42
|
+
|
|
43
|
+
if (!user || !(await bcrypt.compare(password, user.password))) {
|
|
44
|
+
return res.status(401).json({ message: "Identifiants invalides" });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const token = jwt.sign(
|
|
48
|
+
{ id: user.id, role: user.role },
|
|
49
|
+
process.env.JWT_SECRET || 'secret_par_defaut',
|
|
50
|
+
{ expiresIn: '1h' }
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const { password: _, ...userWithoutPassword } = user;
|
|
54
|
+
|
|
55
|
+
res.json({
|
|
56
|
+
message: "Connecté !",
|
|
57
|
+
token,
|
|
58
|
+
user: userWithoutPassword
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
} catch (error) {
|
|
62
|
+
res.status(500).json({ status: "error", message: error.message });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const User = require('../models/userModel');
|
|
2
|
+
|
|
3
|
+
// --- RĂCUPĂRER MON PROFIL (Via Token) ---
|
|
4
|
+
exports.getMe = async (req, res) => {
|
|
5
|
+
try {
|
|
6
|
+
// req.userId est injecté par votre authMiddleware
|
|
7
|
+
const user = await User.findById(req.userId);
|
|
8
|
+
|
|
9
|
+
if (!user) {
|
|
10
|
+
return res.status(404).json({ message: "Utilisateur non trouvé" });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
res.json({ status: "success", data: user });
|
|
14
|
+
} catch (error) {
|
|
15
|
+
res.status(500).json({ status: "error", message: error.message });
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// --- RĂCUPĂRER UN UTILISATEUR PAR ID (ParamĂštre URL) ---
|
|
20
|
+
exports.getUserById = async (req, res) => {
|
|
21
|
+
const { id } = req.params;
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const user = await User.findById(id);
|
|
25
|
+
|
|
26
|
+
if (!user) {
|
|
27
|
+
return res.status(404).json({ message: "Utilisateur non trouvé" });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
res.json({ status: "success", data: user });
|
|
31
|
+
} catch (error) {
|
|
32
|
+
res.status(500).json({ status: "error", message: error.message });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const db = require('../../config/db');
|
|
2
|
+
|
|
3
|
+
const User = {
|
|
4
|
+
// Trouver un utilisateur par son email
|
|
5
|
+
findByEmail: async (email) => {
|
|
6
|
+
const [rows] = await db.query('SELECT * FROM users WHERE email = ?', [email]);
|
|
7
|
+
return rows[0];
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
// Créer un nouvel utilisateur
|
|
11
|
+
create: async (userData) => {
|
|
12
|
+
const { email, password, nom, prenom, role } = userData;
|
|
13
|
+
const [result] = await db.query(
|
|
14
|
+
'INSERT INTO users (email, password, nom, prenom, role) VALUES (?, ?, ?, ?, ?)',
|
|
15
|
+
[email, password, nom, prenom, role]
|
|
16
|
+
);
|
|
17
|
+
return result.insertId;
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
findById: async (id) => {
|
|
21
|
+
const [rows] = await db.query(
|
|
22
|
+
'SELECT id, email, nom, prenom, role, createdAt FROM users WHERE id = ?',
|
|
23
|
+
[id]
|
|
24
|
+
);
|
|
25
|
+
return rows[0]; // Retourne l'utilisateur ou undefined
|
|
26
|
+
},
|
|
27
|
+
findAll: async () => {
|
|
28
|
+
const [rows] = await db.query('SELECT id, email, nom, prenom, role, createdAt FROM users');
|
|
29
|
+
return rows;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports = User;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const authController = require('../controllers/authController');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @swagger
|
|
7
|
+
* /api/v1/auth/register:
|
|
8
|
+
* post:
|
|
9
|
+
* summary: Inscrire un utilisateur
|
|
10
|
+
* tags: [Auth]
|
|
11
|
+
* requestBody:
|
|
12
|
+
* required: true
|
|
13
|
+
* content:
|
|
14
|
+
* application/json:
|
|
15
|
+
* schema:
|
|
16
|
+
* type: object
|
|
17
|
+
* properties:
|
|
18
|
+
* email:
|
|
19
|
+
* type: string
|
|
20
|
+
* password:
|
|
21
|
+
* type: string
|
|
22
|
+
* nom:
|
|
23
|
+
* type: string
|
|
24
|
+
* prenom:
|
|
25
|
+
* type: string
|
|
26
|
+
* responses:
|
|
27
|
+
* 201:
|
|
28
|
+
* description: SuccĂšs
|
|
29
|
+
*/
|
|
30
|
+
router.post('/register', authController.register);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @swagger
|
|
34
|
+
* /api/v1/auth/login:
|
|
35
|
+
* post:
|
|
36
|
+
* summary: Se connecter
|
|
37
|
+
* tags: [Auth]
|
|
38
|
+
* requestBody:
|
|
39
|
+
* required: true
|
|
40
|
+
* content:
|
|
41
|
+
* application/json:
|
|
42
|
+
* schema:
|
|
43
|
+
* type: object
|
|
44
|
+
* properties:
|
|
45
|
+
* email:
|
|
46
|
+
* type: string
|
|
47
|
+
* password:
|
|
48
|
+
* type: string
|
|
49
|
+
* responses:
|
|
50
|
+
* 200:
|
|
51
|
+
* description: Connexion réussie
|
|
52
|
+
*/
|
|
53
|
+
router.post('/login', authController.login);
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
module.exports = router;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const userController = require('../controllers/userController');
|
|
4
|
+
const authMiddleware = require('../../middlewares/authMiddleware');
|
|
5
|
+
const { isAdmin } = require('../../middlewares/roleMiddleware');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @swagger
|
|
9
|
+
* /api/v1/users/me:
|
|
10
|
+
* get:
|
|
11
|
+
* summary: Récupérer les informations de l'utilisateur connecté
|
|
12
|
+
* tags: [Users]
|
|
13
|
+
* security:
|
|
14
|
+
* - bearerAuth: []
|
|
15
|
+
* responses:
|
|
16
|
+
* 200:
|
|
17
|
+
* description: Informations de l'utilisateur connecté
|
|
18
|
+
* 401:
|
|
19
|
+
* description: Non authentifié
|
|
20
|
+
*/
|
|
21
|
+
router.get('/me', authMiddleware, userController.getMe);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @swagger
|
|
25
|
+
* /api/v1/users/{id}:
|
|
26
|
+
* get:
|
|
27
|
+
* summary: Récupérer un utilisateur par ID (admin uniquement)
|
|
28
|
+
* tags: [Users]
|
|
29
|
+
* security:
|
|
30
|
+
* - bearerAuth: []
|
|
31
|
+
* parameters:
|
|
32
|
+
* - in: path
|
|
33
|
+
* name: id
|
|
34
|
+
* required: true
|
|
35
|
+
* schema:
|
|
36
|
+
* type: integer
|
|
37
|
+
* responses:
|
|
38
|
+
* 200:
|
|
39
|
+
* description: Utilisateur trouvé
|
|
40
|
+
* 401:
|
|
41
|
+
* description: Non authentifié
|
|
42
|
+
* 403:
|
|
43
|
+
* description: AccÚs refusé (admin requis)
|
|
44
|
+
* 404:
|
|
45
|
+
* description: Utilisateur non trouvé
|
|
46
|
+
*/
|
|
47
|
+
router.get('/:id', authMiddleware, isAdmin, userController.getUserById);
|
|
48
|
+
|
|
49
|
+
module.exports = router;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const request = require('supertest');
|
|
2
|
+
const app = require('../src/app');
|
|
3
|
+
const db = require('../src/config/db');
|
|
4
|
+
const bcrypt = require('bcryptjs');
|
|
5
|
+
|
|
6
|
+
// Mock de la base de données
|
|
7
|
+
jest.mock('../src/config/db');
|
|
8
|
+
|
|
9
|
+
describe('Auth API - Login', () => {
|
|
10
|
+
|
|
11
|
+
it('devrait retourner un token 200 si les identifiants sont corrects', async () => {
|
|
12
|
+
const hashedPassword = await bcrypt.hash('password123', 10);
|
|
13
|
+
const mockUser = {
|
|
14
|
+
id: 1,
|
|
15
|
+
email: 'test@example.com',
|
|
16
|
+
password: hashedPassword,
|
|
17
|
+
nom: 'Test',
|
|
18
|
+
prenom: 'User',
|
|
19
|
+
role: 'user'
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
db.query.mockResolvedValue([[mockUser]]);
|
|
23
|
+
|
|
24
|
+
const res = await request(app)
|
|
25
|
+
.post('/api/v1/auth/login')
|
|
26
|
+
.send({
|
|
27
|
+
email: 'test@example.com',
|
|
28
|
+
password: 'password123'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// 3. Vérifications (Assertions)
|
|
32
|
+
expect(res.statusCode).toEqual(200);
|
|
33
|
+
expect(res.body).toHaveProperty('token');
|
|
34
|
+
expect(res.body.user.email).toBe('test@example.com');
|
|
35
|
+
expect(res.body.message).toBe('Connecté !');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('devrait retourner 401 si le mot de passe est faux', async () => {
|
|
39
|
+
const hashedPassword = await bcrypt.hash('correct_password', 10);
|
|
40
|
+
db.query.mockResolvedValue([[{ email: 'test@example.com', password: hashedPassword }]]);
|
|
41
|
+
|
|
42
|
+
const res = await request(app)
|
|
43
|
+
.post('/api/v1/auth/login')
|
|
44
|
+
.send({
|
|
45
|
+
email: 'test@example.com',
|
|
46
|
+
password: 'wrong_password'
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(res.statusCode).toEqual(401);
|
|
50
|
+
expect(res.body.message).toBe('Identifiants invalides');
|
|
51
|
+
});
|
|
52
|
+
});
|