backend: PUT /users - Modifier le profil

This commit is contained in:
Divlo 2020-04-07 16:21:48 +02:00
parent de28cbe706
commit 5bf9a2ade6
6 changed files with 180 additions and 75 deletions

View File

@ -10,7 +10,6 @@ exports.postFunction = (req, res, next) => {
const image = req.files.image; const image = req.files.image;
const errors = validationResult(req); const errors = validationResult(req);
if (!errors.isEmpty()) { if (!errors.isEmpty()) {
console.log(errors.array())
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 }); return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
} }
if (!image || image.truncated && ( if (!image || image.truncated && (
@ -28,7 +27,7 @@ exports.postFunction = (req, res, next) => {
return res.status(201).json({ message: "La fonction a été correctement ajouté!"}); return res.status(201).json({ message: "La fonction a été correctement ajouté!"});
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
}); });
} }
@ -48,6 +47,6 @@ exports.deleteFunction = async (req, res, next) => {
res.status(200).json({ message: "La fonction a été correctement supprimé!"}); res.status(200).json({ message: "La fonction a été correctement supprimé!"});
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }

View File

@ -8,6 +8,6 @@ exports.getCategories = (_req, res, next) => {
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
}); });
} }

View File

@ -37,7 +37,8 @@ exports.getFunctions = (req, res, next) => {
], ],
attributes: { attributes: {
exclude: ["updatedAt", "utilizationForm", "article", "isOnline"] exclude: ["updatedAt", "utilizationForm", "article", "isOnline"]
} },
order: [['createdAt', 'DESC']]
}) })
.then((result) => { .then((result) => {
const { count, rows } = result; const { count, rows } = result;
@ -46,7 +47,7 @@ exports.getFunctions = (req, res, next) => {
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
}); });
} }
@ -69,7 +70,7 @@ exports.getFunctionBySlug = (req, res, next) => {
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
}); });
} }

View File

@ -1,3 +1,4 @@
const path = require('path');
const { validationResult } = require('express-validator'); const { validationResult } = require('express-validator');
const bcrypt = require('bcryptjs'); const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
@ -14,6 +15,55 @@ const Functions = require('../models/functions');
const Categories = require('../models/categories'); const Categories = require('../models/categories');
const Comments = require('../models/comments'); const Comments = require('../models/comments');
async function handleEditUser(res, { name, email, biography, isPublicEmail }, userId, logoName) {
const user = await Users.findOne({ where: { id: userId } });
user.name = name;
user.email = email;
user.biography = biography;
user.isPublicEmail = isPublicEmail;
if (logoName != undefined) {
user.logo = `/images/users/${logoName}`;
}
await user.save();
return res.status(200).json({ message: "Le profil a bien été modifié!" });
}
exports.putUser = (req, res, next) => {
const { name, email, biography, isPublicEmail } = req.body;
const logo = req.files.logo;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
}
if (logo != undefined) {
if (!logo || logo.truncated && (
logo.mimetype !== 'image/png' ||
logo.mimetype !== 'image/jpg' ||
logo.mimetype !== 'image/jpeg' ||
logo.mimetype !== 'image/gif'
)) {
return errorHandling(next, { message:"Le profil doit avoir une image valide.", statusCode: 400 });
}
const logoName = name + uuid.v4() + logo.name;
logo.mv(path.join(__dirname, '..', 'assets', 'images', 'users') + '/' + logoName, async (error) => {
if (error) return errorHandling(next, serverError);
try {
return handleEditUser(res, { name, email, biography, isPublicEmail }, req.userId, logoName);
} catch (error) {
console.log(error);
return errorHandling(next, serverError);
}
});
} else {
try {
return handleEditUser(res, { name, email, biography, isPublicEmail }, req.userId, null);
} catch (error) {
console.log(error);
return errorHandling(next, serverError);
}
}
}
exports.register = async (req, res, next) => { exports.register = async (req, res, next) => {
const { name, email, password } = req.body; const { name, email, password } = req.body;
const errors = validationResult(req); const errors = validationResult(req);
@ -33,7 +83,7 @@ exports.register = async (req, res, next) => {
return res.status(201).json({ result: "Vous y êtes presque, veuillez vérifier vos emails pour confirmer l'inscription." }); return res.status(201).json({ result: "Vous y êtes presque, veuillez vérifier vos emails pour confirmer l'inscription." });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }
@ -57,11 +107,11 @@ exports.login = async (req, res, next) => {
} }
const token = jwt.sign({ const token = jwt.sign({
email: user.email, userId: user.id email: user.email, userId: user.id
}, JWT_SECRET, { expiresIn: '1h' }); }, JWT_SECRET, { expiresIn: '3h' });
return res.status(200).json({ token, id: user.id, name: user.name, email: user.email, biography: user.biography, logo: user.logo, isPublicEmail: user.isPublicEmail, isAdmin: user.isAdmin, createdAt: user.createdAt }); return res.status(200).json({ token, id: user.id, name: user.name, email: user.email, biography: user.biography, logo: user.logo, isPublicEmail: user.isPublicEmail, isAdmin: user.isAdmin, createdAt: user.createdAt });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }
@ -81,7 +131,7 @@ exports.confirmEmail = async (req, res, next) => {
return res.redirect(`${FRONT_END_HOST}/login?isConfirmed=true`); return res.redirect(`${FRONT_END_HOST}/login?isConfirmed=true`);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }
@ -109,7 +159,7 @@ exports.resetPassword = async (req, res, next) => {
return res.status(200).json({ result: "Demande de réinitialisation du mot de passe réussi, veuillez vérifier vos emails!" }); return res.status(200).json({ result: "Demande de réinitialisation du mot de passe réussi, veuillez vérifier vos emails!" });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }
@ -132,7 +182,7 @@ exports.newPassword = async (req, res, next) => {
return res.status(200).json({ result: "Le mot de passe a bien été modifié!" }); return res.status(200).json({ result: "Le mot de passe a bien été modifié!" });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }
@ -156,10 +206,12 @@ exports.getUserInfo = async (req, res, next) => {
}); });
const favoritesArray = favorites.map((favorite) => favorite.function); const favoritesArray = favorites.map((favorite) => favorite.function);
const comments = await Comments.findAll({ const comments = await Comments.findAll({
limit: 10,
where: { userId: user.id }, where: { userId: user.id },
include: [ include: [
{ model: Functions, attributes: { exclude: ["updatedAt", "utilizationForm", "article", "isOnline"] } } { model: Functions, attributes: { exclude: ["updatedAt", "utilizationForm", "article", "isOnline"] } }
] ],
order: [['createdAt', 'DESC']]
}); });
const commentsArray = comments.map((commentObject) => { const commentsArray = comments.map((commentObject) => {
return { return {
@ -182,6 +234,6 @@ exports.getUserInfo = async (req, res, next) => {
return res.status(200).json(userObject); return res.status(200).json(userObject);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
errorHandling(next, serverError); return errorHandling(next, serverError);
} }
} }

View File

@ -11,68 +11,66 @@ const AdminRouter = Router();
// Permet de créé une fonction // Permet de créé une fonction
AdminRouter.post('/functions', isAuth, isAdmin, AdminRouter.post('/functions', isAuth, isAdmin,
fileUpload({ fileUpload({
useTempFiles: true, useTempFiles: true,
safeFileNames: true, safeFileNames: true,
preserveExtension: Number, preserveExtension: Number,
limits: { fileSize: 5 * 1024 * 1024 }, // 5mb, limits: { fileSize: 5 * 1024 * 1024 }, // 5mb,
parseNested: true parseNested: true
}), }),
[ [
body('title') body('title')
.not() .not()
.isEmpty() .isEmpty()
.withMessage("La fonction doit avoir un titre.") .withMessage("La fonction doit avoir un titre.")
.isLength({ max: 100 }) .isLength({ max: 100 })
.withMessage("Le titre est trop long."), .withMessage("Le titre est trop long."),
body('slug') body('slug')
.not() .not()
.isEmpty() .isEmpty()
.withMessage("La fonction doit avoir un slug.") .withMessage("La fonction doit avoir un slug.")
.isLength({ max: 100 }) .isLength({ max: 100 })
.withMessage("Le slug est trop long.") .withMessage("Le slug est trop long.")
.custom((async (slug) => { .custom((async (slug) => {
try { try {
const FunctionSlug = await Functions.findOne({ where: { slug } }); const FunctionSlug = await Functions.findOne({ where: { slug } });
if (FunctionSlug) { if (FunctionSlug) {
return Promise.reject("Le slug existe déjà..."); return Promise.reject("Le slug existe déjà...");
}
} catch (error) {
console.log(error);
} }
return true; } catch (error) {
})), console.log(error);
body('description') }
.not() return true;
.isEmpty() })),
.withMessage("La fonction doit avoir une description.") body('description')
.isLength({ max: 255 }) .not()
.withMessage("La description est trop longue."), .isEmpty()
body('categorieId') .withMessage("La fonction doit avoir une description.")
.not() .isLength({ max: 255 })
.isEmpty() .withMessage("La description est trop longue."),
.withMessage("La fonction doit avoir une catégorie.") body('categorieId')
.custom(async (categorieId) => { .not()
try { .isEmpty()
const categorieFound = await Categories.findOne({ where: { id: categorieId } }); .withMessage("La fonction doit avoir une catégorie.")
if (!categorieFound) { .custom(async (categorieId) => {
return Promise.reject("La catégorie n'existe pas!"); try {
} const categorieFound = await Categories.findOne({ where: { id: categorieId } });
} catch (error) { if (!categorieFound) {
console.log(error); return Promise.reject("La catégorie n'existe pas!");
} }
return true; } catch (error) {
}), console.log(error);
body('type') }
.custom((type) => { return true;
if (!(type === 'article' || type === 'form' || type === 'page')) { }),
return Promise.reject('Le type de la fonction peut être : article, form ou page.'); body('type')
} .custom((type) => {
return true; if (!(type === 'article' || type === 'form' || type === 'page')) {
}) return Promise.reject('Le type de la fonction peut être : article, form ou page.');
], }
adminController.postFunction return true;
); })
], adminController.postFunction);
// Supprime une fonction avec son id // Supprime une fonction avec son id
AdminRouter.delete('/functions/:id', isAuth, isAdmin, adminController.deleteFunction); AdminRouter.delete('/functions/:id', isAuth, isAdmin, adminController.deleteFunction);

View File

@ -1,8 +1,10 @@
const { Router } = require('express'); const { Router } = require('express');
const { body } = require('express-validator'); const { body } = require('express-validator');
const fileUpload = require('express-fileupload');
const usersController = require('../controllers/users'); const usersController = require('../controllers/users');
const { requiredFields } = require('../assets/config/errors'); const { requiredFields } = require('../assets/config/errors');
const Users = require('../models/users'); const Users = require('../models/users');
const isAuth = require('../middlewares/isAuth');
const UsersRouter = Router(); const UsersRouter = Router();
@ -21,6 +23,59 @@ UsersRouter.post('/login', [
// Récupère les informations public d'un profil // Récupère les informations public d'un profil
UsersRouter.get('/:name', usersController.getUserInfo); UsersRouter.get('/:name', usersController.getUserInfo);
// Permet de modifier son profil
UsersRouter.put('/', isAuth,
fileUpload({
useTempFiles: true,
safeFileNames: true,
preserveExtension: Number,
limits: { fileSize: 5 * 1024 * 1024 }, // 5mb,
parseNested: true
}),
[
body('email')
.isEmail()
.withMessage("Veuillez rentré une adresse mail valide.")
.custom((async (email) => {
try {
const user = await Users.findOne({ where: { email } });
if (user && user.email !== email) {
return Promise.reject("L'adresse email existe déjà...");
}
} catch (error) {
return console.log(error);
}
return true;
}))
.normalizeEmail(),
body('name')
.trim()
.not()
.isEmpty()
.withMessage("Vous devez avoir un nom (ou pseudo).")
.isAlphanumeric()
.withMessage("Votre nom ne peut contenir que des lettres ou/et des nombres.")
.isLength({ max: 30 })
.withMessage("Votre nom est trop long")
.custom(async (name) => {
try {
const user = await Users.findOne({ where: { name } });
if (user && user.name !== name) {
return Promise.reject("Le nom existe déjà...");
}
} catch (error) {
console.log(error);
}
return true;
}),
body('isPublicEmail')
.isBoolean()
.withMessage("L'adresse email peut être public ou privé, rien d'autre."),
body('biography')
.trim()
.escape()
], usersController.putUser);
// Permet de s'inscrire // Permet de s'inscrire
UsersRouter.post('/register', [ UsersRouter.post('/register', [
body('email') body('email')