diff --git a/src/index.ts b/src/index.ts index 273f1c8f87ed8f7aa7379342ed737386887341ec..0181a400f7831df7b7bec7e6a19aa454a988d008 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import "./utils/env"; +import { ErrorHandler, handleError } from "./middlewares/utils/ErrorHandler"; import express, { Application, NextFunction, Request, Response } from "express"; import authRoute from "./routes/auth"; @@ -74,10 +75,11 @@ cardRoute(app); warningsRoute(app); app.use((err: any, req: Request, res: Response, next: NextFunction) => { - res.status(500).send("Houston, we have a problem!"); + if (err instanceof ErrorHandler) return handleError(err, res); //Flush out the stack to the console console.error(err.stack); + res.status(500).send("Houston, we have a problem!"); }); app.listen(8000, () => console.log(`Example app listening on port 8000!`)); diff --git a/src/middlewares/auth/complete.ts b/src/middlewares/auth/complete.ts index 3a329b2fafd3ef71e8133518b37d063df9e0e1e2..d53beb27813200edd4f230e5dff1282c70cc5268 100644 --- a/src/middlewares/auth/complete.ts +++ b/src/middlewares/auth/complete.ts @@ -1,4 +1,4 @@ -import { Request, Response } from "express"; +import { NextFunction, Request, Response } from "express"; import { oauth2, scope } from "../../utils/auth"; import Profile from "../../models/ProfileSchema"; @@ -12,32 +12,41 @@ import axios from "axios"; * If the user is registered, then the Profile object * id from the database will be added to session.profile.id */ -const complete = () => async (req: Request, res: Response) => { - const tokenConfig = { - code: String(req.query.code), - scope: scope, - redirect_uri: "", - }; - - const token = await oauth2().authorizationCode.getToken(tokenConfig); - - const response = await axios.get<authschResponse>( - `https://auth.sch.bme.hu/api/profile/?access_token=${token.access_token}` - ); - - req.session!.user = { - external_id: String(response.data.internal_id), - email: String(response.data.mail), - name: `${response.data.sn} ${response.data.givenName}`, - token, - }; - - const profile = await Profile.findOne({ - external_id: response.data.internal_id, - }).lean(); - if (!!profile) req.session!.user.id = profile.id; - - return res.redirect(process.env.REDIRECT_URI || "/"); +const complete = () => async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const tokenConfig = { + code: String(req.query.code), + scope: scope, + redirect_uri: "", + }; + + const token = await oauth2().authorizationCode.getToken(tokenConfig); + + const response = await axios.get<authschResponse>( + `https://auth.sch.bme.hu/api/profile/?access_token=${token.access_token}` + ); + + req.session!.user = { + external_id: String(response.data.internal_id), + email: String(response.data.mail), + name: `${response.data.sn} ${response.data.givenName}`, + token, + }; + + const profile = await Profile.findOne({ + external_id: response.data.internal_id, + }).lean(); + + if (profile) req.session!.user.id = profile._id; + + return res.redirect(process.env.REDIRECT_URI || "/"); + } catch (err) { + next(err); + } }; export default complete; diff --git a/src/middlewares/auth/logout.ts b/src/middlewares/auth/logout.ts index 41ea05e8efdc7d2d533ae971742e06199b6052b7..c3a150c09c9e0fc891cbc8a303f47da369007dad 100644 --- a/src/middlewares/auth/logout.ts +++ b/src/middlewares/auth/logout.ts @@ -1,11 +1,19 @@ -import { Request, Response } from "express"; +import { NextFunction, Request, Response } from "express"; /** * Logs out the user by destroying the session */ -const logout = () => async (req: Request, res: Response) => { - await req.session!.destroy(() => console.log("user logged out.")); - res.redirect("/"); +const logout = () => async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + await req.session!.destroy(() => console.log("user logged out.")); + res.redirect("/"); + } catch (err) { + next(err); + } }; export default logout; diff --git a/src/middlewares/auth/refreshToken.ts b/src/middlewares/auth/refreshToken.ts index 4a21a6a459ae7896873b5b16292cd68a65a90b7d..bc7303be1cd5e25317dc21cc71a1cd023781a7d7 100644 --- a/src/middlewares/auth/refreshToken.ts +++ b/src/middlewares/auth/refreshToken.ts @@ -10,13 +10,17 @@ const refreshToken = () => async ( res: Response, next: NextFunction ) => { - if (req.session && req.session.user) { - let accessToken = oauth2().accessToken.create(req.session.user.token); - if (accessToken.expired()) { - req.session.user.token = (await accessToken.refresh()).token; + try { + if (req.session && req.session.user) { + let accessToken = oauth2().accessToken.create(req.session.user.token); + if (accessToken.expired()) { + req.session.user.token = (await accessToken.refresh()).token; + } } + next(); + } catch (err) { + next(err); } - next(); }; export default refreshToken; diff --git a/src/middlewares/cards/addCard.ts b/src/middlewares/cards/addCard.ts index 5e77e8b8aa8b0602cf5edb1ef4f96cbba513f14d..06c620304a0da9f2de122d126dafcc83f40618a7 100644 --- a/src/middlewares/cards/addCard.ts +++ b/src/middlewares/cards/addCard.ts @@ -1,6 +1,7 @@ import { NextFunction, Request, Response } from "express"; import Card from "../../models/CardSchema"; +import { ErrorHandler } from "../utils/ErrorHandler"; import Profile from "../../models/ProfileSchema"; import { validateFields } from "../utils/validateFields"; @@ -19,29 +20,37 @@ const addCard = () => async ( res: Response, next: NextFunction ) => { - // Register - const newCard = new Card(); + try { + // Register + const newCard = new Card(); - // Validate and set fields from request body - validateFields({ fields, reqBody: req.body }); - fields.forEach((field) => { - const value = req.body[field.name]; - if (value) newCard.set(field.name, req.body[field.name]); - }); + // Validate and set fields from request body + validateFields({ fields, reqBody: req.body }); + fields.forEach((field) => { + const value = req.body[field.name]; + if (value) newCard.set(field.name, req.body[field.name]); + }); - // Find and remove old card - const oldCard = await Card.findOne({ userId: newCard.userId }).lean().exec(); - if (oldCard) await Card.deleteOne({ userId: newCard.userId }).lean().exec(); + // Find and remove old card + const oldCard = await Card.findOne({ userId: newCard.userId }) + .lean() + .exec(); + if (oldCard) await Card.deleteOne({ userId: newCard.userId }).lean().exec(); - const profile = await Profile.findById(newCard.userId).lean().exec(); + const profile = await Profile.findById(newCard.userId).lean().exec(); - newCard.fullName = profile!.name; - newCard.roomNumber = profile!.roomNumber; + if (!profile) throw new ErrorHandler(400, "User doesn't exist"); - await newCard.save(); - res.data.card = newCard; + newCard.fullName = profile!.name; + newCard.roomNumber = profile!.roomNumber; - next(); + await newCard.save(); + res.data.card = newCard; + + next(); + } catch (err) { + next(err); + } }; export default addCard; diff --git a/src/middlewares/cards/getCard.ts b/src/middlewares/cards/getCard.ts index 99dec4c8afe67b815499e6f0c3685742b3bbe74b..58106bdc38f65e1accb4e5bdd2772cc13406f682 100644 --- a/src/middlewares/cards/getCard.ts +++ b/src/middlewares/cards/getCard.ts @@ -12,9 +12,13 @@ const getCard = () => async ( res: Response, next: NextFunction ) => { - res.data.card = await Card.findById(req.params.id).lean(); + try { + res.data.card = await Card.findById(req.params.id).lean(); - next(); + next(); + } catch (err) { + next(err); + } }; export default getCard; diff --git a/src/middlewares/cards/getCardList.ts b/src/middlewares/cards/getCardList.ts index 1eacce1cd2a02d6b111cd06551b95ca1160350e6..4c76a26237ea947fb756b6d73ae93f1727044f1f 100644 --- a/src/middlewares/cards/getCardList.ts +++ b/src/middlewares/cards/getCardList.ts @@ -11,8 +11,12 @@ const getCardList = () => async ( res: Response, next: NextFunction ) => { - res.data.cards = await Card.find(); - next(); + try { + res.data.cards = await Card.find().lean().exec(); + next(); + } catch (err) { + next(err); + } }; export default getCardList; diff --git a/src/middlewares/cards/getCardListValid.ts b/src/middlewares/cards/getCardListValid.ts index e5c99d30fca4bcd9e86a8b60fe1dd534ce55d0aa..42b912b725d7dd25f0c340fb36e5be0fca267c9e 100644 --- a/src/middlewares/cards/getCardListValid.ts +++ b/src/middlewares/cards/getCardListValid.ts @@ -12,10 +12,16 @@ const getCardListValid = () => async ( res: Response, next: NextFunction ) => { - res.data.cards = await Card.find({ - expirationDate: { $gte: new Date() }, - }).lean(); - next(); + try { + res.data.cards = await Card.find({ + expirationDate: { $gte: new Date() }, + }) + .lean() + .exec(); + next(); + } catch (err) { + next(err); + } }; export default getCardListValid; diff --git a/src/middlewares/files/card/cardImageStorage.ts b/src/middlewares/files/card/cardImageStorage.ts index 8372d0dc883ea5d4009ce39a7789759d3ed57c0b..f9132f439581ca685bf465a114d719d1e6bc4a2b 100644 --- a/src/middlewares/files/card/cardImageStorage.ts +++ b/src/middlewares/files/card/cardImageStorage.ts @@ -5,7 +5,13 @@ export const cardImageStorage = multer.diskStorage({ callback(null, "uploads/card_image/"); }, filename: function (req, file, callback) { - callback(null, Date.now() + "-" + file.originalname); + const fileExtension = file.originalname.substring( + file.originalname.lastIndexOf(".") + ); + callback( + null, + Date.now() + "-" + Math.random().toString(36).substring(7) + fileExtension + ); }, }); diff --git a/src/middlewares/files/card/getCardImage.ts b/src/middlewares/files/card/getCardImage.ts index 39a7cd009680d7ea424d391dd6d02dcc83327712..323292098f719a6ec4e935eab803eee5c0a707e0 100644 --- a/src/middlewares/files/card/getCardImage.ts +++ b/src/middlewares/files/card/getCardImage.ts @@ -11,8 +11,12 @@ const getCardImage = () => async ( res: Response, next: NextFunction ) => { - res.data.cardImage = await CardImage.findOne().lean().exec(); - next(); + try { + res.data.cardImage = await CardImage.findOne().lean().exec(); + next(); + } catch (err) { + next(err); + } }; export default getCardImage; diff --git a/src/middlewares/files/card/getUserCard.ts b/src/middlewares/files/card/getUserCard.ts index 59947d0d1debb6b1c88cb214934c605d423a7db1..e1e35121f6bfeced11f4abab806d3003bb73b5b3 100644 --- a/src/middlewares/files/card/getUserCard.ts +++ b/src/middlewares/files/card/getUserCard.ts @@ -12,49 +12,55 @@ const getUserCard = (): any => async ( res: Response, next: NextFunction ) => { - const userCard = await Card.findOne({ userId: res.data.profile?.id }) - .lean() - .exec(); - if (!userCard) - return res.status(404).json({ message: "The user doesn't have any card!" }); - - let profilePicture = "data:image/png;base64,"; - if (!res.data.profile!.pictureId) { - profilePicture += fs.readFileSync( - "src/utils/card/profile_picture.png", - "base64" - ); - } else { - const profilePicFile = await File.findById(res.data.profile!.pictureId) + try { + const userCard = await Card.findOne({ userId: res.data.profile?._id }) .lean() .exec(); - profilePicture += fs.readFileSync(profilePicFile!.path, "base64"); - } + if (!userCard) + return res + .status(404) + .json({ message: "The user doesn't have any card!" }); - let bgPicture = "data:image/png;base64,"; - if (!res.data.cardImage) - bgPicture += fs.readFileSync("src/utils/card/background.png", "base64"); - else { - const bgFile = await File.findById(res.data.cardImage.imageId) - .lean() - .exec(); - bgPicture += fs.readFileSync(bgFile!.path, "base64"); - } + let profilePicture = "data:image/png;base64,"; + if (!res.data.profile!.pictureId) { + profilePicture += fs.readFileSync( + "src/utils/card/profile_picture.png", + "base64" + ); + } else { + const profilePicFile = await File.findById(res.data.profile!.pictureId) + .lean() + .exec(); + profilePicture += fs.readFileSync(profilePicFile!.path, "base64"); + } + + let bgPicture = "data:image/png;base64,"; + if (!res.data.cardImage) + bgPicture += fs.readFileSync("src/utils/card/background.png", "base64"); + else { + const bgFile = await File.findById(res.data.cardImage.imageId) + .lean() + .exec(); + bgPicture += fs.readFileSync(bgFile!.path, "base64"); + } - const svg = fs.readFileSync("src/utils/card/template.svg", "utf8"); + const svg = fs.readFileSync("src/utils/card/template.svg", "utf8"); - const result = svg - .replace(/{{profile_picture}}/g, profilePicture) - .replace(/{{background_image}}/g, bgPicture) - .replace(/{{full_name}}/g, String(userCard?.fullName)) - .replace(/{{room_number}}/g, String(userCard?.roomNumber)) - .replace(/{{card_number}}/g, String(userCard?.cardId)) - .replace( - /{{expiration_date}}/g, - String(userCard?.expirationDate.toISOString().split("T")[0]) - ); + const result = svg + .replace(/{{profile_picture}}/g, profilePicture) + .replace(/{{background_image}}/g, bgPicture) + .replace(/{{full_name}}/g, String(userCard?.fullName)) + .replace(/{{room_number}}/g, String(userCard?.roomNumber)) + .replace(/{{card_number}}/g, String(userCard?.cardId)) + .replace( + /{{expiration_date}}/g, + String(userCard?.expirationDate.toISOString().split("T")[0]) + ); - return res.type("svg").send(result); + return res.type("svg").send(result); + } catch (err) { + next(err); + } }; export default getUserCard; diff --git a/src/middlewares/files/card/responseCardImage.ts b/src/middlewares/files/card/responseCardImage.ts index bc11170d51a6e54a1395107375d3691144cf0d4f..a5a52bb27733615d26df3f6e048d6b9f580b06c6 100644 --- a/src/middlewares/files/card/responseCardImage.ts +++ b/src/middlewares/files/card/responseCardImage.ts @@ -1,18 +1,26 @@ -import { Request, Response } from "express"; +import { NextFunction, Request, Response } from "express"; import File from "../../../models/FileSchema"; /** * Return the Entry card background Image */ -const responseCardImage = (): any => async (req: Request, res: Response) => { - if (!res.data.cardImage) - return res.sendFile("src/utils/card/background.png", { root: "." }); +const responseCardImage = (): any => async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + if (!res.data.cardImage) + return res.sendFile("src/utils/card/background.png", { root: "." }); - const cardImage = await File.findById(res.data.cardImage.imageId) - .lean() - .exec(); - return res.sendFile(cardImage!.path, { root: "." }); + const cardImage = await File.findById(res.data.cardImage.imageId) + .lean() + .exec(); + return res.sendFile(cardImage!.path, { root: "." }); + } catch (err) { + next(err); + } }; export default responseCardImage; diff --git a/src/middlewares/files/card/uploadCardImage.ts b/src/middlewares/files/card/uploadCardImage.ts index a0df799ff034a4301eb5bac8afdb31b0d55d25da..10fe5b55c96f9dff0c592368db1f352a0fe5d1d2 100644 --- a/src/middlewares/files/card/uploadCardImage.ts +++ b/src/middlewares/files/card/uploadCardImage.ts @@ -12,39 +12,40 @@ const uploadCardImage = () => async ( res: Response, next: NextFunction ) => { - const oldCardImage = await CardImage.findOne().lean().exec(); - - if (oldCardImage) { - const oldFile = await File.findByIdAndRemove(oldCardImage.imageId) - .lean() - .exec(); - - fs.unlink(oldFile!.path, (err) => { - throw err; - }); - } - - const newFile = new File(); - newFile.originalName = req.file.originalname; - newFile.uploadDate = new Date(); - newFile.path = req.file.path; - newFile.mimeType = req.file.mimetype; - - await newFile.save(); - - if (oldCardImage) { - await CardImage.updateOne( - { _id: oldCardImage?.id }, - { imageId: String(newFile.id) } - ).exec(); - } else { - const cardImage = new CardImage(); - cardImage.imageId = String(newFile.id); - - await cardImage.save(); + try { + const oldCardImage = await CardImage.findOne().lean().exec(); + + if (oldCardImage) { + const oldFile = await File.findByIdAndRemove(oldCardImage.imageId) + .lean() + .exec(); + if (oldFile) await fs.unlinkSync(oldFile!.path); + } + + const newFile = new File(); + newFile.originalName = req.file.originalname; + newFile.uploadDate = new Date(); + newFile.path = req.file.path; + newFile.mimeType = req.file.mimetype; + + await newFile.save(); + + if (oldCardImage) { + await CardImage.updateOne( + { _id: oldCardImage?._id }, + { imageId: String(newFile._id) } + ).exec(); + } else { + const cardImage = new CardImage(); + cardImage.imageId = String(newFile._id); + + await cardImage.save(); + } + + return res.status(200).send(); + } catch (err) { + next(err); } - - return res.status(200).send(); }; export default uploadCardImage; diff --git a/src/middlewares/files/handleFileValidationError.ts b/src/middlewares/files/handleFileValidationError.ts index b77f3be5680284448fb36d645b45b17415e6972f..0bdf0f873267ba1f3c6fd0e362c828a42654336d 100644 --- a/src/middlewares/files/handleFileValidationError.ts +++ b/src/middlewares/files/handleFileValidationError.ts @@ -9,7 +9,7 @@ const handleFileValidationError = () => async ( next: NextFunction ) => { if (req.fileValidationError) { - res.status(400).send(req.fileValidationError); + return res.status(400).send(req.fileValidationError); } if (!req.file) { return res.status(400).send("File wasn't provided!"); diff --git a/src/middlewares/files/profile/getProfilePicture.ts b/src/middlewares/files/profile/getProfilePicture.ts index 6429e14d01bbae8f5ced64eac266133795775bf6..660beab170d280d365f7530fe6319e611e9bf865 100644 --- a/src/middlewares/files/profile/getProfilePicture.ts +++ b/src/middlewares/files/profile/getProfilePicture.ts @@ -10,13 +10,17 @@ const getProfilePicture = () => async ( res: Response, next: NextFunction ) => { - if (!res.data.profile!.pictureId) - return res - .status(400) - .send({ message: "You dont have a profile picture!" }); + try { + if (!res.data.profile!.pictureId) + return res + .status(400) + .send({ message: "You dont have a profile picture!" }); - const file = await File.findById(res.data.profile!.pictureId).lean().exec(); - return res.sendFile(file!.path, { root: "." }); + const file = await File.findById(res.data.profile!.pictureId).lean().exec(); + return res.sendFile(file!.path, { root: "." }); + } catch (err) { + next(err); + } }; export default getProfilePicture; diff --git a/src/middlewares/files/profile/profilePictureStorage.ts b/src/middlewares/files/profile/profilePictureStorage.ts index 2252de35e4c93ed3fe44f95a8365df6e0ec7c5ac..3ce61b9ee3e42f73925838a9760492c9c2bb48e1 100644 --- a/src/middlewares/files/profile/profilePictureStorage.ts +++ b/src/middlewares/files/profile/profilePictureStorage.ts @@ -6,7 +6,13 @@ export const profilePictureStorage = multer.diskStorage({ callback(null, "uploads/profile_pictures/"); }, filename: function (req, file, callback) { - callback(null, Date.now() + "-" + file.originalname); + const fileExtension = file.originalname.substring( + file.originalname.lastIndexOf(".") + ); + callback( + null, + Date.now() + "-" + Math.random().toString(36).substring(7) + fileExtension + ); }, }); diff --git a/src/middlewares/files/profile/uploadProfilePicture.ts b/src/middlewares/files/profile/uploadProfilePicture.ts index 89e8707b59671c52cc258808872658829bd13173..d18667298cf4cde82b167572556ab8c5ed4d0e1c 100644 --- a/src/middlewares/files/profile/uploadProfilePicture.ts +++ b/src/middlewares/files/profile/uploadProfilePicture.ts @@ -1,5 +1,6 @@ import { NextFunction, Request, Response } from "express"; +import { ErrorHandler } from "../../../middlewares/utils/ErrorHandler"; import File from "../../../models/FileSchema"; import Profile from "../../../models/ProfileSchema"; import fs from "fs"; @@ -12,33 +13,33 @@ const uploadProfilePicture = () => async ( res: Response, next: NextFunction ) => { - if (res.data.profile!.pictureId) { - const oldFile = await File.findByIdAndRemove(res.data.profile!.pictureId) - .lean() - .exec(); - - fs.unlink(oldFile!.path, (err) => { - throw err; - }); + try { + if (!res.data.profile) throw new ErrorHandler(400, "User not found!"); + if (res.data.profile.pictureId) { + const oldFile = await File.findByIdAndRemove(res.data.profile.pictureId) + .lean() + .exec(); + if (oldFile) await fs.unlinkSync(oldFile!.path); + } + + const newFile = new File(); + + newFile.originalName = req.file.originalname; + newFile.uploadDate = new Date(); + newFile.path = req.file.path; + newFile.mimeType = req.file.mimetype; + + await newFile.save(); + + await Profile.updateOne( + { _id: res.data.profile!._id }, + { pictureId: newFile._id } + ).exec(); + + return res.status(200).send(); + } catch (err) { + next(err); } - - const newFile = new File(); - - newFile.originalName = req.file.originalname; - newFile.uploadDate = new Date(); - newFile.path = req.file.path; - newFile.mimeType = req.file.mimetype; - - await newFile.save(); - - await Profile.updateOne( - { id: res.data.profile!.id }, - { pictureId: newFile.id } - ) - .lean() - .exec(); - - return res.status(200).send(); }; export default uploadProfilePicture; diff --git a/src/middlewares/news/addNews.ts b/src/middlewares/news/addNews.ts index 7c8ef3c5b3059f564741fc7e9ca61eeeeed28714..4be1fe97e8a6805c8a9059e674e63c6195dd4a9e 100644 --- a/src/middlewares/news/addNews.ts +++ b/src/middlewares/news/addNews.ts @@ -1,7 +1,6 @@ import { NextFunction, Request, Response } from "express"; import News from "../../models/NewsSchema"; -import { ValidationError } from "../utils/ValidationError"; import { validateFields } from "../utils/validateFields"; const fields = [ @@ -17,21 +16,25 @@ const addNews = () => async ( res: Response, next: NextFunction ) => { - const news = new News(); + try { + const news = new News(); - // Validate and set fields from request body - validateFields({ fields, reqBody: req.body }); - fields.forEach((field) => { - const value = req.body[field.name]; - if (value) news.set(field.name, req.body[field.name]); - }); + // Validate and set fields from request body + validateFields({ fields, reqBody: req.body }); + fields.forEach((field) => { + const value = req.body[field.name]; + if (value) news.set(field.name, req.body[field.name]); + }); - news.publishedAt = new Date(); + news.publishedAt = new Date(); - await news.save(); + await news.save(); - res.data.newsObject = news; - next(); + res.data.newsObject = news; + next(); + } catch (err) { + next(err); + } }; export default addNews; diff --git a/src/middlewares/news/deleteNews.ts b/src/middlewares/news/deleteNews.ts index 8e33524750d674162249b24b0f21cfa40d3d2b59..406b13381c488d42e56e855de82fc5f5a7b4b51d 100644 --- a/src/middlewares/news/deleteNews.ts +++ b/src/middlewares/news/deleteNews.ts @@ -1,5 +1,6 @@ import { NextFunction, Request, Response } from "express"; +import { ErrorHandler } from "../utils/ErrorHandler"; import News from "../../models/NewsSchema"; const deleteNews = () => async ( @@ -7,9 +8,13 @@ const deleteNews = () => async ( res: Response, next: NextFunction ) => { - await News.findByIdAndDelete(req.params.id).lean().exec(); - - res.status(204).send(); + try { + const news = await News.findByIdAndRemove(req.params.id).lean().exec(); + if (!news) throw new ErrorHandler(404, "News not found!"); + next(); + } catch (err) { + next(err); + } }; export default deleteNews; diff --git a/src/middlewares/news/getNews.ts b/src/middlewares/news/getNews.ts index e8b14899b06f609457f182ca8ede4846ed7357b4..2f8e60a6473aa2d2c688e65cd8b4c55196c75f8c 100644 --- a/src/middlewares/news/getNews.ts +++ b/src/middlewares/news/getNews.ts @@ -11,8 +11,12 @@ const getNews = () => async ( res: Response, next: NextFunction ) => { - res.data.newsObject = await News.findById(req.params.id).lean().exec(); - next(); + try { + res.data.newsObject = await News.findById(req.params.id).lean().exec(); + next(); + } catch (err) { + next(err); + } }; export default getNews; diff --git a/src/middlewares/news/getNewsList.ts b/src/middlewares/news/getNewsList.ts index ae6bbefceb5c5c43637f09ad46fe3d14e8e9d45d..21b6f71e4d52d7fda3becf97b5bd32433eb4b396 100644 --- a/src/middlewares/news/getNewsList.ts +++ b/src/middlewares/news/getNewsList.ts @@ -11,8 +11,12 @@ const getNewsList = () => async ( res: Response, next: NextFunction ) => { - res.data.news = await News.find(); - next(); + try { + res.data.news = await News.find(); + next(); + } catch (err) { + next(err); + } }; export default getNewsList; diff --git a/src/middlewares/news/responseNews.ts b/src/middlewares/news/responseNews.ts new file mode 100644 index 0000000000000000000000000000000000000000..d570a738ba7e7830e0e19dc2a43e0994dd5d5b23 --- /dev/null +++ b/src/middlewares/news/responseNews.ts @@ -0,0 +1,10 @@ +import { NextFunction, Request, Response, response } from "express"; + +/** + * Return the found news from res.data.news + */ +const responseNews = () => (req: Request, res: Response) => { + res.json(res.data.news); +}; + +export default responseNews; diff --git a/src/middlewares/news/responseNewsObject.ts b/src/middlewares/news/responseNewsObject.ts new file mode 100644 index 0000000000000000000000000000000000000000..abcf8d595e0e04a29b1df9d03d3910c650ae0e95 --- /dev/null +++ b/src/middlewares/news/responseNewsObject.ts @@ -0,0 +1,14 @@ +import { NextFunction, Request, Response, response } from "express"; + +/** + * Return the found user from res.data.profile + */ +const responseNewsObject = () => (req: Request, res: Response) => { + if (!res.data.newsObject) { + res.status(404).json({ message: "News not found!" }); + } else { + res.json(res.data.newsObject); + } +}; + +export default responseNewsObject; diff --git a/src/middlewares/news/updateNews.ts b/src/middlewares/news/updateNews.ts index 73f608152be1658fa7755f9501aee61551a25517..8be12bb9b85310d5818650019d513ab6b0341330 100644 --- a/src/middlewares/news/updateNews.ts +++ b/src/middlewares/news/updateNews.ts @@ -12,18 +12,22 @@ const updateNews = () => async ( res: Response, next: NextFunction ) => { - const news = await News.findById(req.params.id).exec(); + try { + const news = await News.findById(req.params.id).exec(); - if (news) { - validFields.forEach((field) => { - const value = req.body[field]; - if (value) news.set(field, value); - }); - await news.save(); - } - res.data.newsObject = news; + if (news) { + validFields.forEach((field) => { + const value = req.body[field]; + if (value) news.set(field, value); + }); + await news.save(); + } + res.data.newsObject = news; - next(); + next(); + } catch (err) { + next(err); + } }; export default updateNews; diff --git a/src/middlewares/user/addUser.ts b/src/middlewares/user/addUser.ts index 61d29352d5ddc611ade4086f9fb9cdb385560a3c..a70507a722f7225b9a22288e498306aed43356c8 100644 --- a/src/middlewares/user/addUser.ts +++ b/src/middlewares/user/addUser.ts @@ -1,7 +1,6 @@ import { NextFunction, Request, Response } from "express"; import Profile, { IProfile, Role } from "../../models/ProfileSchema"; -import { ValidationError } from "../utils/ValidationError"; import { validateFields } from "../utils/validateFields"; const fields = [ @@ -19,33 +18,37 @@ const addUser = () => async ( res: Response, next: NextFunction ) => { - // Already registered - if (req.session?.user?.id) { - res.data.profile = await Profile.findById(req.session.user.id) - .lean() - .exec(); - return next(); + try { + // Already registered + if (req.session?.user?.id) { + res.data.profile = await Profile.findById(req.session.user.id) + .lean() + .exec(); + return next(); + } + + // Register + const newProfile = new Profile(); + + // Validate and set fields from request body + validateFields({ fields, reqBody: req.body }); + fields.forEach((field) => { + const value = req.body[field.name]; + if (value) newProfile.set(field.name, req.body[field.name]); + }); + + newProfile.external_id = req.session!.user!.external_id; + newProfile.email = String(req.session?.user?.email); + newProfile.name = String(req.session?.user?.name); + + await newProfile.save(); + + res.data.profile = newProfile; + req.session!.user!.id = newProfile._id; + next(); + } catch (err) { + next(err); } - - // Register - const newProfile = new Profile(); - - // Validate and set fields from request body - validateFields({ fields, reqBody: req.body }); - fields.forEach((field) => { - const value = req.body[field.name]; - if (value) newProfile.set(field.name, req.body[field.name]); - }); - - newProfile.external_id = req.session!.user!.external_id; - newProfile.email = String(req.session?.user?.email); - newProfile.name = String(req.session?.user?.name); - - await newProfile.save(); - - res.data.profile = newProfile; - req.session!.user!.id = newProfile.id; - next(); }; export default addUser; diff --git a/src/middlewares/user/deleteUser.ts b/src/middlewares/user/deleteUser.ts index 76e732659bc3feb401c846509f9e5a35e77e56bb..00b61114dbd328f9dae3e3cc57257ea272b96292 100644 --- a/src/middlewares/user/deleteUser.ts +++ b/src/middlewares/user/deleteUser.ts @@ -10,8 +10,12 @@ const deleteUser = () => async ( res: Response, next: NextFunction ) => { - await Profile.findByIdAndDelete(req.params.id); - res.status(204).send(); + try { + await Profile.findByIdAndDelete(req.params.id); + next(); + } catch (err) { + next(err); + } }; export default deleteUser; diff --git a/src/middlewares/user/getUser.ts b/src/middlewares/user/getUser.ts index ad8460a13042740c034bdbf322193d6536eccf02..079233a6c62ff771d3d51b790bc903d7e6231999 100644 --- a/src/middlewares/user/getUser.ts +++ b/src/middlewares/user/getUser.ts @@ -13,8 +13,12 @@ const getUser = () => async ( res: Response, next: NextFunction ) => { - res.data.profile = await Profile.findById(req.params.id).lean().exec(); - next(); + try { + res.data.profile = await Profile.findById(req.params.id).lean().exec(); + next(); + } catch (err) { + next(err); + } }; export default getUser; diff --git a/src/middlewares/user/getUsersList.ts b/src/middlewares/user/getUsersList.ts index e3a8f69ef131ff43753167c1782c4518dfdd64e1..3cc3e4cb1a91a0670b701bf412aa4fa872757b7a 100644 --- a/src/middlewares/user/getUsersList.ts +++ b/src/middlewares/user/getUsersList.ts @@ -7,8 +7,12 @@ const getUsersList = () => async ( res: Response, next: NextFunction ) => { - res.data.profiles = await Profile.find(); - next(); + try { + res.data.profiles = await Profile.find(); + next(); + } catch (err) { + next(err); + } }; export default getUsersList; diff --git a/src/middlewares/user/updateUser.ts b/src/middlewares/user/updateUser.ts index de64f0988570dbe8bd2da5464a0a1f3c8a0d4ccc..d0c8d98048778f3e746e2f66fd9a065465165706 100644 --- a/src/middlewares/user/updateUser.ts +++ b/src/middlewares/user/updateUser.ts @@ -13,18 +13,22 @@ const updateUser = () => async ( res: Response, next: NextFunction ) => { - const profile = await Profile.findById(req.params.id).exec(); + try { + const profile = await Profile.findById(req.params.id).exec(); - if (profile) { - validFields.forEach((field) => { - const value = req.body[field]; - if (value) profile.set(field, value); - }); - await profile.save(); - } - res.data.profile = profile; + if (profile) { + validFields.forEach((field) => { + const value = req.body[field]; + if (value) profile.set(field, value); + }); + await profile.save(); + } + res.data.profile = profile; - next(); + next(); + } catch (err) { + next(err); + } }; export default updateUser; diff --git a/src/middlewares/utils/ErrorHandler.ts b/src/middlewares/utils/ErrorHandler.ts new file mode 100644 index 0000000000000000000000000000000000000000..bcc87e5818684e12b89ecd87f2e2d687364e6273 --- /dev/null +++ b/src/middlewares/utils/ErrorHandler.ts @@ -0,0 +1,19 @@ +import { Response } from "express"; + +export const handleError = (err: ErrorHandler, res: Response) => { + const { statusCode, message } = err; + res.status(statusCode).json({ + status: "error", + statusCode, + message, + }); +}; + +export class ErrorHandler extends Error { + statusCode: number; + constructor(statusCode: number, message: string) { + super(); + this.statusCode = statusCode; + this.message = message; + } +} diff --git a/src/middlewares/utils/ValidationError.ts b/src/middlewares/utils/ValidationError.ts deleted file mode 100644 index 4da9eeaa20f57ba786a10cb8befc10df8a05e4c3..0000000000000000000000000000000000000000 --- a/src/middlewares/utils/ValidationError.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class ValidationError extends Error { - code: number; - constructor(code: number, message: string) { - super(message); - this.code = code; - this.name = "ValidationError"; - Object.setPrototypeOf(this, new.target.prototype); - } -} diff --git a/src/middlewares/utils/emptyResponse.ts b/src/middlewares/utils/emptyResponse.ts index a8113f2d81e4609a10c574a5653cd0c304180f8d..73508b7e4b90888ce05ebca11ca2c16aba63aa69 100644 --- a/src/middlewares/utils/emptyResponse.ts +++ b/src/middlewares/utils/emptyResponse.ts @@ -1,5 +1,8 @@ import { Request, Response } from "express"; +/** + * Empty response + */ const emptyResponse = () => (req: Request, res: Response) => res.json({}); export default emptyResponse; diff --git a/src/middlewares/utils/validateFields.ts b/src/middlewares/utils/validateFields.ts index 3d46747811f14efd364ce51f19387fec52ed19e9..977002720f8565354f0aa0a74c6c586e29bd6078 100644 --- a/src/middlewares/utils/validateFields.ts +++ b/src/middlewares/utils/validateFields.ts @@ -1,5 +1,5 @@ +import { ErrorHandler } from "./ErrorHandler"; import { Request } from "express"; -import { ValidationError } from "./ValidationError"; interface IValidateFields { fields: { @@ -13,7 +13,7 @@ export function validateFields({ fields, reqBody }: IValidateFields) { fields.forEach((field) => { const value = reqBody[field.name]; if (field.required && !value) { - throw new ValidationError(400, `Field: {${field.name}} is required!`); + throw new ErrorHandler(400, `Field: {${field.name}} is required!`); } }); } diff --git a/src/middlewares/warning/addWarning.ts b/src/middlewares/warning/addWarning.ts index 200e14ff063fe4c07a111514aa9cb348e085239d..58704d6448ce99b52b25be255b080069e39e3d4d 100644 --- a/src/middlewares/warning/addWarning.ts +++ b/src/middlewares/warning/addWarning.ts @@ -1,7 +1,7 @@ import { NextFunction, Request, Response } from "express"; +import { ErrorHandler } from "../utils/ErrorHandler"; import Profile from "../../models/ProfileSchema"; -import { ValidationError } from "../utils/ValidationError"; import Warning from "../../models/WarningSchema"; import { validateFields } from "../utils/validateFields"; import warningsRoute from "../../routes/warning"; @@ -13,39 +13,43 @@ const addWarning = () => async ( res: Response, next: NextFunction ) => { - const warningReceiver = await Profile.findById(req.params.userId).exec(); - if (!warningReceiver) return res.status(400).send("Profile not found"); - - const warning = new Warning(); - - // Validate and set fields from request body - validateFields({ fields, reqBody: req.body }); - fields.forEach((field) => { - const value = req.body[field.name]; - if (value) warning.set(field.name, req.body[field.name]); - }); - - warning.receiver = warningReceiver.id!; - warning.date = new Date(); - warning.given_by = { - _id: req.session.user!.id!, - name: req.session.user!.name!, - }; - - await warning.save(); - - warningReceiver.warningIds = [ - ...warningReceiver.warningIds, - String(warning.id), - ]; - await warningReceiver.save(async (err) => { - if (err) { - await warning.remove(); - throw err; - } - }); - res.data.warning = warning; - next(); + try { + const warningReceiver = await Profile.findById(req.params.id).exec(); + if (!warningReceiver) throw new ErrorHandler(404, "User not found!"); + + const warning = new Warning(); + + // Validate and set fields from request body + validateFields({ fields, reqBody: req.body }); + fields.forEach((field) => { + const value = req.body[field.name]; + if (value) warning.set(field.name, req.body[field.name]); + }); + + warning.receiver = warningReceiver._id!; + warning.date = new Date(); + warning.given_by = { + _id: req.session.user!.id!, + name: req.session.user!.name!, + }; + + await warning.save(); + + warningReceiver.warningIds = [ + ...warningReceiver.warningIds, + String(warning._id), + ]; + await warningReceiver.save(async (err) => { + if (err) { + await warning.remove(); + throw err; + } + }); + res.data.warning = warning; + next(); + } catch (err) { + next(err); + } }; export default addWarning; diff --git a/src/middlewares/warning/deleteWarning.ts b/src/middlewares/warning/deleteWarning.ts index dbc566c4d10dcf1dd94fdc21a934a79d8f074c33..6d1b633809db11a55a779f8fa2d95c7291a942fe 100644 --- a/src/middlewares/warning/deleteWarning.ts +++ b/src/middlewares/warning/deleteWarning.ts @@ -8,13 +8,17 @@ const deleteWarning = () => async ( res: Response, next: NextFunction ) => { - const warning = await Warning.findByIdAndRemove(req.params.warningId); + try { + const warning = await Warning.findByIdAndRemove(req.params.warningId); - await Profile.updateOne( - { _id: warning?.receiver }, - { $pull: { warningIds: warning?._id } } - ); - res.status(204).send(); + await Profile.updateOne( + { _id: warning?.receiver }, + { $pull: { warningIds: warning?._id } } + ); + next(); + } catch (err) { + next(err); + } }; export default deleteWarning; diff --git a/src/middlewares/warning/getUserWarningsList.ts b/src/middlewares/warning/getUserWarningsList.ts index 06303340fe657e4b58079ccaf24b04d888e6d9a9..fdca929ffa57433b1b8dd779184e3e9baf1fdc27 100644 --- a/src/middlewares/warning/getUserWarningsList.ts +++ b/src/middlewares/warning/getUserWarningsList.ts @@ -8,14 +8,18 @@ const getUserWarningsList = () => async ( res: Response, next: NextFunction ) => { - if (!res.data.profile) - return res.status(404).json({ message: "User not found" }); + try { + if (!res.data.profile) + return res.status(404).json({ message: "User not found" }); - res.data.warnings = await Warning.find({ - _id: { $in: res.data.profile?.warningIds }, - }); + res.data.warnings = await Warning.find({ + _id: { $in: res.data.profile?.warningIds }, + }); - next(); + next(); + } catch (err) { + next(err); + } }; export default getUserWarningsList; diff --git a/src/middlewares/warning/getWarning.ts b/src/middlewares/warning/getWarning.ts index a529ad705c2270a20b27f56b61514fa858e472c9..f1d59c34f7a3262c0127d6efbdf4beea624cb95c 100644 --- a/src/middlewares/warning/getWarning.ts +++ b/src/middlewares/warning/getWarning.ts @@ -7,8 +7,14 @@ const getWarning = () => async ( res: Response, next: NextFunction ) => { - res.data.warning = await Warning.findById(req.params.warningId).lean().exec(); - next(); + try { + res.data.warning = await Warning.findById(req.params.warningId) + .lean() + .exec(); + next(); + } catch (err) { + next(err); + } }; export default getWarning; diff --git a/src/middlewares/warning/updateWarning.ts b/src/middlewares/warning/updateWarning.ts index 722f4c4550fab32a94717abd23477d76514b05a9..5d819d499181577bc6fd9ed73928bd4b1e6cf9f8 100644 --- a/src/middlewares/warning/updateWarning.ts +++ b/src/middlewares/warning/updateWarning.ts @@ -10,18 +10,22 @@ const updateWarning = () => async ( res: Response, next: NextFunction ) => { - const warning = await Warning.findById(req.params.warnmingId).exec(); + try { + const warning = await Warning.findById(req.params.warnmingId).exec(); - if (warning) { - validFields.forEach((field) => { - const value = req.body[field]; - if (value) warning.set(field, value); - }); - await warning.save(); - } - res.data.warning = warning; + if (warning) { + validFields.forEach((field) => { + const value = req.body[field]; + if (value) warning.set(field, value); + }); + await warning.save(); + } + res.data.warning = warning; - next(); + next(); + } catch (err) { + next(err); + } }; export default updateWarning; diff --git a/src/routes/file.ts b/src/routes/file.ts index 7546ec6af282a0553d61f41af04eba529a823de6..720de10bb00cf6f8dbb837870fd3a98207afc9d9 100644 --- a/src/routes/file.ts +++ b/src/routes/file.ts @@ -25,10 +25,20 @@ const CardImageUpload = multer({ const fileRoute = (app: Application): void => { app.post( - "/api/v1/files/profile", + "/api/v1/files/profile/picture/me", + isAuthenticated(), + profilePictureUpload.single("profile_picture"), + handleFileValidationError(), + setOwnUserId(), + getUser(), + uploadProfilePicture() + ); + app.post( + "/api/v1/files/profile/picture/:id", isAuthenticated(), profilePictureUpload.single("profile_picture"), handleFileValidationError(), + getUser(), uploadProfilePicture() ); app.get( diff --git a/src/routes/news.ts b/src/routes/news.ts index 37e55558fab3c67d907ce8fbbdb96da62103bd6f..a5030463e4229ca6e9e845f11b6fb685dccab9fa 100644 --- a/src/routes/news.ts +++ b/src/routes/news.ts @@ -2,42 +2,21 @@ import { Application, Response } from "express"; import addNews from "../middlewares/news/addNews"; import deleteNews from "../middlewares/news/deleteNews"; +import emptyResponse from "../middlewares/utils/emptyResponse"; import getNews from "../middlewares/news/getNews"; import getNewsList from "../middlewares/news/getNewsList"; +import responseNews from "../middlewares/news/responseNews"; +import responseNewsObject from "../middlewares/news/responseNewsObject"; import updateNews from "../middlewares/news/updateNews"; export default (app: Application): void => { - app.get("/api/v1/news", getNewsList(), (req, res: Response) => { - if (res.data.news) { - res.json(res.data.news); - } else { - throw Error("Cant get the news list"); - } - }); + app.get("/api/v1/news", getNewsList(), responseNews()); - app.post("/api/v1/news", addNews(), (req, res: Response) => { - if (res.data.newsObject) { - res.json(res.data.newsObject); - } else { - throw Error("Cant add news"); - } - }); + app.post("/api/v1/news", addNews(), responseNewsObject()); - app.get("/api/v1/news/:id", getNews(), (req, res: Response) => { - if (res.data.newsObject) { - res.json(res.data.newsObject); - } else { - throw Error("Cant get the news"); - } - }); + app.get("/api/v1/news/:id", getNews(), responseNewsObject()); - app.put("/api/v1/news/:id", getNews(), updateNews(), (req, res: Response) => { - if (res.data.newsObject) { - res.json(res.data.newsObject); - } else { - throw Error("Cant add news"); - } - }); + app.put("/api/v1/news/:id", getNews(), updateNews(), responseNewsObject()); - app.delete("/api/v1/news/:id", deleteNews()); + app.delete("/api/v1/news/:id", deleteNews(), emptyResponse()); }; diff --git a/src/routes/user.ts b/src/routes/user.ts index fe249ad3757c544caea598832a7838d477811910..c24d0eab45a7191c1b4da01d687c8a4e719f0403 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -11,6 +11,7 @@ import getUsersList from "../middlewares/user/getUsersList"; import getWarning from "../middlewares/warning/getWarning"; import getWarningsList from "../middlewares/warning/getUserWarningsList"; import isAuthenticated from "../middlewares/auth/isAuthenticated"; +import isLoggedIn from "../middlewares/auth/isLoggedIn"; import responseUser from "../middlewares/user/responseUser"; import responseUserList from "../middlewares/user/responseUserList"; import setOwnUserId from "../middlewares/user/setOwnUserId"; @@ -25,12 +26,13 @@ const usersRoute = (app: Application): void => { responseUserList() ); - app.post("/api/v1/users", addUser(), responseUser()); + app.post("/api/v1/users", isLoggedIn(), addUser(), responseUser()); app.get( "/api/v1/users/me", isAuthenticated(), setOwnUserId(), + getUser(), responseUser() ); @@ -38,6 +40,7 @@ const usersRoute = (app: Application): void => { "/api/v1/users/me/card", isAuthenticated(), setOwnUserId(), + getUser(), getCardImage(), getUserCard() ); diff --git a/src/routes/warning.ts b/src/routes/warning.ts index 389f2131d1cd88b59baa10f5cb097d92082f51f4..be2afb970128c66f8bb150b29ff7ded0e2c1e975 100644 --- a/src/routes/warning.ts +++ b/src/routes/warning.ts @@ -1,6 +1,8 @@ import { Application } from "express"; import addWarning from "../middlewares/warning/addWarning"; import deleteWarning from "../middlewares/warning/deleteWarning"; +import emptyResponse from "../middlewares/utils/emptyResponse"; +import getUser from "../middlewares/user/getUser"; import getUserWarningsList from "../middlewares/warning/getUserWarningsList"; import getWarning from "../middlewares/warning/getWarning"; import isAuthenticated from "../middlewares/auth/isAuthenticated"; @@ -18,16 +20,25 @@ const warningsRoute = (app: Application): void => { ); app.get( - "/api/v1/warnings/user/:userId", + "/api/v1/warnings/me", isAuthenticated(), + setOwnUserId(), + getUser(), + getUserWarningsList(), + responseWarningList() + ); + + app.get( + "/api/v1/warnings/user/:id", + isAuthenticated(), + getUser(), getUserWarningsList(), responseWarningList() ); app.post( - "/api/v1/warnings/user/:userId", + "/api/v1/warnings/user/:id", isAuthenticated(), - setOwnUserId(), addWarning(), responseWarning() ); @@ -42,7 +53,8 @@ const warningsRoute = (app: Application): void => { app.delete( "/api/v1/warnings/warning/:warningId", isAuthenticated(), - deleteWarning() + deleteWarning(), + emptyResponse() ); };