diff --git a/controller/ArticleCtrl.js b/controller/ArticleCtrl.js index e603b60..2fcac65 100644 --- a/controller/ArticleCtrl.js +++ b/controller/ArticleCtrl.js @@ -7,18 +7,19 @@ const nem = require("nemjs"); require("dotenv").config(); -const ARTICLES_IMG = process.env.IMG_URL + "articles/"; -const ARTICLES_THUMB = process.env.THUMB_URL + "articles/"; +const { ARTICLE_NOT_FOUND, ARTICLES_NOT_FOUND, IMG_EXT, IMG_URL, THUMB_URL } = process.env; + +const ARTICLES_IMG = IMG_URL + "articles/"; +const ARTICLES_THUMB = THUMB_URL + "articles/"; const Article = db.article; const form = formidable({ uploadDir: ARTICLES_IMG, keepExtensions: true }); -//! ******************** CHECKERS ******************** +//! ******************** UTILS ******************** /** * ? CHECK ARTICLE DATA * * Checks the validity of article data. - * * @param {string} name - The name of the article. * @param {string} text - The text of the article. * @param {string} alt - The alternative text for the article. @@ -27,25 +28,23 @@ const form = formidable({ uploadDir: ARTICLES_IMG, keepExtensions: true }); * @return {object} The response object with an error message if the article is not correct. */ exports.checkArticleData = (name, text, alt, cat, res) => { - const STR_MAX = process.env.STRING_MAX; - const STR_MIN = process.env.STRING_MIN; - const TXT_MAX = process.env.TEXT_MAX; - const TXT_MIN = process.env.TEXT_MIN; - - let alert = ""; - - if (!nem.checkRange(cat, STR_MIN, STR_MAX)) alert = process.env.CHECK_CAT; - if (!nem.checkRange(alt, STR_MIN, STR_MAX)) alert = process.env.CHECK_NAME; - if (!nem.checkRange(text, TXT_MIN, TXT_MAX)) alert = process.env.CHECK_TEXT; - if (!nem.checkRange(name, STR_MIN, STR_MAX)) alert = process.env.CHECK_NAME; - - if (alert !== "") return res.status(403).json({ message: alert }); + const { CHECK_CAT, CHECK_NAME, CHECK_TEXT, STRING_MAX, STRING_MIN, TEXT_MAX, TEXT_MIN } = process.env; + + if ( + !nem.checkRange(cat, STRING_MIN, STRING_MAX) || + !nem.checkRange(alt, STRING_MIN, STRING_MAX) || + !nem.checkRange(text, TEXT_MIN, TEXT_MAX) || + !nem.checkRange(name, STRING_MIN, STRING_MAX) + ) { + return res.status(403).json({ + message: CHECK_CAT || CHECK_NAME || CHECK_TEXT || CHECK_NAME + }); + } } /** * ? CHECK ARTICLE UNIQUE * * Checks if an article is unique based on its name & text. - * * @param {string} name - The name of the article. * @param {string} text - The text of the article. * @param {object} article - The existing article to compare with. @@ -53,100 +52,27 @@ exports.checkArticleData = (name, text, alt, cat, res) => { * @return {object} The response object with an error message if the article is not unique. */ exports.checkArticleUnique = (name, text, article, res) => { - if (article.name === name) { - return res.status(403).json({ message: process.env.DISPO_NAME }); - } - - if (article.text === text) { - return res.status(403).json({ message: process.env.DISPO_TEXT }); - } -} - -/** - * ? CHECK ARTICLES FOR UNIQUE - * * Checks the articles for uniqueness based on the given id. - * - * @param {string} id - The id to compare against. - * @param {Array} articles - The array of articles to check. - * @param {Object} fields - The object containing the fields to check against. - * @param {Object} res - The response object. - */ -exports.checkArticlesForUnique = (id, articles, fields, res) => { - for (let article of articles) { - if (article.id !== id) { - this.checkArticleUnique(fields.name, fields.text, article, res) - } - } -} - -//! ******************** GETTERS ******************** - -/** - * ? GET ARTICLE CREATED - * * Returns an object containing the details of an article. - * - * @param {string} name - The name of the article. - * @param {string} text - The text of the article. - * @param {string} image - The image of the article. - * @param {string} alt - The alt text for the image. - * @param {string} cat - The category of the article. - * @return {object} An object containing the details of the article. - */ -exports.getArticleCreated = (name, text, image, alt, cat) => { - - return { - name: name, - text: text, - image: image, - alt: alt, - cat: cat - } -} + const { DISPO_NAME, DISPO_TEXT } = process.env; -/** - * ? GET ARTICLE UPDATED - * * Returns an object containing updated article information. - * - * @param {string} name - The name of the article. - * @param {string} text - The text content of the article. - * @param {string} image - The URL of the article image. - * @param {string} alt - The alternative text for the article image. - * @param {string} likes - The list of user Ids as article likes. - * @param {string} cat - The category that the article belongs to. - * @return {object} - An object containing the updated article information. - */ -exports.getArticleUpdated = (name, text, image, alt, likes, cat) => { - - return { - name: name, - text: text, - image: image, - alt: alt, - likes: likes, - cat: cat + if (article.name === name || article.text === text) { + return res.status(403).json({ message: DISPO_NAME || DISPO_TEXT }) } } -//! ******************** SETTER ******************** - /** * ? SET IMAGE * * Sets the image for an article. - * * @param {string} name - The name of the article. * @param {string} newFilename - The new filename of the image. */ exports.setImage = (name, newFilename) => { - let input = "articles/" + newFilename; - let output = "articles/" + name; - - nem.setThumbnail(input, process.env.THUMB_URL + output); - nem.setThumbnail( - input, - process.env.IMG_URL + output, - process.env.IMG_WIDTH, - process.env.IMG_HEIGHT - ); + const { IMG_HEIGHT, IMG_WIDTH } = process.env; + + const INPUT = "articles/" + newFilename; + const OUTPUT = "articles/" + name; + + nem.setThumbnail(INPUT, THUMB_URL + OUTPUT); + nem.setThumbnail(INPUT, IMG_URL + OUTPUT, IMG_WIDTH, IMG_HEIGHT); } //! ******************** PUBLIC ******************** @@ -161,10 +87,9 @@ exports.setImage = (name, newFilename) => { * @throws {Error} If the articles are not found in the database. */ exports.listArticles = (req, res) => { - Article - .findAll() + Article.findAll() .then((articles) => { res.status(200).json(articles) }) - .catch(() => res.status(404).json({ message: process.env.ARTICLES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ARTICLES_NOT_FOUND })); } /** @@ -177,10 +102,11 @@ exports.listArticles = (req, res) => { * @throws {Error} If the article is not found in the database. */ exports.readArticle = (req, res) => { - Article - .findByPk(parseInt(req.params.id)) + const ID = parseInt(req.params.id); + + Article.findByPk(ID) .then((article) => { res.status(200).json(article) }) - .catch(() => res.status(404).json({ message: process.env.ARTICLE_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ARTICLE_NOT_FOUND })); } //! ******************** PRIVATE ******************** @@ -196,35 +122,36 @@ exports.readArticle = (req, res) => { * @throws {Error} If the article is not created in the database. */ exports.createArticle = (req, res, next) => { + const { ARTICLE_CREATED, ARTICLE_NOT_CREATED } = process.env; + form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkArticleData(fields.name, fields.text, fields.alt, fields.cat, res); + const { name, text, alt, cat } = fields; + const { image } = files; - Article - .findAll() - .then((articles) => { - for (let article of articles) { - this.checkArticleUnique(fields.name, fields.text, article, res) - } + const IMG = nem.getName(name) + "." + IMG_EXT; - let image = nem.getName(fields.name) + "." + process.env.IMG_EXT; - this.setImage(image, files.image.newFilename); + this.checkArticleData(name, text, alt, cat, res); - let article = this.getArticleCreated( - fields.name, fields.text, image, fields.alt, fields.cat - ); + Article.findAll() + .then((articles) => { + for (const article of articles) this.checkArticleUnique(name, text, article, res); + if (image && image.newFilename) this.setImage(IMG, image.newFilename); + + const article = { ...fields, image: IMG }; - Article - .create(article) + Article.create(article) .then(() => { - fs.unlink(ARTICLES_IMG + files.image.newFilename, () => { - res.status(201).json({ message: process.env.ARTICLE_CREATED }) - }) + if (image && image.newFilename) { + fs.unlink(ARTICLES_IMG + image.newFilename, () => { + res.status(201).json({ message: ARTICLE_CREATED }) + }) + } }) - .catch(() => res.status(400).json({ message: process.env.ARTICLE_NOT_CREATED })); + .catch(() => res.status(400).json({ message: ARTICLE_NOT_CREATED })); }) - .catch(() => res.status(404).json({ message: process.env.ARTICLES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ARTICLES_NOT_FOUND })); }) } @@ -239,32 +166,37 @@ exports.createArticle = (req, res, next) => { * @throws {Error} If the article is not updated in the database. */ exports.updateArticle = (req, res, next) => { - const id = parseInt(req.params.id); + const { ARTICLE_UPDATED, ARTICLE_NOT_UPDATED } = process.env; form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkArticleData(fields.name, fields.text, fields.alt, fields.cat, res); + const { name, text, alt, cat } = fields; + const { image } = files; - Article - .findAll() - .then((articles) => { - this.checkArticlesForUnique(id, articles, fields, res); + const ID = parseInt(req.params.id); + const IMG = nem.getName(name) + "." + IMG_EXT; - let image = nem.getName(fields.name) + "." + process.env.IMG_EXT; - if (files.image) this.setImage(image, files.image.newFilename); + this.checkArticleData(name, text, alt, cat, res); + + Article.findAll() + .then((articles) => { + articles.filter(article => article.id !== ID) + .forEach(article => this.checkArticleUnique(name, text, article, res)); - let article = this.getArticleUpdated(fields.name, fields.text, image, fields.alt, fields.likes, fields.cat); + if (image && image.newFilename) this.setImage(IMG, image.newFilename); + const article = { ...fields, image: IMG }; - Article - .update(article, { where: { id: id }}) + Article.update(article, { where: { id: ID }}) .then(() => { - if (files.image) fs.unlink(ARTICLES_IMG + files.image.newFilename, () => { }); - res.status(200).json({ message: process.env.ARTICLE_UPDATED }); + if (image && image.newFilename) { + fs.unlink(ARTICLES_IMG + image.newFilename, () => {}) + } + res.status(200).json({ message: ARTICLE_UPDATED }); }) - .catch(() => res.status(400).json({ message: process.env.ARTICLE_NOT_UPDATED })); + .catch(() => res.status(400).json({ message: ARTICLE_NOT_UPDATED })); }) - .catch(() => res.status(404).json({ message: process.env.ARTICLES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ARTICLES_NOT_FOUND })); }) } @@ -278,20 +210,19 @@ exports.updateArticle = (req, res, next) => { * @throws {Error} If the article is not deleted in the database. */ exports.deleteArticle = (req, res) => { - const id = parseInt(req.params.id); + const { ARTICLE_DELETED, ARTICLE_NOT_DELETED } = process.env; + const ID = parseInt(req.params.id); - Article - .findByPk(id) + Article.findByPk(ID) .then(article => { fs.unlink(ARTICLES_THUMB + article.image, () => { fs.unlink(ARTICLES_IMG + article.image, () => { - Article - .destroy({ where: { id: id }}) - .then(() => res.status(204).json({ message: process.env.ARTICLE_DELETED })) - .catch(() => res.status(400).json({ message: process.env.ARTICLE_NOT_DELETED })) - }); + Article.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: ARTICLE_DELETED })) + .catch(() => res.status(400).json({ message: ARTICLE_NOT_DELETED })); + }) }) }) - .catch(() => res.status(404).json({ message: process.env.ARTICLE_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ARTICLE_NOT_FOUND })); } diff --git a/controller/AuthCtrl.js b/controller/AuthCtrl.js index 448237d..5bbe5bc 100644 --- a/controller/AuthCtrl.js +++ b/controller/AuthCtrl.js @@ -8,127 +8,35 @@ const Recaptcha = require("google-recaptcha"); require("dotenv").config(); +const { USER_NOT_FOUND } = process.env; + const form = formidable(); const recaptcha = new Recaptcha({ secret: process.env.RECAPTCHA_SECRET }); const User = db.user; - -//! ******************** CHECKER ******************** - -/** - * ? CHECK AUTH DATA - * * Validates the provided email and sends an error response if the email is invalid. - * - * @param {string} email - The email to be validated. - * @param {object} res - The response object used to send the error response. - * @return {object} - The error response containing a message. - */ -exports.checkAuthData = (email, res) => { - if (!nem.checkEmail(email)) { - return res.status(403).json({ message: process.env.CHECK_EMAIL }); - } -} - -//! ******************** GETTER ******************** - -/** - * ? GET USER - * * Returns a user object with the provided details. - * - * @param {string} name - The name of the user. - * @param {string} email - The email of the user. - * @param {string} image - The image URL of the user. - * @param {string} pass - The password of the user. - * @param {string} role - The role of the user. - * @param {string} created - The date of creation of the user. - * @param {string} updated - The date of last update of the user. - * @return {Object} - The user object with the provided details. - */ -exports.getUser = (name, email, image, pass, role, created, updated) => { - - return { - name: name, - email: email, - image: image, - pass: pass, - role: role, - created: created, - updated: updated - } -} - -//! ******************** SETTER ******************** - -/** - * ? SET MAILER - * * Set the mailer and send an email. - * - * @param {Object} fields - The fields for the email. - * @param {Object} res - The response object. - * @return {Object} A message indicating that the email was sent. - * @throws {Error} If an error occurs while sending the email. - */ -exports.setMailer = (fields, res) => { - const mailer = nem.getMailer(); - - (async function(){ - try { - let mail = nem.getMessage(fields); - - await mailer.sendMail(mail, function() { - res.status(202).json({ message: process.env.AUTH_MESSAGE }); - }); - } catch(e){ console.error(e); } - })(); -} - -/** - * ? SET MESSAGE - * * Sets a message in the fields object and returns the modified fields object. - * - * @param {object} fields - The fields object to modify. - * @param {string} pass - The password to include in the message. - * @return {object} The modified fields object. - */ -exports.setMessage = (fields, pass) => { - fields.html = ` -

${fields.html}

- ${pass} - `; - - return fields; -} - -//! ******************** PUBLIC ******************** - /** * ? READ AVATAR * * Retrieves the avatar information for a specific user. - * * @param {object} req - The request object. * @param {object} res - The response object. * @return {object} The avatar information for the user. * @throws {Error} If the user is not found in the database. */ exports.readAvatar = (req, res) => { - User - .findByPk(parseInt(req.params.id)) - .then((user) => { - let avatar = {}; + const ID = parseInt(req.params.id); - avatar.name = user.name; - avatar.image = user.image; - avatar.role = user.role; - - res.status(200).json(avatar) + User.findByPk(ID) + .then((user) => { + const { name, image, role } = user; + const avatar = { name: name, image: image, role: role }; + res.status(200).json(avatar); }) - .catch(() => res.status(404).json({ message: process.env.USER_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USER_NOT_FOUND })); } /** * ? CHECK RECAPTCHA * * Checks the validity of a recaptcha response. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -143,12 +51,8 @@ exports.checkRecaptcha = (req, res, next) => { const remoteIp = req.connection.remoteAddress; recaptcha.verify({ response, remoteIp }, (err, data) => { - - if (err) { - res.status(500).send(err); - } else { - res.send(data); - } + if (!err) res.send(data); + else res.status(500).send(err); }); }) } @@ -156,27 +60,27 @@ exports.checkRecaptcha = (req, res, next) => { /** * ? LOGIN USER * * Login a user. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function * @throws {Error} If the user is not found in the database. */ exports.loginUser = (req, res, next) => { + const { AUTH_LOGIN } = process.env; + form.parse(req, (err, fields) => { if (err) { next(err); return } + const { email, pass } = fields; - User - .findOne({ where: { email: fields.email }}) - .then((user) => { nem.setAuth(fields.pass, user, res) }) - .catch(() => res.status(401).json({ message: process.env.AUTH_LOGIN })); + User.findOne({ where: { email: email }}) + .then((user) => { nem.setAuth(pass, user, res) }) + .catch(() => res.status(401).json({ message: AUTH_LOGIN })); }) } /** * ? FORGOT PASSWORD * * Handles the forgot password functionality. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -184,35 +88,45 @@ exports.loginUser = (req, res, next) => { * @throws {Error} If the user is not found in the database. */ exports.forgotPass = (req, res, next) => { + const { AUTH_MESSAGE, CHECK_EMAIL, DISPO_EMAIL_REF, USER_NOT_PASS, USER_NOT_UPDATED } = process.env; + form.parse(req, (err, fields) => { if (err) { next(err); return } - this.checkAuthData(fields.email, res); + const { email, html } = fields; + const pass = nem.getPassword(); + fields.html = `

${html}

${pass}`; - User - .findOne({ where: { email: fields.email }}) - .then((user) => { - if (user !== null) { + if (!nem.checkEmail(email)) return res.status(403).json({ message: CHECK_EMAIL }); - let pass = nem.getPassword(); - fields.html = this.setMessage(fields, pass); + const mailer = nem.getMailer(); + const mail = nem.getMessage(fields); + User.findOne({ where: { email: email }}) + .then((user) => { + if (user !== null) { bcrypt .hash(pass, 10) .then((hash) => { - let newUser = this.getUser(user.name, user.email, user.image, hash, user.role, user.created, user.updated); - - User - .update(newUser, { where: { id: user.id }}) - .then(() => { this.setMailer(fields, res) }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_UPDATED })); + const newUser = { ...user, pass: hash }; + + User.update(newUser, { where: { id: user.id }}) + .then(() => { + (async function(){ + try { + await mailer.sendMail(mail, function() { + res.status(202).json({ message: AUTH_MESSAGE }) + }); + } catch(e){ console.error(e) } + })(); + }) + .catch(() => res.status(400).json({ message: USER_NOT_UPDATED })); }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_PASS })); - + .catch(() => res.status(400).json({ message: USER_NOT_PASS })); } else { - return res.status(403).json({ message: process.env.DISPO_EMAIL_REF }); + return res.status(403).json({ message: DISPO_EMAIL_REF }); } }) - .catch(() => res.status(404).json({ message: process.env.USER_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USER_NOT_FOUND })); }) } diff --git a/controller/GalleryCtrl.js b/controller/GalleryCtrl.js index 8be308d..9c38ee7 100644 --- a/controller/GalleryCtrl.js +++ b/controller/GalleryCtrl.js @@ -7,6 +7,8 @@ const nem = require("nemjs"); require("dotenv").config(); +const { GALLERIES_NOT_FOUND } = process.env; + const GALLERIES_IMG = process.env.IMG_URL + "galleries/"; const GALLERIES_THUMB = process.env.THUMB_URL + "galleries/"; @@ -14,34 +16,30 @@ const form = formidable(); const Gallery = db.gallery; const Image = db.image; -//! ******************** CHECKERS ******************** +//! ******************** UTILS ******************** /** * ? CHECK GALLERY DATA * * Checks the gallery data for valid name and author. - * * @param {string} name - The name of the gallery. * @param {string} author - The author of the gallery. * @param {object} res - The response object. * @return {object} A message indicating that the gallery data is invalid. */ exports.checkGalleryData = (name, author, res) => { - const MAX = process.env.STRING_MAX; - const MIN = process.env.STRING_MIN; - - if (!nem.checkRange(author, MIN, MAX)) { - return res.status(403).json({ message: process.env.CHECK_NAME }); - } + const { CHECK_NAME, STRING_MAX, STRING_MIN } = process.env; - if (!nem.checkRange(name, MIN, MAX)) { - return res.status(403).json({ message: process.env.CHECK_NAME }); + if ( + !nem.checkRange(author, STRING_MIN, STRING_MAX) || + !nem.checkRange(name, STRING_MIN, STRING_MAX) + ) { + return res.status(403).json({ message: CHECK_NAME }); } } /** * ? CHECK GALLERY UNIQUE * * Checks if the given name is unique in the gallery. - * * @param {string} name - The name to be checked. * @param {object} gallery - The gallery object. * @param {object} res - The response object. @@ -49,26 +47,9 @@ exports.checkGalleryData = (name, author, res) => { * @throws {Error} If the name is not unique. */ exports.checkGalleryUnique = (name, gallery, res) => { - if (gallery.name === name) { - return res.status(403).json({ message: process.env.DISPO_NAME }); - } -} + const { DISPO_NAME } = process.env; -/** - * ? CHECK GALLERIES FOR UNIQUE - * * Checks if the given name is unique in the array of galleries. - * - * @param {type} id - The ID to compare with the galleries' IDs. - * @param {type} galleries - The array of galleries to check. - * @param {type} name - The name parameter to pass to the "checkGalleryUnique" function. - * @param {type} res - The res parameter to pass to the "checkGalleryUnique" function. - */ -exports.checkGalleriesForUnique = (id, galleries, name, res) => { - for (let gallery of galleries) { - if (gallery.id !== id) { - this.checkGalleryUnique(name, gallery, res) - } - } + if (gallery.name === name) return res.status(403).json({ message: DISPO_NAME }); } //! ******************** PUBLIC ******************** @@ -76,33 +57,32 @@ exports.checkGalleriesForUnique = (id, galleries, name, res) => { /** * ? LIST GALLERIES * * Retrieves a list of all galleries. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The list of galleries in JSON format. * @throws {Error} If the galleries are not found in the database. */ exports.listGalleries = (req, res) => { - Gallery - .findAll() + Gallery.findAll() .then((galleries) => { res.status(200).json(galleries) }) - .catch(() => res.status(404).json({ message: process.env.GALLERIES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: GALLERIES_NOT_FOUND })); } /** * ? READ GALLERY * * Retrieves a gallery by its ID and sends it as a JSON response. - * * @param {object} req - The request object. * @param {object} res - The response object. * @return {object} The retrieved gallery as a JSON response. * @throws {Error} If the gallery is not found in the database. */ exports.readGallery = (req, res) => { - Gallery - .findByPk(parseInt(req.params.id)) - .then((gallery) => { res.status(200).json(gallery) }) - .catch(() => res.status(404).json({ message: process.env.GALLERY_NOT_FOUND })); + const { GALLERY_NOT_FOUND } = process.env; + const ID = parseInt(req.params.id); + + Gallery.findByPk(ID) + .then((gallery) => { res.status(200).json(gallery) }) + .catch(() => res.status(404).json({ message: GALLERY_NOT_FOUND })); } //! ******************** PRIVATE ******************** @@ -110,7 +90,6 @@ exports.readGallery = (req, res) => { /** * ? CREATE GALLERY * * Creates a new gallery. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function @@ -118,38 +97,32 @@ exports.readGallery = (req, res) => { * @throws {Error} If the gallery was not created. */ exports.createGallery = (req, res, next) => { + const { GALLERY_CREATED, GALLERY_NOT_CREATED } = process.env; + form.parse(req, (err, fields) => { if (err) { next(err); return } - this.checkGalleryData(fields.name, fields.author, res); + const { author, name } = fields; + this.checkGalleryData(name, author, res); - Gallery - .findAll() + Gallery.findAll() .then((galleries) => { - for (let gallery of galleries) { - this.checkGalleryUnique(fields.name, gallery, res) - } - - let cover = nem.getPosterName(fields.name); - let gallery = { - name: fields.name, - author: fields.author, - cover: cover - }; - - Gallery - .create(gallery) - .then(() => res.status(201).json({ message: process.env.GALLERY_CREATED })) - .catch(() => res.status(400).json({ message: process.env.GALLERY_NOT_CREATED })); + for (let gallery of galleries) this.checkGalleryUnique(name, gallery, res); + + const cover = nem.getPosterName(name); + const gallery = { ...fields, cover: cover }; + + Gallery.create(gallery) + .then(() => res.status(201).json({ message: GALLERY_CREATED })) + .catch(() => res.status(400).json({ message: GALLERY_NOT_CREATED })); }) - .catch(() => res.status(404).json({ message: process.env.GALLERIES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: GALLERIES_NOT_FOUND })); }) } /** * ? UPDATE GALLERY * * Update the gallery with the given request data. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -157,62 +130,56 @@ exports.createGallery = (req, res, next) => { * @throws {Error} If the gallery is not updated. */ exports.updateGallery = (req, res, next) => { - const id = parseInt(req.params.id); + const { GALLERY_NOT_UPDATED, GALLERY_UPDATED } = process.env; + const ID = parseInt(req.params.id); form.parse(req, (err, fields) => { if (err) { next(err); return } - this.checkGalleryData(fields.name, fields.author, res); + const { author, name } = fields; + this.checkGalleryData(name, author, res); - Gallery - .findAll() + Gallery.findAll() .then((galleries) => { - this.checkGalleriesForUnique(id, galleries, fields.name, res); + galleries.filter(gallery => gallery.id !== ID).forEach(gallery => + this.checkGalleryUnique(name, gallery, res)); - let gallery = { - name: fields.name, - author: fields.author - }; + const gallery = { ...fields }; - Gallery - .update(gallery, { where: { id: id }}) - .then(() => res.status(200).json({ message: process.env.GALLERY_UPDATED })) - .catch(() => res.status(400).json({ message: process.env.GALLERY_NOT_UPDATED })); + Gallery.update(gallery, { where: { id: ID }}) + .then(() => res.status(200).json({ message: GALLERY_UPDATED })) + .catch(() => res.status(400).json({ message: GALLERY_NOT_UPDATED })); }) - .catch(() => res.status(404).json({ message: process.env.GALLERIES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: GALLERIES_NOT_FOUND })); }) } /** * ? DELETE GALLERY * * Deletes a gallery and its associated images. - * * @param {Object} req - the request object * @param {Object} res - the response object * @return {Object} A message indicating that the gallery was deleted. * @throws {Error} If the gallery is not deleted. */ exports.deleteGallery = (req, res) => { - const id = parseInt(req.params.id); + const { GALLERY_DELETED, GALLERY_NOT_DELETED, IMAGE_DELETE_MANY, IMAGES_NOT_FOUND } = process.env; + const ID = parseInt(req.params.id); - Image - .findAll({ where: { galleryId: id }}) + Image.findAll({ where: { galleryId: ID }}) .then(images => { for (let image of images) { - fs.unlink(GALLERIES_THUMB + image.name, () => { - fs.unlink(GALLERIES_IMG + image.name, () => {}); + fs.unlink(GALLERIES_THUMB + image.name, () => { + fs.unlink(GALLERIES_IMG + image.name, () => {}) }); } - Image - .destroy({ where: { galleryId: id }}) + Image.destroy({ where: { galleryId: ID }}) .then(() => - - Gallery - .destroy({ where: { id: id }}) - .then(() => res.status(204).json({ message: process.env.GALLERY_DELETED })) - .catch(() => res.status(400).json({ message: process.env.GALLERY_NOT_DELETED })) + Gallery.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: GALLERY_DELETED })) + .catch(() => res.status(400).json({ message: GALLERY_NOT_DELETED })) ) - .catch(() => res.status(400).json({ message: process.env.IMAGE_DELETE_MANY })); + .catch(() => res.status(400).json({ message: IMAGE_DELETE_MANY })); }) - .catch(() => res.status(404).json({ message: process.env.IMAGES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: IMAGES_NOT_FOUND })); } diff --git a/controller/ImageCtrl.js b/controller/ImageCtrl.js index 4c4fab4..1a29787 100644 --- a/controller/ImageCtrl.js +++ b/controller/ImageCtrl.js @@ -7,64 +7,44 @@ const nem = require("nemjs"); require("dotenv").config(); -const GALLERIES_IMG = process.env.IMG_URL + "galleries/"; -const GALLERIES_THUMB = process.env.THUMB_URL + "galleries/"; +const { IMAGES_NOT_FOUND, IMG_URL, THUMB_URL } = process.env; + +const GALLERIES_IMG = IMG_URL + "galleries/"; +const GALLERIES_THUMB = THUMB_URL + "galleries/"; const form = formidable({ uploadDir: GALLERIES_IMG, keepExtensions: true }); const Gallery = db.gallery; const Image = db.image; -//! ******************** CHECKER ******************** +//! ******************** UTILS ******************** /** * ? CHECK IMAGE DATA * * Checks the image data. - * * @param {string} description - The description of the image data. * @param {object} res - The response object. * @return {object} The JSON response. */ exports.checkImageData = (description, res) => { - if (!nem.checkRange(description, process.env.STRING_MIN, process.env.TEXT_MAX)) { - return res.status(403).json({ message: process.env.CHECK_NAME }); + const { CHECK_NAME, STRING_MIN, TEXT_MAX } = process.env; + + if (!nem.checkRange(description, STRING_MIN, TEXT_MAX)) { + return res.status(403).json({ message: CHECK_NAME }) } } -//! ******************** SETTER ******************** - /** * ? SET IMAGE * * Sets the image & thumbnail for a gallery. - * * @param {string} image - The filename of the image to set. * @param {string} newFilename - The new filename to use for the image. */ exports.setImage = (image, newFilename) => { - let input = "galleries/" + newFilename; - let output = "galleries/" + image; - - nem.setImage(input, process.env.IMG_URL + output); - nem.setThumbnail(input, process.env.THUMB_URL + output); -} - -//! ******************** GETTER ******************** - -/** - * ? GET IMAGE - * * Retrieves an image with the given name, description & gallery ID. - * - * @param {string} name - The name of the image. - * @param {string} description - The description of the image. - * @param {number} galleryId - The ID of the gallery the image belongs to. - * @return {object} - An object containing the name, description & gallery ID of the image. - */ -exports.getImage = (name, description, galleryId) => { + const INPUT = "galleries/" + newFilename; + const OUTPUT = "galleries/" + image; - return { - name: name, - description: description, - galleryId: galleryId - } + nem.setImage(INPUT, IMG_URL + OUTPUT); + nem.setThumbnail(INPUT, THUMB_URL + OUTPUT); } //! ******************** PUBLIC ******************** @@ -72,7 +52,6 @@ exports.getImage = (name, description, galleryId) => { /** * ? LIST IMAGES * * Retrieves a list of gallery images based on the provided gallery ID. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Promise} A promise that resolves to a response containing the list of gallery images. @@ -81,17 +60,13 @@ exports.getImage = (name, description, galleryId) => { exports.listImages = (req, res) => { Image.belongsTo(Gallery, { foreignKey: "galleryId" }); - Image - .findAll({ + Image.findAll({ where: { galleryId: req.params.id }, attributes: ["id", "name", "description", "galleryId"], - include: { - model: Gallery, - attributes: ["name"], - } + include: { model: Gallery, attributes: ["name"] } }) .then((images) => { res.status(200).json(images) }) - .catch(() => res.status(404).json({ message: process.env.IMAGES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: IMAGES_NOT_FOUND })); }; //! ******************** PRIVATE ******************** @@ -99,7 +74,6 @@ exports.listImages = (req, res) => { /** * ? CREATE IMAGE * * Creates an image based on the request data. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function @@ -107,44 +81,48 @@ exports.listImages = (req, res) => { * @throws {Error} If the image is not created in the database. */ exports.createImage = (req, res, next) => { + const { GALLERY_NOT_FOUND, IMAGE_CREATED, IMAGE_NOT_CREATED, IMAGES_NOT_FOUND, IMG_EXT } = process.env; + form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkImageData(fields.description, res); + const { description, galleryId } = fields; + const { image } = files; - Gallery - .findOne({ where: { id: fields.galleryId }}) + this.checkImageData(description, res); + + Gallery.findOne({ where: { id: galleryId }}) .then((gallery) => { - Image - .findAll({ where: { galleryId: fields.galleryId }}) + Image.findAll({ where: { galleryId: galleryId }}) .then((images) => { let index = images.length + 1; - if (index < 10) { index = "0" + index } + if (index < 10) index = "0" + index; + + const name = nem.getName(gallery.name) + "-" + index + "." + IMG_EXT; + const img = { ...fields, name: name }; - let name = nem.getName(gallery.name) + "-" + index + "." + process.env.IMG_EXT; - this.setImage(name, files.image.newFilename); - let image = this.getImage(name, fields.description, fields.galleryId); + if (image && image.newFilename) this.setImage(name, image.newFilename); - Image - .create(image) + Image.create(img) .then(() => { - fs.unlink(GALLERIES_IMG + files.image.newFilename, () => { - res.status(201).json({ message: process.env.IMAGE_CREATED }); - }) + if (image && image.newFilename) { + fs.unlink(GALLERIES_IMG + image.newFilename, () => { + res.status(201).json({ message: IMAGE_CREATED }) + }) + } }) - .catch(() => res.status(400).json({ message: process.env.IMAGE_NOT_CREATED })); + .catch(() => res.status(400).json({ message: IMAGE_NOT_CREATED })); }) - .catch(() => res.status(404).json({ message: process.env.IMAGES_NOT_FOUND })); + .catch(() => res.status(404).json({ message: IMAGES_NOT_FOUND })); }) - .catch(() => res.status(404).json({ message: process.env.GALLERY_NOT_FOUND })); + .catch(() => res.status(404).json({ message: GALLERY_NOT_FOUND })); }) }; /** * ? UPDATE IMAGE * * Updates an image. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -152,49 +130,52 @@ exports.createImage = (req, res, next) => { * @throws {Error} If the image is not updated in the database. */ exports.updateImage = (req, res, next) => { + const { IMAGE_NOT_UPDATED, IMAGE_UPDATED } = process.env; + const ID = parseInt(req.params.id); + form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkImageData(fields.description, res); - let name = fields.name; + const { name, description } = fields; + const { image } = files; + const img = { ...fields }; - if (files.image) this.setImage(name, files.image.newFilename); - let image = this.getImage(name, fields.description, fields.galleryId); + this.checkImageData(description, res); + if (image && image.newFilename) this.setImage(name, image.newFilename); - Image - .update(image, { where: { id: parseInt(req.params.id) }}) + Image.update(img, { where: { id: ID }}) .then(() => { - if (files.image) fs.unlink(GALLERIES_IMG + files.image.newFilename, () => {}); - res.status(200).json({ message: process.env.IMAGE_UPDATED }); + if (image && image.newFilename) { + fs.unlink(GALLERIES_IMG + image.newFilename, () => {}) + } + res.status(200).json({ message: IMAGE_UPDATED }); }) - .catch(() => res.status(400).json({ message: process.env.IMAGE_NOT_UPDATED })); + .catch(() => res.status(400).json({ message: IMAGE_NOT_UPDATED })); }) }; /** * ? DELETE IMAGE * * Deletes an image from the server and database. - * * @param {Object} req - The HTTP request object. * @param {Object} res - The HTTP response object. * @return {Object} A message indicating that the image was deleted. * @throws {Error} If the image is not deleted in the database. */ exports.deleteImage = (req, res) => { - const id = parseInt(req.params.id); + const { IMAGE_DELETED, IMAGE_NOT_DELETED, IMAGE_NOT_FOUND } = process.env; + const ID = parseInt(req.params.id); - Image - .findByPk(id) + Image.findByPk(ID) .then((image) => { fs.unlink(GALLERIES_THUMB + image.name, () => { fs.unlink(GALLERIES_IMG + image.name, () => { - Image - .destroy({ where: { id: id }}) - .then(() => res.status(204).json({ message: process.env.IMAGE_DELETED })) - .catch(() => res.status(400).json({ message: process.env.IMAGE_NOT_DELETED })); + Image.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: IMAGE_DELETED })) + .catch(() => res.status(400).json({ message: IMAGE_NOT_DELETED })); }) }) }) - .catch(() => res.status(400).json({ message: process.env.IMAGE_NOT_FOUND })); + .catch(() => res.status(400).json({ message: IMAGE_NOT_FOUND })); }; diff --git a/controller/LinkCtrl.js b/controller/LinkCtrl.js index 9eadf46..ba29b3b 100644 --- a/controller/LinkCtrl.js +++ b/controller/LinkCtrl.js @@ -6,15 +6,16 @@ const nem = require("nemjs"); require("dotenv").config(); +const { LINKS_NOT_FOUND } = process.env; + const form = formidable(); const Link = db.link; -//! ******************** CHECKERS ******************** +//! ******************** UTILS ******************** /** * ? CHECK LINK DATA * * Validates the link data provided and returns an error message if any validation fails. - * * @param {string} name - The name of the link. * @param {string} url - The URL of the link. * @param {string} cat - The category of the link. @@ -22,22 +23,20 @@ const Link = db.link; * @return {object} The error message if any validation fails. */ exports.checkLinkData = (name, url, cat, res) => { - const MAX = process.env.STRING_MAX; - const MIN = process.env.STRING_MIN; - - let alert = ""; - - if (!nem.checkRange(cat, MIN, MAX)) alert = process.env.CHECK_CAT; - if (!nem.checkUrl("https://" + url)) alert = process.env.CHECK_URL; - if (!nem.checkRange(name, MIN, MAX)) alert = process.env.CHECK_NAME; - - if (alert !== "") return res.status(403).json({ message: alert }); + const { CHECK_CAT, CHECK_NAME, CHECK_URL, STRING_MAX, STRING_MIN } = process.env; + + if ( + !nem.checkRange(cat, STRING_MIN, STRING_MAX) || + !nem.checkUrl("https://" + url) || + !nem.checkRange(name, STRING_MIN, STRING_MAX) + ) { + return res.status(403).json({ message: CHECK_CAT || CHECK_URL || CHECK_NAME }); + } } /** * ? CHECK LINK UNIQUE * * Checks if the given link name & URL are unique. - * * @param {string} name - The name of the link to check uniqueness for. * @param {string} url - The URL of the link to check uniqueness for. * @param {object} link - The link object to compare against. @@ -45,29 +44,10 @@ exports.checkLinkData = (name, url, cat, res) => { * @return {object} - The response object with the appropriate status & message. */ exports.checkLinkUnique = (name, url, link, res) => { - if (link.name === name) { - return res.status(403).json({ message: process.env.DISPO_NAME }); - } - - if (link.url === url) { - return res.status(403).json({ message: process.env.DISPO_URL }); - } -} + const { DISPO_NAME, DISPO_URL } = process.env; -/** - * ? CHECK LINKS FOR UNIQUE - * * Checks the links for uniqueness based on the given ID. - * - * @param {string} id - The ID to compare against the links. - * @param {Array} links - An array of links to check. - * @param {Object} fields - An object containing the fields to check against the links. - * @param {Object} res - The response object to handle the result. - */ -exports.checkLinksForUnique = (id, links, fields, res) => { - for (let link of links) { - if (link.id !== id) { - this.checkLinkUnique(fields.name, fields.url, link, res); - } + if (link.name === name || link.url === url) { + return res.status(403).json({ message: DISPO_NAME || DISPO_URL }); } } @@ -76,17 +56,15 @@ exports.checkLinksForUnique = (id, links, fields, res) => { /** * ? LIST LINKS * * Retrieves a list of links. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} A JSON object containing the list of links. * @throws {Error} If the links are not found in the database. */ exports.listLinks = (req, res) => { - Link - .findAll() + Link.findAll() .then((links) => res.status(200).json(links)) - .catch(() => res.status(404).json({ message: process.env.LINKS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: LINKS_NOT_FOUND })); }; //! ******************** PRIVATE ******************** @@ -94,7 +72,6 @@ exports.listLinks = (req, res) => { /** * ? CREATE LINK * * Creates a link based on the request data. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function @@ -102,30 +79,29 @@ exports.listLinks = (req, res) => { * @throws {Error} If the link is not created. */ exports.createLink = (req, res, next) => { + const { LINK_CREATED, LINK_NOT_CREATED } = process.env; + form.parse(req, (err, fields) => { if (err) { next(err); return } - this.checkLinkData(fields.name, fields.url, fields.cat, res); + const { name, url, cat } = fields; + this.checkLinkData(name, url, cat, res); - Link - .findAll() + Link.findAll() .then((links) => { - for (let link of links) { - this.checkLinkUnique(fields.name, fields.url, link, res); - } - Link - .create(fields) - .then(() => res.status(201).json({ message: process.env.LINK_CREATED })) - .catch(() => res.status(400).json({ message: process.env.LINK_NOT_CREATED })); + for (let link of links) this.checkLinkUnique(name, url, link, res); + + Link.create(fields) + .then(() => res.status(201).json({ message: LINK_CREATED })) + .catch(() => res.status(400).json({ message: LINK_NOT_CREATED })); }) - .catch(() => res.status(404).json({ message: process.env.LINKS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: LINKS_NOT_FOUND })); }) }; /** * ? UPDATE LINK * * Updates a link in the database. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -133,39 +109,41 @@ exports.createLink = (req, res, next) => { * @throws {Error} If the link is not updated. */ exports.updateLink = (req, res, next) => { - const id = parseInt(req.params.id); + const { LINK_NOT_UPDATED, LINK_UPDATED } = process.env; + const ID = parseInt(req.params.id); form.parse(req, (err, fields) => { if (err) { next(err); return } - this.checkLinkData(fields.name, fields.url, fields.cat, res); + const { name, url, cat } = fields; + this.checkLinkData(name, url, cat, res); - Link - .findAll() + Link.findAll() .then((links) => { - this.checkLinksForUnique(id, links, fields, res); + links.filter(link => link.id !== ID).forEach(link => + this.checkLinkUnique(name, url, link, res)); - Link - .update(fields, { where: { id: id }}) - .then(() => res.status(200).json({ message: process.env.LINK_UPDATED })) - .catch(() => res.status(400).json({ message: process.env.LINK_NOT_UPDATED })); + Link.update(fields, { where: { id: ID }}) + .then(() => res.status(200).json({ message: LINK_UPDATED })) + .catch(() => res.status(400).json({ message: LINK_NOT_UPDATED })); }) - .catch(() => res.status(404).json({ message: process.env.LINKS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: LINKS_NOT_FOUND })); }) }; /** * ? DELETE LINK * * Deletes a link. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} - A message indicating that the link was deleted. * @throws {Error} If the link is not deleted. */ exports.deleteLink = (req, res) => { - Link - .destroy({ where: { id: parseInt(req.params.id) }}) - .then(() => res.status(204).json({ message: process.env.LINK_DELETED })) - .catch(() => res.status(400).json({ message: process.env.LINK_NOT_DELETED })) + const { LINK_DELETED, LINK_NOT_DELETED } = process.env; + const ID = parseInt(req.params.id); + + Link.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: LINK_DELETED })) + .catch(() => res.status(400).json({ message: LINK_NOT_DELETED })) }; diff --git a/controller/OrderCtrl.js b/controller/OrderCtrl.js index 7c8dfef..ee91439 100644 --- a/controller/OrderCtrl.js +++ b/controller/OrderCtrl.js @@ -6,66 +6,48 @@ const nem = require("nemjs"); require("dotenv").config(); +const { ORDERS_NOT_FOUND } = process.env; + const form = formidable(); const Order = db.order; const User = db.user; -//! ******************** SETTERS ******************** - -/** - * ? SET MAILER - * * Sets the mailer and sends an email. - * - * @param {Object} fields - The fields used to generate the email message. - * @param {Object} res - The response object used to send the HTTP response. - * @return {Object} A message indicating that the email was sent. - * @throws {Error} If an error occurs while sending the email. - */ -exports.setMailer = (fields, res) => { - const mailer = nem.getMailer(); - - (async function(){ - try { - let mail = nem.getMessage(fields); - - await mailer.sendMail(mail, function() { - res.status(202).json({ message: process.env.ORDER_MESSAGE }); - }); - } catch(e){ console.error(e); } - })(); -} +//! ******************** UTILS ******************** /** * ? SET MESSAGE * * Sets the message content for an order. - * * @param {number} total - The total amount of the order. * @param {string} paymentId - The ID of the payment. * @param {Array} products - An array of products in the order. - * @return {Object} message - The message object containing the subject, text, and html properties. + * @return {Object} message - The message object containing subject, text & html. */ exports.setMessage = (total, paymentId, products) => { + const { CURRENCY_SYMBOL, ORDER_LIST, ORDER_NAME, ORDER_PAYMENT, ORDER_PRICE, ORDER_QUANTITY, ORDER_SUBJECT, ORDER_TITLE, ORDER_TOTAL } = process.env; + let message = {}; - message.subject = process.env.ORDER_SUBJECT; + message.subject = ORDER_SUBJECT; message.text = ` -

${process.env.ORDER_TITLE}

+

${ORDER_TITLE}

- ${process.env.ORDER_TOTAL} - ${total} ${process.env.CURRENCY_SYMBOL}, - ${process.env.ORDER_PAYMENT} + ${ORDER_TOTAL} + ${total} ${CURRENCY_SYMBOL}, + ${ORDER_PAYMENT} #${paymentId} !

-

${process.env.ORDER_LIST}

`; +

${ORDER_LIST}

`; for (let product of products) { + const { id, name, option, quantity, price } = product; + message.products += ` `; } @@ -80,39 +62,36 @@ exports.setMessage = (total, paymentId, products) => { /** * ? LIST ORDERS * * Retrieves a list of orders. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The list of orders. * @throws {Error} If the orders are not found in the database. */ exports.listOrders = (req, res) => { - Order - .findAll() + Order.findAll() .then((orders) => { res.status(200).json(orders) }) - .catch(() => res.status(404).json({ message: process.env.ORDERS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ORDERS_NOT_FOUND })); }; /** * ? LIST USER ORDERS * * Retrieves a list of orders for a specific user. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The list of user orders. * @throws {Error} If the orders are not found in the database. */ exports.listUserOrders = (req, res) => { - Order - .findAll({ where: { userId: parseInt(req.params.id) }}) + const ID = parseInt(req.params.id); + + Order.findAll({ where: { userId: ID }}) .then((orders) => res.status(200).json(orders)) - .catch(() => res.status(404).json({ message: process.env.ORDERS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: ORDERS_NOT_FOUND })); }; /** * ? CREATE ORDER * * Creates an order based on the request data. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -120,31 +99,41 @@ exports.listUserOrders = (req, res) => { * @throws {Error} If an error occurs while creating the order. */ exports.createOrder = (req, res, next) => { + const { ORDER_CREATED, ORDER_MESSAGE, ORDER_NOT_CREATED, USER_NOT_FOUND } = process.env; + form.parse(req, (err, fields) => { if (err) { next(err); return } - let message = this.setMessage(fields.total, fields.paymentId, fields.products); + const { paymentId, products, total } = fields; + let message = this.setMessage(total, paymentId, products); - Order - .create(fields) + Order.create(fields) .then(() => { - User - .findByPk(fields.userId) + + User.findByPk(fields.userId) .then((user) => { message.email = user.email; - this.setMailer(message, res); + const mailer = nem.getMailer(); + const mail = nem.getMessage(message); + + (async function(){ + try { + await mailer.sendMail(mail, function() { + res.status(202).json({ message: ORDER_MESSAGE }) + }); + } catch(e){ console.error(e); } + })(); }) - .catch(() => res.status(404).json({ message: process.env.USER_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USER_NOT_FOUND })); }) - .then(() => res.status(201).json({ message: process.env.ORDER_CREATED })) - .catch(() => res.status(400).json({ message: process.env.ORDER_NOT_CREATED })); + .then(() => res.status(201).json({ message: ORDER_CREATED })) + .catch(() => res.status(400).json({ message: ORDER_NOT_CREATED })); }) }; /** * ? UPDATE ORDER * * Updates an order. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {function} next - The next middleware function. @@ -152,28 +141,31 @@ exports.createOrder = (req, res, next) => { * @throws {Error} If the order is not updated. */ exports.updateOrder = (req, res, next) => { + const { ORDER_NOT_UPDATED, ORDER_UPDATED } = process.env; + const ID = parseInt(req.params.id); + form.parse(req, (err, fields) => { if (err) { next(err); return } - Order - .update(fields, { where: { id: parseInt(req.params.id) }}) - .then(() => res.status(200).json({ message: process.env.ORDER_UPDATED })) - .catch(() => res.status(400).json({ message: process.env.ORDER_NOT_UPDATED })); + Order.update(fields, { where: { id: ID }}) + .then(() => res.status(200).json({ message: ORDER_UPDATED })) + .catch(() => res.status(400).json({ message: ORDER_NOT_UPDATED })); }) }; /** * ? DELETE ORDER * * Deletes an order. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} A message indicating that the order was deleted. * @throws {Error} If the order is not deleted. */ exports.deleteOrder = (req, res) => { - Order - .destroy({ where: { id: parseInt(req.params.id) }}) - .then(() => res.status(204).json({ message: process.env.ORDER_DELETED })) - .catch(() => res.status(400).json({ message: process.env.ORDER_NOT_DELETED })) + const { ORDER_DELETED, ORDER_NOT_DELETED } = process.env; + const ID = parseInt(req.params.id); + + Order.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: ORDER_DELETED })) + .catch(() => res.status(400).json({ message: ORDER_NOT_DELETED })) }; diff --git a/controller/ProductCtrl.js b/controller/ProductCtrl.js index 38a7ac0..c6aceb6 100644 --- a/controller/ProductCtrl.js +++ b/controller/ProductCtrl.js @@ -7,49 +7,46 @@ const nem = require("nemjs"); require("dotenv").config(); -const PRODUCTS_IMG = process.env.IMG_URL + "products/"; -const PRODUCTS_THUMB = process.env.THUMB_URL + "products/"; +const {IMG_EXT, IMG_URL, PRODUCT_NOT_FOUND, PRODUCTS_NOT_FOUND, THUMB_URL } = process.env; + +const PRODUCTS_IMG = IMG_URL + "products/"; +const PRODUCTS_THUMB = THUMB_URL + "products/"; const form = formidable({ uploadDir: PRODUCTS_IMG, keepExtensions: true }); const Product = db.product; -//! ******************** CHECKERS ******************** +//! ******************** UTILS ******************** /** * ? CHECK PRODUCT DATA * * Validates and checks the product data before processing it. - * * @param {string} name - The name of the product. * @param {string} description - The description of the product. * @param {string} alt - The alternative name of the product. * @param {number} price - The price of the product. * @param {string} cat - The category of the product. * @param {object} res - The response object. - * @return {object} The response object with a JSON message if there are any validation errors. + * @return {object} The response object with a JSON message if there are errors. */ exports.checkProductData = (name, description, alt, price, cat, res) => { - const PRICE_MAX = process.env.PRICE_MAX; - const PRICE_MIN = process.env.PRICE_MIN; - const STR_MAX = process.env.STRING_MAX; - const STR_MIN = process.env.STRING_MIN; - const TXT_MAX = process.env.TEXT_MAX; - const TXT_MIN = process.env.TEXT_MIN; - - let alert = ""; - - if (!nem.checkRange(cat, STR_MIN, STR_MAX)) alert = process.env.CHECK_CAT; - if (!nem.checkRange(price, PRICE_MIN, PRICE_MAX)) alert = process.env.CHECK_PRICE; - if (!nem.checkRange(alt, STR_MIN, STR_MAX)) alert = process.env.CHECK_NAME; - if (!nem.checkRange(description, TXT_MIN, TXT_MAX)) alert = process.env.CHECK_TEXT; - if (!nem.checkRange(name, STR_MIN, STR_MAX)) alert = process.env.CHECK_NAME; - - if (alert !== "") return res.status(403).json({ message: alert }); + const { CHECK_CAT, CHECK_NAME, CHECK_PRICE, CHECK_TEXT, PRICE_MAX, PRICE_MIN, STRING_MAX, STRING_MIN, TEXT_MAX, TEXT_MIN } = process.env; + + if ( + !nem.checkRange(cat, STRING_MIN, STRING_MAX) || + !nem.checkRange(price, PRICE_MIN, PRICE_MAX) || + !nem.checkRange(alt, STRING_MIN, STRING_MAX) || + !nem.checkRange(description, TEXT_MIN, TEXT_MAX) || + !nem.checkRange(name, STRING_MIN, STRING_MAX) + ) { + return res.status(403).json({ + message: CHECK_CAT || CHECK_PRICE || CHECK_NAME || CHECK_TEXT || CHECK_NAME + }); + } } /** * ? CHECK PRODUCT UNIQUE * * Checks if the given product name and description are unique. - * * @param {string} name - The name of the product. * @param {string} description - The description of the product. * @param {object} product - The product object to compare with. @@ -57,80 +54,27 @@ exports.checkProductData = (name, description, alt, price, cat, res) => { * @return {object} The JSON response object with the appropriate message and status code. */ exports.checkProductUnique = (name, description, product, res) => { - if (product.name === name) { - return res.status(403).json({ message: process.env.DISPO_NAME }); - } + const { DISPO_DESCRIPTION, DISPO_NAME } = process.env; - if (product.description === description) { - return res.status(403).json({ message: process.env.DISPO_DESCRIPTION }); + if (product.name === name || product.description === description) { + return res.status(403).json({ message: DISPO_NAME || DISPO_DESCRIPTION }); } } -/** - * ? CHECK PRODUCTS FOR UNIQUE - * * Checks if a product is unique based on its ID & fields. - * - * @param {string} id - The ID of the product to check uniqueness against. - * @param {Array} products - An array of products to check for uniqueness. - * @param {Object} fields - An object containing the fields to check for uniqueness. - * @param {Object} res - The response object to send the result to. - */ -exports.checkProductsForUnique = (id, products, fields, res) => { - for (let product of products) { - if (product.id !== id) { - this.checkProductUnique(fields.name, fields.description, product, res) - } - } -} - -//! ******************** GETTERS ******************** - -/** - * ? GET PRODUCT - * * Returns a product object with the given properties. - * - * @param {string} name - The name of the product. - * @param {string} description - The description of the product. - * @param {string} image - The image URL of the product. - * @param {string} alt - The alternative text for the product image. - * @param {number} price - The price of the product. - * @param {object} options - The options for the product. - * @param {string} cat - The category of the product. - * @return {object} The product object with the given properties. - */ -exports.getProduct = (name, description, image, alt, price, options, cat) => { - - return { - name: name, - description: description, - image: image, - alt: alt, - price: price, - options: options, - cat: cat - } -} - -//! ******************** SETTER ******************** - /** * ? SET IMAGE * * Sets the image for a product. - * * @param {string} name - The name of the product. * @param {string} newFilename - The new filename of the image. */ exports.setImage = (name, newFilename) => { - let input = "products/" + newFilename; - let output = "products/" + name; - - nem.setThumbnail(input, process.env.THUMB_URL + output); - nem.setThumbnail( - input, - process.env.IMG_URL + output, - process.env.IMG_WIDTH, - process.env.IMG_HEIGHT - ); + const { IMG_HEIGHT, IMG_WIDTH } = process.env; + + const INPUT = "products/" + newFilename; + const OUTPUT = "products/" + name; + + nem.setThumbnail(INPUT, THUMB_URL + OUTPUT); + nem.setThumbnail(INPUT, IMG_URL + OUTPUT, IMG_WIDTH, IMG_HEIGHT); } //! ******************** PUBLIC ******************** @@ -138,33 +82,31 @@ exports.setImage = (name, newFilename) => { /** * ? LIST PRODUCTS * * Retrieves a list of all products. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The list of products in JSON format. * @throws {Error} If the products are not found in the database. */ exports.listProducts = (req, res) => { - Product - .findAll() + Product.findAll() .then((products) => { res.status(200).json(products) }) - .catch(() => res.status(404).json({ message: process.env.PRODUCTS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: PRODUCTS_NOT_FOUND })); }; /** * ? READ PRODUCT * * Reads a product by its ID. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The product in JSON format. * @throws {Error} If the product is not found in the database. */ exports.readProduct = (req, res) => { - Product - .findByPk(parseInt(req.params.id)) + const ID = parseInt(req.params.id); + + Product.findByPk(ID) .then((product) => { res.status(200).json(product) }) - .catch(() => res.status(404).json({ message: process.env.PRODUCT_NOT_FOUND })); + .catch(() => res.status(404).json({ message: PRODUCT_NOT_FOUND })); } //! ******************** PRIVATE ******************** @@ -172,7 +114,6 @@ exports.readProduct = (req, res) => { /** * ? CREATE PRODUCT * * Creates a new product. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function @@ -180,41 +121,44 @@ exports.readProduct = (req, res) => { * @throws {Error} If the product is not created. */ exports.createProduct = (req, res, next) => { + const { PRODUCT_CREATED, PRODUCT_NOT_CREATED } = process.env; + form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkProductData(fields.name, fields.description, fields.alt, fields.price, fields.cat, res); + const { alt, cat, description, name, price } = fields; + const { image } = files; + + this.checkProductData(name, description, alt, price, cat, res); - Product - .findAll() + Product.findAll() .then((products) => { - for (let product of products) { this.checkProductUnique(fields.name, fields.description, product, res) } + for (let product of products) { + this.checkProductUnique(name, description, product, res) + } - let options = nem.getArrayFromString(fields.options); - let image = nem.getName(fields.name) + "." + process.env.IMG_EXT; - this.setImage(image, files.image.newFilename); + const IMG = nem.getName(fields.name) + "." + IMG_EXT; + const product = { ...fields, image: IMG }; - let product = this.getProduct( - fields.name, fields.description, image, fields.alt, fields.price, options, fields.cat - ); + if (image && image.newFilename) this.setImage(IMG, image.newFilename); - Product - .create(product) + Product.create(product) .then(() => { - fs.unlink(PRODUCTS_IMG + files.image.newFilename, () => { - res.status(201).json({ message: process.env.PRODUCT_CREATED }) - }) + if (image && image.newFilename) { + fs.unlink(PRODUCTS_IMG + image.newFilename, () => { + res.status(201).json({ message: PRODUCT_CREATED }) + }) + } }) - .catch(() => res.status(400).json({ message: process.env.PRODUCT_NOT_CREATED })); + .catch(() => res.status(400).json({ message: PRODUCT_NOT_CREATED })); }) - .catch(() => res.status(404).json({ message: process.env.PRODUCTS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: PRODUCTS_NOT_FOUND })); }) }; /** * ? UPDATE PRODUCT * * Updates a product. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function @@ -222,60 +166,62 @@ exports.createProduct = (req, res, next) => { * @throws {Error} If the product is not updated. */ exports.updateProduct = (req, res, next) => { - const id = parseInt(req.params.id); + const { PRODUCT_NOT_UPDATED, PRODUCT_UPDATED } = process.env; + const ID = parseInt(req.params.id); form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkProductData(fields.name, fields.description, fields.alt, fields.price, fields.cat, res); + const { name, description, alt, price, cat } = fields; + const { image } = files; + + this.checkProductData(name, description, alt, price, cat, res); - Product - .findAll() + Product.findAll() .then((products) => { - this.checkProductsForUnique(id, products, fields, res); + products.filter(product => product.id !== ID).forEach(product => + this.checkProductUnique(name, description, product, res)); - let image = nem.getName(fields.name) + "." + process.env.IMG_EXT; - if (files.image) this.setImage(image, files.image.newFilename); + const IMG = nem.getName(name) + "." + IMG_EXT; + const product = { ...fields, image: IMG }; - let options = nem.getArrayFromString(fields.options); - let product = this.getProduct(fields.name, fields.description, image, fields.alt, fields.price, options, fields.cat); + if (image && image.newFilename) this.setImage(IMG, image.newFilename); - Product - .update(product, { where: { id: id }}) + Product.update(product, { where: { id: ID }}) .then(() => { - if (files.image) fs.unlink(PRODUCTS_IMG + files.image.newFilename, () => { }); - res.status(200).json({ message: process.env.PRODUCT_UPDATED }); + if (image && image.newFilename) { + fs.unlink(PRODUCTS_IMG + image.newFilename, () => {}) + } + res.status(200).json({ message: PRODUCT_UPDATED }); }) - .catch(() => res.status(400).json({ message: process.env.PRODUCT_NOT_UPDATED })); + .catch(() => res.status(400).json({ message: PRODUCT_NOT_UPDATED })); }) - .catch(() => res.status(404).json({ message: process.env.PRODUCTS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: PRODUCTS_NOT_FOUND })); }) }; /** * ? DELETE PRODUCT * * Deletes a product from the database. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} A message indicating that the product was deleted. * @throws {Error} If the product is not found in the database. */ exports.deleteProduct = (req, res) => { - const id = parseInt(req.params.id); + const { PRODUCT_DELETED, PRODUCT_NOT_DELETED } = process.env; + const ID = parseInt(req.params.id); - Product - .findByPk(id) + Product.findByPk(ID) .then(product => { fs.unlink(PRODUCTS_THUMB + product.image, () => { fs.unlink(PRODUCTS_IMG + product.image, () => { - Product - .destroy({ where: { id: id }}) - .then(() => res.status(204).json({ message: process.env.PRODUCT_DELETED })) - .catch(() => res.status(400).json({ message: process.env.PRODUCT_NOT_DELETED })) + Product.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: PRODUCT_DELETED })) + .catch(() => res.status(400).json({ message: PRODUCT_NOT_DELETED })) }) }) }) - .catch(() => res.status(404).json({ message: process.env.PRODUCT_NOT_FOUND })); + .catch(() => res.status(404).json({ message: PRODUCT_NOT_FOUND })); } diff --git a/controller/UserCtrl.js b/controller/UserCtrl.js index 6678463..e635a14 100644 --- a/controller/UserCtrl.js +++ b/controller/UserCtrl.js @@ -8,18 +8,19 @@ const nem = require("nemjs"); require("dotenv").config(); +const { IMG_EXT, USER_NOT_FOUND, USER_NOT_PASS, USERS_NOT_FOUND } = process.env; + const USERS_IMG = process.env.IMG_URL + "users/"; const USERS_THUMB = process.env.THUMB_URL + "users/"; const form = formidable({ uploadDir: USERS_IMG, keepExtensions: true }); const User = db.user; -//! ******************** CHECKERS ******************** +//! ******************** UTILS ******************** /** * ? CHECK USER DATA - * * Validates user data & returns a JSON response with an error message if any validation fails. - * + * * Validates user data & returns a JSON response with an error message if it fails. * @param {string} name - The user's name. * @param {string} email - The user's email. * @param {string} role - The user's role. @@ -27,36 +28,33 @@ const User = db.user; * @return {object} - JSON response with an error message if any validation fails. */ exports.checkUserData = (name, email, role, res) => { - const MAX = process.env.STRING_MAX; - const MIN = process.env.STRING_MIN; - - let alert = ""; - - if (!nem.checkRange(role, MIN, MAX)) alert = process.env.CHECK_ROLE; - if (!nem.checkEmail(email)) alert = process.env.CHECK_EMAIL; - if (!nem.checkRange(name, MIN, MAX)) alert = process.env.CHECK_NAME; - - if (alert !== "") return res.status(403).json({ message: alert }); + const { CHECK_EMAIL, CHECK_NAME, CHECK_ROLE, STRING_MAX, STRING_MIN } = process.env; + + if ( + !nem.checkRange(role, STRING_MIN, STRING_MAX) || + !nem.checkEmail(email) || + !nem.checkRange(name, STRING_MIN, STRING_MAX) + ) { + return res.status(403).json({ message: CHECK_ROLE || CHECK_EMAIL || CHECK_NAME }); + } } /** * ? CHECK USER PASSWORD * * Checks if the user password is valid. - * * @param {string} pass - The user password to be checked. * @param {object} res - The response object. * @return {object} - The response object with an error message if the password is invalid. */ exports.checkUserPass = (pass, res) => { - if (!nem.checkPass(pass)) { - return res.status(403).json({ message: process.env.CHECK_PASS }) - } + const { CHECK_PASS } = process.env; + + if (!nem.checkPass(pass)) return res.status(403).json({ message: CHECK_PASS }); } /** * ? CHECK USER UNIQUE * * Checks if the given user's name & email are unique. - * * @param {string} name - The name to check against the user's name. * @param {string} email - The email to check against the user's email. * @param {object} user - The user object to compare against. @@ -64,137 +62,18 @@ exports.checkUserPass = (pass, res) => { * @return {object} The JSON response containing the error message if the name or email is not unique. */ exports.checkUserUnique = (name, email, user, res) => { - if (user.name === name) { - return res.status(403).json({ message: process.env.DISPO_NAME }); - } - - if (user.email === email) { - return res.status(403).json({ message: process.env.DISPO_EMAIL }); - } -} - -/** - * ? CHECK USERS FOR UNIQUE - * * Checks if users in the given array have unique fields except for the user with the given id, - * * & calls the checkUserUnique function for each non-matching user. - * - * @param {string} id - The id of the user to exclude from the uniqueness check. - * @param {Array} users - The array of user objects to check. - * @param {Object} fields - The fields object containing the name & email fields to check for uniqueness. - * @param {Object} res - The response object to send the result of the uniqueness check. - */ -exports.checkUsersForUnique = (id, users, fields, res) => { - for (let user of users) { - if (user.id !== id) { - this.checkUserUnique(fields.name, fields.email, user, res) - } - } -} - -//! ******************** GETTERS ******************** + const { DISPO_EMAIL, DISPO_NAME } = process.env; -/** - * ? GET USER CREATED - * * Returns an object with the user's information. - * - * @param {string} name - The name of the user. - * @param {string} email - The email of the user. - * @param {string} image - The image of the user. - * @param {string} pass - The password of the user. - * @param {string} role - The role of the user. - * @param {string} created - The creation date of the user. - * @param {string} updated - The update date of the user. - * @return {Object} - An object containing the user's information. - */ -exports.getUserCreated = (name, email, image, pass, role, created, updated) => { - - return { - name: name, - email: email, - image: image, - pass: pass, - role: role, - created: created, - updated: updated + if (user.name === name || user.email === email) { + return res.status(403).json({ message: DISPO_NAME || DISPO_EMAIL }) } } -/** - * ? GET USER WITH PASSWORD - * * Returns a user object with the password field. - * - * @param {string} name - The name of the user. - * @param {string} email - The email address of the user. - * @param {string} image - The image URL of the user. - * @param {string} pass - The password of the user. - * @param {string} role - The role of the user. - * @param {string} updated - The date of the last update. - * @return {object} - The user object with the provided properties. - */ -exports.getUserWithPass = (name, email, image, pass, role, updated) => { - - return { - name: name, - email: email, - image: image, - pass: pass, - role: role, - updated: updated - } -} - -/** - * ? GET USER NO PASSWORD - * * Returns a user object without the password field. - * - * @param {string} name - The name of the user. - * @param {string} email - The email address of the user. - * @param {string} image - The URL of the user's profile image. - * @param {string} role - The role of the user. - * @param {string} updated - The date when the user was last updated. - * @return {Object} - The user object without the password field. - */ -exports.getUserNoPass = (name, email, image, role, updated) => { - - return { - name: name, - email: email, - image: image, - role: role, - updated: updated - } -} - -//! ******************** SETTERS ******************** - -/** - * ? SET MESSAGE - * * Sets the message using the provided fields & sends it via email. - * - * @param {object} fields - The fields containing the necessary information to construct the message. - * @param {object} res - The response object used to send the HTTP response. - * @return {undefined} This function does not return anything. - */ -exports.setMessage = (fields, res) => { - const mailer = nem.getMailer(); - - (async function () { - try { - let mail = nem.getMessage(fields); - - await mailer.sendMail(mail, function () { - res.status(202).json({ message: process.env.USER_MESSAGE }); - }); - } catch (e) { console.error(e); } - })(); -} - //! ******************** PUBLIC ******************** /** * ? CREATE USER * * Creates a new user. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -202,53 +81,70 @@ exports.setMessage = (fields, res) => { * @throws {Error} If the user is not created. */ exports.createUser = (req, res, next) => { + const { USER_CREATED, USER_NOT_CREATED } = process.env; + form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkUserData(fields.name, fields.email, fields.role, res); - this.checkUserPass(fields.pass, res); + const { name, email, role, pass } = fields; + const { image } = files; - User - .findAll() - .then((users) => { - for (let user of users) { this.checkUserUnique(fields.name, fields.email, user, res) } + const IMG = nem.getName(name) + "." + IMG_EXT; - let image = nem.getName(fields.name) + "." + process.env.IMG_EXT; - nem.setThumbnail("users/" + files.image.newFilename, USERS_THUMB + image); + this.checkUserData(name, email, role, res); + this.checkUserPass(pass, res); - bcrypt - .hash(fields.pass, 10) + User.findAll() + .then((users) => { + for (const user of users) this.checkUserUnique(name, email, user, res); + if (image && image.newFilename) { + nem.setThumbnail("users/" + image.newFilename, USERS_THUMB + IMG); + } + + bcrypt.hash(pass, 10) .then((hash) => { - let user = this.getUserCreated(fields.name, fields.email, image, hash, fields.role, fields.created, fields.updated); + const user = { ...fields, image: IMG, pass: hash }; - User - .create(user) + User.create(user) .then(() => { - fs.unlink(USERS_IMG + files.image.newFilename, () => { res.status(201).json({ message: process.env.USER_CREATED }) }) + if (image && image.newFilename) { + fs.unlink(USERS_IMG + image.newFilename, () => { + res.status(201).json({ message: USER_CREATED }) + }) + } }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_CREATED })); - + .catch(() => res.status(400).json({ message: USER_NOT_CREATED })); }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_PASS })); + .catch(() => res.status(400).json({ message: USER_NOT_PASS })); }) - .catch(() => { res.status(404).json({ message: process.env.USERS_NOT_FOUND }) }); + .catch(() => { res.status(404).json({ message: USERS_NOT_FOUND })}); }); } /** * ? SEND USER MESSAGE * * Sends a message. - * * @param {Object} req - the request object * @param {Object} res - the response object * @param {Function} next - the next middleware function */ exports.sendMessage = (req, res, next) => { + const { USER_MESSAGE } = process.env; + const mailer = nem.getMailer(); + form.parse(req, (err, fields) => { if (err) { next(err); return } + const mail = nem.getMessage(fields); fields.html = `

${fields.html}

`; - this.setMessage(fields, res); + + (async function () { + try { + await mailer.sendMail(mail, function () { + res.status(202).json({ message: USER_MESSAGE }) + }); + } catch (e) { console.error(e) } + })(); }) } @@ -257,56 +153,48 @@ exports.sendMessage = (req, res, next) => { /** * ? LIST ALL USERS WITHOUT PASSWORD * * Retrieves the list of users. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The list of users in JSON format. * @throws {Error} If the users are not found in the database. */ exports.listUsers = (req, res) => { - User - .findAll() - .then((users) => { - let usersList = []; + const usersList = []; - for (let user of users) { - let userSafe = { + User.findAll() + .then((users) => { + for (const user of users) { + const userSafe = { id: user.id, name: user.name, email: user.email, image: user.image, - role: user.role, - created: user.created, - updated: user.updated, + role: user.role }; - usersList.push(userSafe); } res.status(200).json(usersList); }) - .catch(() => res.status(404).json({ message: process.env.USERS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USERS_NOT_FOUND })); } /** * ? READ A USER * * Retrieves a user by their ID & sends a JSON response. - * * @param {object} req - The request object. * @param {object} res - The response object. * @return {object} The user data in JSON format. * @throws {Error} If the user is not found in the database. */ exports.readUser = (req, res) => { - User - .findByPk(parseInt(req.params.id)) + User.findByPk(parseInt(req.params.id)) .then((user) => res.status(200).json(user)) - .catch(() => res.status(404).json({ message: process.env.USER_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USER_NOT_FOUND })); } /** * ? UPDATE USER * * Updates a user based on the provided request data. - * * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Function} next - The next middleware function. @@ -314,77 +202,73 @@ exports.readUser = (req, res) => { * @throws {Error} If the user is not updated in the database. */ exports.updateUser = (req, res, next) => { - const id = parseInt(req.params.id); + const { USER_NOT_UPDATED, USER_UPDATED } = process.env; form.parse(req, (err, fields, files) => { if (err) { next(err); return } - this.checkUserData(fields.name, fields.email, fields.role, res); + const { name, email, role, pass } = fields; + const { image } = files; + + const ID = parseInt(req.params.id); + const IMG = nem.getName(name) + "." + IMG_EXT; + + let user; + this.checkUserData(name, email, role, res); - User - .findAll() + User.findAll() .then((users) => { - this.checkUsersForUnique(id, users, fields, res); - - let image = nem.getName(fields.name) + "." + process.env.IMG_EXT; - if (files.image) nem.setThumbnail("users/" + files.image.newFilename, USERS_THUMB + image); - - if (fields.pass) { - this.checkUserPass(fields.pass, res); - - bcrypt - .hash(fields.pass, 10) - .then((hash) => { - let user = this.getUserWithPass(fields.name, fields.email, image, hash, fields.role, fields.updated); - - User - .update(user, { where: { id: id }}) - .then(() => { - if (files.image) fs.unlink(USERS_IMG + files.image.newFilename, () => { }); - res.status(200).json({ message: process.env.USER_UPDATED }); - }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_UPDATED })); - }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_PASS })); - - } else { - let user = this.getUserNoPass(fields.name, fields.email, image, fields.role, fields.updated); - - User - .update(user, { where: { id: id }}) - .then(() => { - if (files.image) fs.unlink(USERS_IMG + files.image.newFilename, () => { }); - res.status(200).json({ message: process.env.USER_UPDATED }); - }) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_UPDATED })); + users.filter(user => user.id !== ID).forEach(user => + this.checkUserUnique(name, email, user, res)); + + if (image && image.newFilename) { + nem.setThumbnail("users/" + image.newFilename, USERS_THUMB + IMG) } + + if (pass) { + this.checkUserPass(pass, res); + + bcrypt.hash(pass, 10) + .then((hash) => { user = { ...fields, image: IMG, pass: hash }}) + .catch(() => res.status(400).json({ message: USER_NOT_PASS })); + + } else { + user = { ...fields, image: IMG } + } + + User.update(user, { where: { id: ID }}) + .then(() => { + if (image && image.newFilename) { + fs.unlink(USERS_IMG + image.newFilename, () => {}) + } + res.status(200).json({ message: USER_UPDATED }); + }) + .catch(() => res.status(400).json({ message: USER_NOT_UPDATED })); }) - .catch(() => res.status(404).json({ message: process.env.USERS_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USERS_NOT_FOUND })); }) } /** * ? DELETE USER - * * Deletes a user and associated comments & reviews from the database. - * + * * Deletes a user, associated comments & reviews from the database. * @param {Object} req - The request object containing the user id in the params. * @param {Object} res - The response object to send the result. - * @return {Object} The response object with a status & JSON message indicating success or failure. + * @return {Object} The response object with a status & JSON message. * @throws {Error} If the user is not deleted from the database. */ exports.deleteUser = (req, res) => { - const id = parseInt(req.params.id); + const { USER_DELETED, USER_NOT_DELETED } = process.env; + const ID = parseInt(req.params.id); - User - .findByPk(id) + User.findByPk(ID) .then(user => { fs.unlink(USERS_THUMB + user.image, () => { - User - .destroy({ where: { id: id }}) - .then(() => res.status(204).json({ message: process.env.USER_DELETED })) - .catch(() => res.status(400).json({ message: process.env.USER_NOT_DELETED })) + User.destroy({ where: { id: ID }}) + .then(() => res.status(204).json({ message: USER_DELETED })) + .catch(() => res.status(400).json({ message: USER_NOT_DELETED })) }) }) - .catch(() => res.status(404).json({ message: process.env.USER_NOT_FOUND })); + .catch(() => res.status(404).json({ message: USER_NOT_FOUND })); } diff --git a/package-lock.json b/package-lock.json index e8ed8dd..3025d1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nens", - "version": "0.2.0-alpha", + "version": "0.2.1-alpha", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nens", - "version": "0.2.0-alpha", + "version": "0.2.1-alpha", "license": "Apache-2.0 License", "dependencies": { "bcrypt": "^5.1.0", diff --git a/package.json b/package.json index 990d9ba..763226e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nens", - "version": "0.2.0-alpha", + "version": "0.2.1-alpha", "description": "API with Node, Express, NemJS & SQL", "keywords": [ "api",