-
+
@@ -12,7 +12,7 @@ exports.signupEmail = (url) => `
|
- FunctionProject
+ FunctionProject
|
@@ -21,21 +21,17 @@ exports.signupEmail = (url) => `
-
+
-
-
- Veuillez confirmer l'inscription
+
+
+ ${subtitle}
- Oui, je m'inscris.
+ ${buttonText}
- 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.
+ ${footerText}
|
|
diff --git a/api/controllers/admin.js b/api/controllers/admin.js
index 9a31389..d029150 100644
--- a/api/controllers/admin.js
+++ b/api/controllers/admin.js
@@ -1,8 +1,33 @@
-const errorHandling = require('../assets/utils/errorHandling');
-const { serverError } = require('../assets/config/errors');
-const Users = require('../models/users');
+const path = require('path');
+const { validationResult } = require('express-validator');
+const errorHandling = require('../assets/utils/errorHandling');
+const { serverError } = require('../assets/config/errors');
+const Functions = require('../models/functions');
exports.postFunction = (req, res, next) => {
- // TODO: Pouvoir créé une fonction
- res.status(200).json({ message: "test"});
+ const { title, slug, description, type, categorieId } = req.body;
+ const image = req.files.image;
+ const errors = validationResult(req);
+ if (!errors.isEmpty()) {
+ console.log(errors.array())
+ return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
+ }
+ if (!image || image.truncated && (
+ image.mimetype !== 'image/png' ||
+ image.mimetype !== 'image/jpg' ||
+ image.mimetype !== 'image/jpeg'
+ )) {
+ return errorHandling(next, { message:"La fonction doit avoir une image valide.", statusCode: 400 });
+ }
+ const imageName = slug + image.name;
+ image.mv(path.join(__dirname, '..', 'assets', 'images', 'functions') + '/' + imageName, async (error) => {
+ if (error) return errorHandling(next, serverError);
+ try {
+ await Functions.create({ title, slug, description, type, categorieId, image: `/images/functions/${imageName}` });
+ return res.status(201).json({ message: "La fonction a été correctement ajouté!"});
+ } catch (error) {
+ console.log(error);
+ errorHandling(next, serverError);
+ }
+ });
}
\ No newline at end of file
diff --git a/api/controllers/users.js b/api/controllers/users.js
index 1f5d2ab..483c35c 100644
--- a/api/controllers/users.js
+++ b/api/controllers/users.js
@@ -7,7 +7,7 @@ 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 { emailTemplate } = require('../assets/config/emails');
const Users = require('../models/users');
exports.register = async (req, res, next) => {
@@ -24,9 +24,9 @@ exports.register = async (req, res, next) => {
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
to: email,
subject: "FunctionProject - Confirmer l'inscription",
- html: signupEmail(`${HOST}/users/confirm-email/${tempToken}`)
+ html: emailTemplate("Veuillez confirmer l'inscription", "Oui, je m'inscris.", `${HOST}/users/confirm-email/${tempToken}`, "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.")
});
- return res.status(201).json({ result: "Vous y êtes presque, veuillez vérifier votre boite d'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) {
console.log(error);
errorHandling(next, serverError);
@@ -36,7 +36,7 @@ exports.register = async (req, res, next) => {
exports.login = async (req, res, next) => {
const { email, password } = req.body;
try {
- const user = await Users.findOne({ where: { email, confirmed: true } });
+ const user = await Users.findOne({ where: { email, isConfirmed: true } });
if (!user) {
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 400 });
}
diff --git a/api/package-lock.json b/api/package-lock.json
index c645886..a49edb7 100644
--- a/api/package-lock.json
+++ b/api/package-lock.json
@@ -173,6 +173,14 @@
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
+ "busboy": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz",
+ "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==",
+ "requires": {
+ "dicer": "0.3.0"
+ }
+ },
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
@@ -384,6 +392,14 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
+ "dicer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz",
+ "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==",
+ "requires": {
+ "streamsearch": "0.1.2"
+ }
+ },
"dns-prefetch-control": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz",
@@ -516,6 +532,14 @@
"vary": "~1.1.2"
}
},
+ "express-fileupload": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.1.6.tgz",
+ "integrity": "sha512-w24zPWT8DkoIxSVkbxYPo9hkTiLpCQQzNsLRTCnecBhfbYv+IkIC5uLw2MIUAxBZ+7UMmXPjGxlhzUXo4RcbZw==",
+ "requires": {
+ "busboy": "^0.3.1"
+ }
+ },
"express-validator": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.4.0.tgz",
@@ -1596,6 +1620,11 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
+ "streamsearch": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
+ "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
+ },
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
diff --git a/api/package.json b/api/package.json
index f77ef92..f06ed0a 100644
--- a/api/package.json
+++ b/api/package.json
@@ -14,6 +14,7 @@
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"express": "^4.17.1",
+ "express-fileupload": "^1.1.6",
"express-validator": "^6.4.0",
"helmet": "^3.21.3",
"jsonwebtoken": "^8.5.1",
diff --git a/api/routes/admin.js b/api/routes/admin.js
index 6e9cb72..8a6f4b0 100644
--- a/api/routes/admin.js
+++ b/api/routes/admin.js
@@ -1,11 +1,79 @@
const { Router } = require('express');
+const fileUpload = require('express-fileupload');
+const { body } = require('express-validator');
const adminController = require('../controllers/admin');
-const isAuth = require('../middlewares/isAuth');
-const isAdmin = require('../middlewares/isAdmin');
+const isAuth = require('../middlewares/isAuth');
+const isAdmin = require('../middlewares/isAdmin');
+const Functions = require('../models/functions');
+const Categories = require('../models/categories');
const AdminRouter = Router();
// Permet de créé une fonction
-AdminRouter.post('/functions', isAuth, isAdmin, adminController.postFunction);
+AdminRouter.post('/functions',
+ isAuth,
+ isAdmin,
+ fileUpload({
+ useTempFiles: true,
+ safeFileNames: true,
+ preserveExtension: Number,
+ limits: { fileSize: 5 * 1024 * 1024 }, // 5mb,
+ parseNested: true
+ }),
+ [
+ body('title')
+ .not()
+ .isEmpty()
+ .withMessage("La fonction doit avoir un titre.")
+ .isLength({ max: 100 })
+ .withMessage("Le titre est trop long."),
+ body('slug')
+ .not()
+ .isEmpty()
+ .withMessage("La fonction doit avoir un slug.")
+ .isLength({ max: 100 })
+ .withMessage("Le slug est trop long.")
+ .custom((async (slug) => {
+ try {
+ const FunctionSlug = await Functions.findOne({ where: { slug } });
+ if (FunctionSlug) {
+ return Promise.reject("Le slug existe déjà...");
+ }
+ } catch (error) {
+ console.log(error);
+ }
+ return true;
+ })),
+ body('description')
+ .not()
+ .isEmpty()
+ .withMessage("La fonction doit avoir une description.")
+ .isLength({ max: 255 })
+ .withMessage("La description est trop longue."),
+ body('categorieId')
+ .not()
+ .isEmpty()
+ .withMessage("La fonction doit avoir une catégorie.")
+ .custom(async (categorieId) => {
+ try {
+ const categorieFound = await Categories.findOne({ where: { id: categorieId } });
+ if (!categorieFound) {
+ return Promise.reject("La catégorie n'existe pas!");
+ }
+ } catch (error) {
+ console.log(error);
+ }
+ return true;
+ }),
+ body('type')
+ .custom((type) => {
+ if (!(type === 'article' || type === 'form' || type === 'page')) {
+ return Promise.reject('Le type de la fonction peut être : article, form ou page.');
+ }
+ return true;
+ })
+ ],
+ adminController.postFunction
+);
module.exports = AdminRouter;
\ No newline at end of file
diff --git a/api/routes/users.js b/api/routes/users.js
index 25a0804..88c0f44 100644
--- a/api/routes/users.js
+++ b/api/routes/users.js
@@ -22,6 +22,7 @@ UsersRouter.post('/register', [
} catch (error) {
return console.log(error);
}
+ return true;
}))
.normalizeEmail(),
body('password')
@@ -34,16 +35,19 @@ UsersRouter.post('/register', [
.withMessage("Vous devez avoir un nom (ou pseudo).")
.isAlphanumeric()
.withMessage("Votre nom ne peut contenir que des lettres ou/et des nombres.")
- .custom((async (name) => {
+ .isLength({ max: 30 })
+ .withMessage("Votre nom est trop long")
+ .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);
+ console.log(error);
}
- }))
+ return true;
+ })
], usersController.register);
// Confirme l'inscription
diff --git a/website/components/FunctionComponentTop.js b/website/components/FunctionComponentTop.js
index f6ce7f8..a8a1497 100644
--- a/website/components/FunctionComponentTop.js
+++ b/website/components/FunctionComponentTop.js
@@ -4,7 +4,7 @@ const FunctionComponentTop = (props) => (
-
+
{props.title}
{props.description}
| |