From 3674e4ce3c2dffd2309824aeece6433794c7c6ff Mon Sep 17 00:00:00 2001 From: Jonasz Bigda Date: Mon, 24 Aug 2020 21:59:37 +0200 Subject: [PATCH] Refactoring day3 --- config/index.js | 4 +- loaders/express.js | 2 - routes/routeCity.js | 14 ----- routes/routeDish.js | 98 ++++++++------------------------ routes/routeImg.js | 15 ++--- routes/routeRestaurant.js | 52 ++++------------- routes/routeTest.js | 11 +--- routes/routeUser.js | 38 +++---------- services/services.js | 114 ++++++++++++++++++++++++++------------ 9 files changed, 132 insertions(+), 216 deletions(-) delete mode 100644 routes/routeCity.js diff --git a/config/index.js b/config/index.js index 15f73e3..c8a0056 100644 --- a/config/index.js +++ b/config/index.js @@ -5,4 +5,6 @@ export const port = process.env.PORT; export const dbPass = process.env.DB_PASS; export const cookiesSecret = process.env.COOKIES_SECRET; export const jwtSecret = process.env.JWT_SECRET; -export const API_KEY = process.env.API_KEY; +export const CRM_KEY = process.env.CRM_KEY; +export const CRM_USER = process.env.CRM_USER; +export const CRM_EMAIL = process.env.CRM_EMAIL; diff --git a/loaders/express.js b/loaders/express.js index 3b4c119..3cff582 100644 --- a/loaders/express.js +++ b/loaders/express.js @@ -3,7 +3,6 @@ import cors from "cors"; import rateLimiter from "express-rate-limit"; import helmet from "helmet"; import routeDish from "../routes/routeDish.js"; -import routeCity from "../routes/routeCity.js"; import routeRestaurant from "../routes/routeRestaurant.js"; import routeUser from "../routes/routeUser.js"; import routeSearch from "../routes/routeSearch.js"; @@ -25,7 +24,6 @@ export default ({ app, secret }) => { if (err) res.sendStatus(422); }); app.use("/dish", routeDish); - app.use("/city", routeCity); app.use("/restaurant", routeRestaurant); app.use("/img", routeImg); app.use("/user", routeUser); diff --git a/routes/routeCity.js b/routes/routeCity.js deleted file mode 100644 index 39fbb2a..0000000 --- a/routes/routeCity.js +++ /dev/null @@ -1,14 +0,0 @@ -import express from "express"; -import Restaurant from "../models/restaurant.js"; - -var router = express.Router(); - -router.get("/", (req, res) => { - Restaurant.find({ city: req.query.city }, (err, data) => { - if (err) { - res.sendStatus(404); - } else res.send(data); - }); -}); - -export default router; diff --git a/routes/routeDish.js b/routes/routeDish.js index 7a31c54..88a53ec 100644 --- a/routes/routeDish.js +++ b/routes/routeDish.js @@ -1,7 +1,6 @@ import express from "express"; import Restaurant from "../models/restaurant.js"; import * as services from "../services/services.js"; -import sanitizer from "string-sanitizer"; import Dish from "../models/dish.js"; var router = express.Router(); @@ -12,89 +11,38 @@ router.get("/", (req, res) => { Dish.findById(req.query.dishId, (err, data) => { if (err) { res.sendStatus(404); - } else - res - .cookie("img", encodeURI(data.imgUrl), { maxAge: 1000 * 600 }) - .send(data); + } else res.send(data); }); }); // ADD NEW DISH -router.post("/", (req, res) => { - services.validateRestaurant(req.body.restaurantId, (result) => { - if (!result) { - res.sendStatus(400); - } else { - const token = req.headers["x-auth-token"]; - if (!token) { - res.sendStatus(401); - return; - } - services.validateUserToken(token, (result) => { - if (!result) { - res.sendStatus(401); - } else { - const dish = services.createDish( - req.body.dish, - req.cookies["img"], - true - ); - dish.save((err) => { - if (err) { - res.sendStatus(400); - } else { - Restaurant.updateOne( - { _id: req.body.restaurantId }, - { $push: { dishes: dish._id } }, - (err) => { - if (err) { - res.sendStatus(400); - } else { - res.clearCookie("img").status(201).send(); - } - } - ); - } - }); - } - }); - } - }); +router.post("/", async (req, res) => { + try { + await services.validateRestaurant(req.body.restaurantId); + const token = req.headers["x-auth-token"]; + services.validateUserToken(token); + const dish = services.createDish(req.body.dish, true); + await dish.save(); + await services.addDishToRestaurant(req.body.restaurantId, dish._id); + } catch (error) { + services.handleError(error, res); + } }); // UPDATE DISH -router.put("/", (req, res) => { - services.validateDishId(req.body.dishId, (result) => { - if (!result) { - res.sendStatus(204); - } else { - const token = req.headers["x-auth-token"]; - if (!token) { - res.sendStatus(401); - return; - } - services.validateUserToken(token, (result) => { - if (!result) { - res.sendStatus(401); - } else { - const dish = services.createDish( - req.body.dish, - req.cookies["img"], - false - ); - Dish.replaceOne({ _id: req.body.dishId }, dish, (err) => { - if (err) { - res.sendStatus(304); - } else { - res.clearCookie("img").status(200).send(); - } - }); - } - }); - } - }); +router.put("/", async (req, res) => { + try { + services.validateDishId(req.body.dishId); + const token = req.headers["x-auth-token"]; + services.validateUserToken(token); + const dish = services.createDish(req.body.dish, false); + await Dish.replaceOne({ _id: req.body.dishId }, dish); + res.sendStatus(200); + } catch (error) { + services.handleError(error, res); + } }); export default router; diff --git a/routes/routeImg.js b/routes/routeImg.js index 1eb4383..5723900 100644 --- a/routes/routeImg.js +++ b/routes/routeImg.js @@ -20,17 +20,12 @@ const uploadStrategy = multer({ // POST router.post("/", uploadStrategy, async (req, res) => { - const token = req.headers["x-auth-token"]; - if (!token) { - res.sendStatus(401); - return; - } - const auth = Boolean(services.validateUserToken(token)); - if (!auth) { - res.sendStatus(401); - return; - } else { + try { + const token = req.headers["x-auth-token"]; + services.validateUserToken(token); await uploadBlob(req, res); + } catch (error) { + services.handleError(error, res); } }); diff --git a/routes/routeRestaurant.js b/routes/routeRestaurant.js index 26d86be..e26f21f 100644 --- a/routes/routeRestaurant.js +++ b/routes/routeRestaurant.js @@ -1,8 +1,6 @@ import express from "express"; import * as services from "../services/services.js"; import Restaurant from "../models/restaurant.js"; -import sanitizer from "string-sanitizer"; -import mongoose from "mongoose"; var router = express.Router(); @@ -12,49 +10,24 @@ router.get("/", async (req, res) => { try { const query = services.decodeAndSanitize(req.query.restaurantId); await services.validateRestaurant(query); - Restaurant.findById(query, (err, data) => { - if (err) { - res.sendStatus(404); - } else res.send(data); - }); + Restaurant.findById(query).then((data) => res.send(data)); } catch (error) { - res.sendStatus(404); + services.handleError(error, res); } }); // ADD NEW RESTAURANT -router.post("/", (req, res) => { - const token = req.headers["x-auth-token"]; - if (!token) { - res.sendStatus(401); - return; +router.post("/", async (req, res) => { + try { + const token = req.headers["x-auth-token"]; + services.validateUserToken(token); + const restaurant = services.createRestaurant(req); + await restaurant.save(); + res.sendStatus(201); + } catch (error) { + services.handleError(error, res); } - services.validateUserToken(token, (result) => { - if (!result) { - res.sendStatus(401); - } else { - const restaurant = new Restaurant({ - _id: new mongoose.Types.ObjectId(), - name: sanitizer.sanitize.keepUnicode(req.body.name), - city: sanitizer.sanitize.keepUnicode(req.body.city), - imgUrl: services.saveImage(req.body.imgURL), - workingHours: req.body.workingHours, - description: sanitizer.sanitize.keepUnicode(req.body.description), - tags: req.body.tags, - links: req.body.links, - phone: req.body.phone, - hidden: req.body.hidden, - }); - restaurant.save((err) => { - if (err) { - res.sendStatus(400); - } else { - res.clearCookie("img").status(201).send(); - } - }); - } - }); }); // GET ALL DISHES FROM A RESTAURANT ID @@ -67,8 +40,7 @@ router.get("/dishes", async (req, res) => { let dishes = await services.fetchAllDishesForRestaurant(restaurant); res.send(dishes); } catch (error) { - console.log(error); - res.sendStatus(400); + services.handleError(error, res); } }); diff --git a/routes/routeTest.js b/routes/routeTest.js index a7f56ea..02000c7 100644 --- a/routes/routeTest.js +++ b/routes/routeTest.js @@ -4,14 +4,9 @@ import * as services from "../services/services.js"; var router = express.Router(); router.post("/", async (req, res) => { - await services - .fetchUser() - .then((response) => { - res.send(response); - }) - .catch((e) => { - services.handleError(e, res); - }); + await services.checkEmailTaken("jonasz@bankai.pl").catch((e) => { + services.handleError(e, res); + }); }); export default router; diff --git a/routes/routeUser.js b/routes/routeUser.js index bbdca39..31a9f39 100644 --- a/routes/routeUser.js +++ b/routes/routeUser.js @@ -1,20 +1,11 @@ import express from "express"; -import mongoose from "mongoose"; -import User from "../models/users.js"; -import bcrypt from "bcrypt"; import * as services from "../services/services.js"; import * as config from "../config/index.js"; import AgileCRMManager from "agile_crm"; -const { API_KEY, jwtSecret } = config; +const { CRM_USER, CRM_EMAIL, CRM_KEY } = config; var router = express.Router(); -var agileAPI = new AgileCRMManager("bankai", API_KEY, "bankai@bankai.pl"); -var success = function (data) { - console.log("Task successfull"); -}; -var error = function (err) { - console.log("Task failed successfully"); -}; +var agileAPI = new AgileCRMManager(CRM_USER, CRM_KEY, CRM_EMAIL); // LOGIN router.post("/login", async (req, res) => { @@ -23,16 +14,10 @@ router.post("/login", async (req, res) => { throw services.newError("No input data", 204); } const user = await services.fetchUser(req.body.email); - /* await services.checkPassword(req.body.password, user.password); - const userNoPass = { - firstname: user.firstname, - lastname: user.lastname, - email: user.email, - id: user._id, - }; - var token = services.generateAuthToken(userNoPass); - res.header("x-auth-token", token).status(202).send(userNoPass); */ - res.send(user); + await services.checkPassword(req.body.password, user.password); + const safeUser = services.prepareSafeUser(user); + var token = services.generateAuthToken(safeUser); + res.header("x-auth-token", token).status(202).send(safeUser); } catch (error) { services.handleError(error, res); } @@ -42,17 +27,10 @@ router.post("/login", async (req, res) => { router.post("/register", async (req, res) => { try { await services.checkEmailTaken(req.body.email); - const password = await services.hashPass(req.body.password); - const user = new User({ - _id: new mongoose.Types.ObjectId(), - email: req.body.email, - password: password, - firstname: req.body.firstname, - lastname: req.body.lastname, - }); + const user = await services.createUser(req); await user.save(); const contact = services.composeNewContact(user); - agileAPI.contactAPI.add(contact, success, error); + agileAPI.contactAPI.add(contact, null, null); res.sendStatus(201); } catch (e) { services.handleError(e, res); diff --git a/services/services.js b/services/services.js index 3f33b17..9e3dd1b 100644 --- a/services/services.js +++ b/services/services.js @@ -28,7 +28,7 @@ export function handleError(error, responseObject) { export async function validateRestaurant(id) { if (!mongoose.Types.ObjectId.isValid(id)) throw newError("Invalid ID", 204); let valid = await Restaurant.exists({ _id: id }); - if (valid !== true) throw "Restaurant doesn't exist"; + if (valid !== true) throw newError("Restaurant doesn't exist", 404); return true; } @@ -37,7 +37,7 @@ export async function fetchRestaurant(id) { await Restaurant.findById(id, (err, result) => { data = result; }).catch((e) => { - throw "Couldn't fetch restaurant"; + throw newError("Couldn't fetch restaurant", 500); }); return data; } @@ -53,23 +53,36 @@ export async function fetchAllDishesForRestaurant(restaurant) { export async function fetchDish(id) { let data = await Dish.findById(id).catch((e) => { - throw `Couldn't fetch ${id}`; + throw newError(`Couldn't fetch ${id}`, 404); }); return data; } export async function fetchUser(email) { - if (!email) throw newError("No input", 404); - User.findOne({ email: email }); + if (!email) throw newError("No input", 204); + const user = await User.findOne({ email: email }); + if (!user) throw newError("No such user...", 404); + return user; } export function decodeAndSanitize(query) { - if (!query) throw "Nothing to sanitize..."; + if (!query) throw newError("Nothing to sanitize...", 204); return sanitizer.sanitize.keepUnicode(decodeURI(query)); } export async function checkPassword(password, hash) { - bcrypt.compare(password, hash); + const result = await bcrypt.compare(password, hash); + if (!result) throw newError("Wrong password :(", 401); +} + +export function prepareSafeUser(user) { + const safeUser = { + firstname: user.firstname, + lastname: user.lastname, + email: user.email, + id: user._id, + }; + return safeUser; } export function generateAuthToken(user) { @@ -89,40 +102,38 @@ export function generateAuthToken(user) { export async function checkEmailTaken(email) { if (!email) throw newError("No input email", 204); - await User.exists({ email: email }) - .then((res) => { - if (res) { - throw newError("Email is taken", 409); - } - }) - .catch((e) => { - throw e; - }); + await User.exists({ email: email }).then((res) => { + if (res) { + throw newError("Email is taken", 409); + } + }); } export function validateUserToken(token) { - let verified; - try { - verified = jwt.verify(token, jwtSecret, { ignoreExpiration: false }); - } catch (error) { - verified = false; + if (!token) throw newError("Invalid user token", 401); + const verified = jwt.verify(token, jwtSecret, { ignoreExpiration: false }); + if (!verified) throw newError("Invalid user token", 401); +} + +export function validateDishId(id) { + if (!mongoose.Types.ObjectId.isValid(id)) { + throw newError("Invalid ID", 400); } - return verified; // should be return verified for production + const dishDoesExist = Dish.exists({ _id: id }); + if (!dishDoesExist) throw newError("Dish doesn't exist", 404); } -export function validateDishId(id, callback) { - if (mongoose.Types.ObjectId.isValid(id)) { - Dish.exists({ _id: id }, (err, res) => { - if (err) { - callback(false); - } else { - callback(res); - } - }); - } else callback(false); +export async function addDishToRestaurant(restaurantId, dishId) { + await Restaurant.updateOne( + { _id: restaurantId }, + { $push: { dishes: dishId } } + ).catch((error) => { + throw newError("Couldn't add dish to restaurant", 500); + }); } -export function createDish(dish, cookie, generateId) { +export function createDish(dish, generateId) { + // TEST THIS ONE!!!!! if (generateId) { const newDish = new Dish({ _id: new mongoose.Types.ObjectId(), @@ -130,7 +141,7 @@ export function createDish(dish, cookie, generateId) { category: dish.category, price: dish.price, notes: sanitizer.sanitize.keepUnicode(dish.notes), - imgUrl: saveImage(cookie), + imgUrl: dish.imgUrl, weight: dish.weight, allergens: { gluten: dish.allergens.gluten, @@ -152,7 +163,7 @@ export function createDish(dish, cookie, generateId) { category: dish.category, price: dish.price, notes: sanitizer.sanitize.keepUnicode(dish.notes), - imgUrl: chooseImg(cookie), + imgUrl: dish.imgUrl, weight: dish.weight, allergens: { gluten: dish.allergens.gluten, @@ -171,13 +182,44 @@ export function createDish(dish, cookie, generateId) { } } +export function createRestaurant(request) { + try { + const restaurant = new Restaurant({ + _id: new mongoose.Types.ObjectId(), + name: sanitizer.sanitize.keepUnicode(request.body.name), + city: sanitizer.sanitize.keepUnicode(request.body.city), + imgUrl: services.saveImage(request.body.imgURL), + workingHours: request.body.workingHours, + description: sanitizer.sanitize.keepUnicode(request.body.description), + tags: request.body.tags, + links: request.body.links, + phone: request.body.phone, + hidden: request.body.hidden, + }); + return restaurant; + } catch (error) { + throw newError("Invalid input data", 206); + } +} + +export async function createUser(request) { + const password = await hashPass(request.body.password); + const user = new User({ + _id: new mongoose.Types.ObjectId(), + email: request.body.email, + password: password, + firstname: request.body.firstname, + lastname: request.body.lastname, + }); + return user; +} + export function yearFromNowDate() { Date.prototype.addDays = function (days) { var date = new Date(this.valueOf()); date.setDate(date.getDate() + days); return date; }; - var date = new Date(); return date.addDays(365); }