backend: Login/Inscription
This commit is contained in:
parent
84712eb251
commit
2239df70b3
@ -1,5 +1,10 @@
|
||||
HOST = "http://localhost:8080"
|
||||
OpenWeatherMap_API_KEY = ""
|
||||
DB_HOST = ""
|
||||
DB_NAME = ""
|
||||
DB_USER = ""
|
||||
DB_PASS = ""
|
||||
DB_PASS = ""
|
||||
JWT_SECRET = ""
|
||||
EMAIL_HOST = ""
|
||||
EMAIL_USER = ""
|
||||
EMAIL_PASSWORD = ""
|
@ -22,6 +22,8 @@ app.use(express.json());
|
||||
app.use('/images', express.static(path.join(__dirname, "assets", "images")));
|
||||
app.use('/functions', require('./routes/functions'));
|
||||
app.use('/categories', require('./routes/categories'));
|
||||
app.use('/users', require('./routes/users'));
|
||||
app.use('/admin', require('./routes/admin'));
|
||||
|
||||
/* Errors Handling */
|
||||
app.use((_req, _res, next) => errorHandling(next, { statusCode: 404, message: "La route n'existe pas!" })); // 404
|
||||
|
@ -1,5 +1,6 @@
|
||||
const config = {
|
||||
PORT: process.env.PORT || 8080,
|
||||
HOST: process.env.HOST,
|
||||
WEATHER_API_KEY: process.env.OpenWeatherMap_API_KEY,
|
||||
DATABASE: {
|
||||
host: process.env.DB_HOST,
|
||||
@ -7,6 +8,16 @@ const config = {
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASS
|
||||
},
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
EMAIL_INFO: {
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: 465,
|
||||
secure: true, // true for 465, false for other ports
|
||||
auth: {
|
||||
user: process.env.EMAIL_USER,
|
||||
pass: process.env.EMAIL_PASSWORD
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = config;
|
53
api/assets/config/emails.js
Normal file
53
api/assets/config/emails.js
Normal file
@ -0,0 +1,53 @@
|
||||
exports.signupEmail = (url) => `
|
||||
<center>
|
||||
<table border="0" cellpadding="20" cellspacing="0" height="100%" width="100%" style="background-color:#eeeeee">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width:600px;border-radius:6px;background-color:none">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width:600px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<h1 style="font-family:Arial, Helvetica, sans-serif;font-size:28px;line-height:110%;margin-bottom:30px;margin-top:0;padding:0">FunctionProject</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width:600px;border-radius:6px;background-color:#ffffff">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" valign="top" style="line-height:150%;font-family:Helvetica;font-size:14px;color:#333333;padding:20px">
|
||||
<h2 style="font-size:22px;line-height:28px;margin:0 0 12px 0">
|
||||
Veuillez confirmer l'inscription
|
||||
</h2>
|
||||
<a href="${url}" style="color:#ffffff!important;display:inline-block;font-weight:500;font-size:16px;line-height:42px;font-family:'Helvetica',Arial,sans-serif;width:auto;white-space:nowrap;height:42px;margin:12px 5px 12px 0;padding:0 22px;text-decoration:none;text-align:center;border:0;border-radius:3px;vertical-align:top;background-color:#5d5d5d!important" target="_blank" rel="noopener noreferrer"><span
|
||||
style="display:inline;font-family:'Helvetica',Arial,sans-serif;text-decoration:none;font-weight:500;font-style:normal;font-size:16px;line-height:42px;border:none;background-color:#5d5d5d!important;color:#ffffff!important">Oui, je m'inscris.</span></a>
|
||||
<br>
|
||||
<div>
|
||||
<p style="padding:0 0 10px 0">Si vous avez reçu ce message
|
||||
par erreur, il suffit de le supprimer. Vous ne serez pas
|
||||
inscrit si vous ne cliquez pas sur le lien de
|
||||
confirmation ci-dessus.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</center>
|
||||
`;
|
6
api/assets/config/transporter.js
Normal file
6
api/assets/config/transporter.js
Normal file
@ -0,0 +1,6 @@
|
||||
const nodemailer = require('nodemailer');
|
||||
const { EMAIL_INFO } = require('./config');
|
||||
|
||||
const transporter = nodemailer.createTransport(EMAIL_INFO);
|
||||
|
||||
module.exports = transporter;
|
BIN
api/assets/images/functions/default.png
Normal file
BIN
api/assets/images/functions/default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
api/assets/images/users/default.png
Normal file
BIN
api/assets/images/users/default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
8
api/controllers/admin.js
Normal file
8
api/controllers/admin.js
Normal file
@ -0,0 +1,8 @@
|
||||
const errorHandling = require('../assets/utils/errorHandling');
|
||||
const { serverError } = require('../assets/config/errors');
|
||||
const Users = require('../models/users');
|
||||
|
||||
exports.postFunction = (req, res, next) => {
|
||||
// TODO: Pouvoir créé une fonction
|
||||
res.status(200).json({ message: "test"});
|
||||
}
|
75
api/controllers/users.js
Normal file
75
api/controllers/users.js
Normal file
@ -0,0 +1,75 @@
|
||||
const { validationResult } = require('express-validator');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const uuid = require('uuid');
|
||||
const errorHandling = require('../assets/utils/errorHandling');
|
||||
const { serverError, generalError } = require('../assets/config/errors');
|
||||
const { JWT_SECRET } = require('../assets/config/config');
|
||||
const transporter = require('../assets/config/transporter');
|
||||
const { EMAIL_INFO, HOST } = require('../assets/config/config');
|
||||
const { signupEmail } = require('../assets/config/emails');
|
||||
const Users = require('../models/users');
|
||||
|
||||
exports.signup = async (req, res, next) => {
|
||||
const { name, email, password } = req.body;
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||
}
|
||||
try {
|
||||
const hashedPassword = await bcrypt.hash(password, 12);
|
||||
const tempToken = uuid.v4();
|
||||
await Users.create({ email, name, password: hashedPassword, tempToken });
|
||||
await transporter.sendMail({
|
||||
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
||||
to: email,
|
||||
subject: "FunctionProject - Confirmer l'inscription",
|
||||
html: signupEmail(`${HOST}/users/confirm-email/${tempToken}`)
|
||||
});
|
||||
return res.status(201).json({ result: "Vous y êtes presque, veuillez vérifier votre boite d'emails pour confirmer l'inscription." });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
errorHandling(next, serverError);
|
||||
}
|
||||
}
|
||||
|
||||
exports.login = async (req, res, next) => {
|
||||
const { email, password } = req.body;
|
||||
try {
|
||||
const user = await Users.findOne({ where: { email, confirmed: true } });
|
||||
if (!user) {
|
||||
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 400 });
|
||||
}
|
||||
const isEqual = await bcrypt.compare(password, user.password);
|
||||
if (!isEqual) {
|
||||
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 400 });
|
||||
}
|
||||
const token = jwt.sign({
|
||||
email: user.email, userId: user.id
|
||||
}, JWT_SECRET, { expiresIn: '1h' });
|
||||
return res.status(200).json({ token, id: user.id, name: user.name, email: user.email, logo: user.logo, isAdmin: user.isAdmin, createdAt: user.createdAt });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
errorHandling(next, serverError);
|
||||
}
|
||||
}
|
||||
|
||||
exports.confirmEmail = async (req, res, next) => {
|
||||
const { tempToken } = req.params;
|
||||
if (!tempToken) {
|
||||
return errorHandling(next, generalError);
|
||||
}
|
||||
try {
|
||||
const user = await Users.findOne({ where: { tempToken, isConfirmed: false } });
|
||||
if (!user) {
|
||||
return errorHandling(next, { message: "Le token n'est pas valide.", statusCode: 400 });
|
||||
}
|
||||
user.tempToken = null;
|
||||
user.isConfirmed = true;
|
||||
await user.save();
|
||||
return res.redirect('https://function.divlo.fr');
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
errorHandling(next, serverError);
|
||||
}
|
||||
}
|
23
api/middlewares/isAdmin.js
Normal file
23
api/middlewares/isAdmin.js
Normal file
@ -0,0 +1,23 @@
|
||||
const errorHandling = require('../assets/utils/errorHandling');
|
||||
const { serverError } = require('../assets/config/errors');
|
||||
const Users = require('../models/users');
|
||||
|
||||
module.exports = (req, _res, next) => {
|
||||
if (!req.userId) {
|
||||
return errorHandling(next, { message: "Vous n'êtes pas connecté.", statusCode: 401 });
|
||||
}
|
||||
Users.findOne({ where: { id: req.userId } })
|
||||
.then((user) => {
|
||||
if (!user) {
|
||||
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 400 });
|
||||
}
|
||||
if (!user.isAdmin) {
|
||||
return errorHandling(next, { message: "Vous n'êtes pas administrateur.", statusCode: 400 });
|
||||
}
|
||||
next();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
errorHandling(next, serverError);
|
||||
});
|
||||
}
|
25
api/middlewares/isAuth.js
Normal file
25
api/middlewares/isAuth.js
Normal file
@ -0,0 +1,25 @@
|
||||
const jwt = require('jsonwebtoken');
|
||||
const errorHandling = require('../assets/utils/errorHandling');
|
||||
const { serverError } = require('../assets/config/errors');
|
||||
const { JWT_SECRET } = require('../assets/config/config');
|
||||
|
||||
module.exports = (req, _res, next) => {
|
||||
const token = req.get('Authorization');
|
||||
if (!token) {
|
||||
return errorHandling(next, { message: "Vous n'êtes pas connecté.", statusCode: 401 });
|
||||
}
|
||||
|
||||
let decodedToken;
|
||||
try {
|
||||
decodedToken = jwt.verify(token, JWT_SECRET);
|
||||
} catch (error) {
|
||||
return errorHandling(next, serverError);
|
||||
}
|
||||
|
||||
if (!decodedToken) {
|
||||
return errorHandling(next, { message: "Vous n'êtes pas connecté.", statusCode: 401 });
|
||||
}
|
||||
|
||||
req.userId = decodedToken.userId;
|
||||
next();
|
||||
}
|
@ -22,7 +22,8 @@ module.exports = sequelize.define('function', {
|
||||
},
|
||||
image: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false
|
||||
allowNull: false,
|
||||
defaultValue: "/images/functions/default.png"
|
||||
},
|
||||
type: {
|
||||
type: Sequelize.STRING,
|
||||
|
50
api/models/users.js
Normal file
50
api/models/users.js
Normal file
@ -0,0 +1,50 @@
|
||||
const Sequelize = require('sequelize');
|
||||
const sequelize = require('../assets/utils/database');
|
||||
|
||||
module.exports = sequelize.define('user', {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
autoIncrement: true,
|
||||
primaryKey: true
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
email: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
password: {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
biography: {
|
||||
type: Sequelize.TEXT,
|
||||
},
|
||||
logo: {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: "/images/users/default.png"
|
||||
},
|
||||
isConfirmed: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
isPublicEmail: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
isAdmin: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
tempToken: {
|
||||
type: Sequelize.TEXT,
|
||||
allowNull: true
|
||||
},
|
||||
tempExpirationToken: {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
}
|
||||
});
|
136
api/package-lock.json
generated
136
api/package-lock.json
generated
@ -96,6 +96,11 @@
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"bcryptjs": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
|
||||
"integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
||||
@ -163,6 +168,11 @@
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
@ -410,6 +420,14 @@
|
||||
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
|
||||
"dev": true
|
||||
},
|
||||
"ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
@ -498,6 +516,22 @@
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"express-validator": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.4.0.tgz",
|
||||
"integrity": "sha512-Fs+x0yDOSiUV+o5jIRloMyBxqpSzJiMM8KQW1IRVv2l49F6ATU0F9uPa+3K6vXNlLlhUjauv2FCGLFPMaNr24w==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.15",
|
||||
"validator": "^12.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"validator": {
|
||||
"version": "12.2.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz",
|
||||
"integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"feature-policy": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
|
||||
@ -873,6 +907,49 @@
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"jsonwebtoken": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
|
||||
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
|
||||
"requires": {
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
"lodash.isboolean": "^3.0.3",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
"lodash.isnumber": "^3.0.3",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.once": "^4.0.0",
|
||||
"ms": "^2.1.1",
|
||||
"semver": "^5.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"jwa": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||
"requires": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"jws": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||
"requires": {
|
||||
"jwa": "^1.4.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"latest-version": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
|
||||
@ -887,6 +964,41 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
},
|
||||
"lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
|
||||
},
|
||||
"lodash.isboolean": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
|
||||
},
|
||||
"lodash.isinteger": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
|
||||
},
|
||||
"lodash.isnumber": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
|
||||
},
|
||||
"lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
|
||||
},
|
||||
"lodash.isstring": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
|
||||
},
|
||||
"lodash.once": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
@ -1052,6 +1164,11 @@
|
||||
"resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
|
||||
"integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
|
||||
},
|
||||
"nodemailer": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz",
|
||||
"integrity": "sha512-/kJ+FYVEm2HuUlw87hjSqTss+GU35D4giOpdSfGp7DO+5h6RlJj7R94YaYHOkoxu1CSaM0d3WRBtCzwXrY6MKA=="
|
||||
},
|
||||
"nodemon": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
|
||||
@ -1303,8 +1420,7 @@
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
},
|
||||
"semver-diff": {
|
||||
"version": "2.1.0",
|
||||
@ -1386,6 +1502,11 @@
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1457,6 +1578,11 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1624,9 +1750,9 @@
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz",
|
||||
"integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
|
@ -11,13 +11,18 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"express-validator": "^6.4.0",
|
||||
"helmet": "^3.21.3",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"moment": "^2.24.0",
|
||||
"mysql2": "^2.1.0",
|
||||
"nodemailer": "^6.4.6",
|
||||
"sequelize": "^5.21.5",
|
||||
"smart-request-balancer": "^2.1.1"
|
||||
"smart-request-balancer": "^2.1.1",
|
||||
"uuid": "^7.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dotenv": "^8.2.0",
|
||||
|
11
api/routes/admin.js
Normal file
11
api/routes/admin.js
Normal file
@ -0,0 +1,11 @@
|
||||
const { Router } = require('express');
|
||||
const adminController = require('../controllers/admin');
|
||||
const isAuth = require('../middlewares/isAuth');
|
||||
const isAdmin = require('../middlewares/isAdmin');
|
||||
|
||||
const AdminRouter = Router();
|
||||
|
||||
// Permet de créé une fonction
|
||||
AdminRouter.post('/functions', isAuth, isAdmin, adminController.postFunction);
|
||||
|
||||
module.exports = AdminRouter;
|
52
api/routes/users.js
Normal file
52
api/routes/users.js
Normal file
@ -0,0 +1,52 @@
|
||||
const { Router } = require('express');
|
||||
const { body } = require('express-validator');
|
||||
const usersController = require('../controllers/users');
|
||||
const Users = require('../models/users');
|
||||
|
||||
const UsersRouter = Router();
|
||||
|
||||
// Permet de se connecter
|
||||
UsersRouter.post('/login', usersController.login);
|
||||
|
||||
// Permet de s'inscrire
|
||||
UsersRouter.post('/signup', [
|
||||
body('email')
|
||||
.isEmail()
|
||||
.withMessage("Veuillez rentré une adresse mail valide.")
|
||||
.custom((async (email) => {
|
||||
try {
|
||||
const user = await Users.findOne({ where: { email } });
|
||||
if (user) {
|
||||
return Promise.reject("L'adresse email existe déjà...");
|
||||
}
|
||||
} catch (error) {
|
||||
return console.log(error);
|
||||
}
|
||||
}))
|
||||
.normalizeEmail(),
|
||||
body('password')
|
||||
.isLength({ min: 4 })
|
||||
.withMessage("Votre mot de passe est trop court!"),
|
||||
body('name')
|
||||
.trim()
|
||||
.not()
|
||||
.isEmpty()
|
||||
.withMessage("Votre nom ne peut pas être vide.")
|
||||
.isAlphanumeric()
|
||||
.withMessage("Votre nom ne peut contenir que des lettres ou/et des nombres.")
|
||||
.custom((async (name) => {
|
||||
try {
|
||||
const user = await Users.findOne({ where: { name } });
|
||||
if (user) {
|
||||
return Promise.reject("Le nom existe déjà...");
|
||||
}
|
||||
} catch (error) {
|
||||
return console.log(error);
|
||||
}
|
||||
}))
|
||||
], usersController.signup);
|
||||
|
||||
// Confirme l'inscription
|
||||
UsersRouter.get('/confirm-email/:tempToken', usersController.confirmEmail);
|
||||
|
||||
module.exports = UsersRouter;
|
Reference in New Issue
Block a user