backend: Login/Inscription
This commit is contained in:
		@@ -1,5 +1,10 @@
 | 
				
			|||||||
 | 
					HOST = "http://localhost:8080"
 | 
				
			||||||
OpenWeatherMap_API_KEY = ""
 | 
					OpenWeatherMap_API_KEY = ""
 | 
				
			||||||
DB_HOST = ""
 | 
					DB_HOST = ""
 | 
				
			||||||
DB_NAME = ""
 | 
					DB_NAME = ""
 | 
				
			||||||
DB_USER = ""
 | 
					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('/images', express.static(path.join(__dirname, "assets", "images")));
 | 
				
			||||||
app.use('/functions', require('./routes/functions'));
 | 
					app.use('/functions', require('./routes/functions'));
 | 
				
			||||||
app.use('/categories', require('./routes/categories'));
 | 
					app.use('/categories', require('./routes/categories'));
 | 
				
			||||||
 | 
					app.use('/users', require('./routes/users'));
 | 
				
			||||||
 | 
					app.use('/admin', require('./routes/admin'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Errors Handling */
 | 
					/* Errors Handling */
 | 
				
			||||||
app.use((_req, _res, next) => errorHandling(next, { statusCode: 404, message: "La route n'existe pas!" })); // 404
 | 
					app.use((_req, _res, next) => errorHandling(next, { statusCode: 404, message: "La route n'existe pas!" })); // 404
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
const config = {
 | 
					const config = {
 | 
				
			||||||
    PORT: process.env.PORT || 8080,
 | 
					    PORT: process.env.PORT || 8080,
 | 
				
			||||||
 | 
					    HOST: process.env.HOST,
 | 
				
			||||||
    WEATHER_API_KEY: process.env.OpenWeatherMap_API_KEY,
 | 
					    WEATHER_API_KEY: process.env.OpenWeatherMap_API_KEY,
 | 
				
			||||||
    DATABASE: {
 | 
					    DATABASE: {
 | 
				
			||||||
        host: process.env.DB_HOST,
 | 
					        host: process.env.DB_HOST,
 | 
				
			||||||
@@ -7,6 +8,16 @@ const config = {
 | 
				
			|||||||
        user: process.env.DB_USER,
 | 
					        user: process.env.DB_USER,
 | 
				
			||||||
        password: process.env.DB_PASS
 | 
					        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;
 | 
					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: {
 | 
					    image: {
 | 
				
			||||||
        type: Sequelize.STRING,
 | 
					        type: Sequelize.STRING,
 | 
				
			||||||
        allowNull: false
 | 
					        allowNull: false,
 | 
				
			||||||
 | 
					        defaultValue: "/images/functions/default.png"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    type: {
 | 
					    type: {
 | 
				
			||||||
        type: Sequelize.STRING,
 | 
					        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"
 | 
					        "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": {
 | 
					    "binary-extensions": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
 | 
				
			||||||
@@ -163,6 +168,11 @@
 | 
				
			|||||||
        "fill-range": "^7.0.1"
 | 
					        "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": {
 | 
					    "bytes": {
 | 
				
			||||||
      "version": "3.1.0",
 | 
					      "version": "3.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
 | 
				
			||||||
@@ -410,6 +420,14 @@
 | 
				
			|||||||
      "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
 | 
					      "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
 | 
				
			||||||
      "dev": true
 | 
					      "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": {
 | 
					    "ee-first": {
 | 
				
			||||||
      "version": "1.1.1",
 | 
					      "version": "1.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 | 
				
			||||||
@@ -498,6 +516,22 @@
 | 
				
			|||||||
        "vary": "~1.1.2"
 | 
					        "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": {
 | 
					    "feature-policy": {
 | 
				
			||||||
      "version": "0.3.0",
 | 
					      "version": "0.3.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
 | 
				
			||||||
@@ -873,6 +907,49 @@
 | 
				
			|||||||
      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
 | 
					      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
 | 
				
			||||||
      "dev": true
 | 
					      "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": {
 | 
					    "latest-version": {
 | 
				
			||||||
      "version": "3.1.0",
 | 
					      "version": "3.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
 | 
					      "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",
 | 
					      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
 | 
				
			||||||
      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
 | 
					      "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": {
 | 
					    "long": {
 | 
				
			||||||
      "version": "4.0.0",
 | 
					      "version": "4.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
 | 
					      "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",
 | 
					      "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
 | 
					      "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": {
 | 
					    "nodemon": {
 | 
				
			||||||
      "version": "2.0.2",
 | 
					      "version": "2.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
 | 
				
			||||||
@@ -1303,8 +1420,7 @@
 | 
				
			|||||||
    "semver": {
 | 
					    "semver": {
 | 
				
			||||||
      "version": "5.7.1",
 | 
					      "version": "5.7.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
 | 
					      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "semver-diff": {
 | 
					    "semver-diff": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
@@ -1386,6 +1502,11 @@
 | 
				
			|||||||
          "version": "6.3.0",
 | 
					          "version": "6.3.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
 | 
				
			||||||
          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
 | 
					          "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",
 | 
					          "version": "2.1.2",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 | 
				
			||||||
          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 | 
					          "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="
 | 
					      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "uuid": {
 | 
					    "uuid": {
 | 
				
			||||||
      "version": "3.4.0",
 | 
					      "version": "7.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
 | 
					      "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "validator": {
 | 
					    "validator": {
 | 
				
			||||||
      "version": "10.11.0",
 | 
					      "version": "10.11.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,13 +11,18 @@
 | 
				
			|||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "axios": "^0.19.2",
 | 
					    "axios": "^0.19.2",
 | 
				
			||||||
 | 
					    "bcryptjs": "^2.4.3",
 | 
				
			||||||
    "cors": "^2.8.5",
 | 
					    "cors": "^2.8.5",
 | 
				
			||||||
    "express": "^4.17.1",
 | 
					    "express": "^4.17.1",
 | 
				
			||||||
 | 
					    "express-validator": "^6.4.0",
 | 
				
			||||||
    "helmet": "^3.21.3",
 | 
					    "helmet": "^3.21.3",
 | 
				
			||||||
 | 
					    "jsonwebtoken": "^8.5.1",
 | 
				
			||||||
    "moment": "^2.24.0",
 | 
					    "moment": "^2.24.0",
 | 
				
			||||||
    "mysql2": "^2.1.0",
 | 
					    "mysql2": "^2.1.0",
 | 
				
			||||||
 | 
					    "nodemailer": "^6.4.6",
 | 
				
			||||||
    "sequelize": "^5.21.5",
 | 
					    "sequelize": "^5.21.5",
 | 
				
			||||||
    "smart-request-balancer": "^2.1.1"
 | 
					    "smart-request-balancer": "^2.1.1",
 | 
				
			||||||
 | 
					    "uuid": "^7.0.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "dotenv": "^8.2.0",
 | 
					    "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