server v1.0.4

+ working hours for a whole week
+ dish visibility API
+ categories API
+ lunch menu API
+ updated Readme
This commit is contained in:
2020-09-23 18:41:02 +02:00
parent d7395f5472
commit 3a6a6f4c5c
7 changed files with 194 additions and 23 deletions

View File

@@ -19,8 +19,16 @@
- ##### **location** - ##### **location**
- ##### **type**: _String_ (enum: ["Point"], required) - ##### **type**: _String_ (enum: ["Point"], required)
- ##### **coordinates**: [Number] required - ##### **coordinates**: [Number] required
- ##### **placesId**: _String_
- ##### **imgUrl**: _String_ (required) - ##### **imgUrl**: _String_ (required)
- ##### **workingHours**: _String_ (required) - ##### **workingHours**:
- ##### **pn**: String
- ##### **wt**: String
- ##### **sr**: String
- ##### **cz**: String
- ##### **pt**: String
- ##### **sb**: String
- ##### **nd**: String
- ##### **description**: _String_ - ##### **description**: _String_
- ##### **tags** - ##### **tags**
- ##### **cardPayments**: _Boolean_ - ##### **cardPayments**: _Boolean_
@@ -32,7 +40,6 @@
- ##### **delivery**: _Boolean_ - ##### **delivery**: _Boolean_
- ##### **links** - ##### **links**
- ##### **facebook**: _String_ - ##### **facebook**: _String_
- ##### **twitter**: _String_
- ##### **instagram**: _String_ - ##### **instagram**: _String_
- ##### **www**: _String_ - ##### **www**: _String_
- ##### **phone**: _Number_ - ##### **phone**: _Number_
@@ -40,6 +47,8 @@
- ##### **subscriptionActive**: _Boolean_ - ##### **subscriptionActive**: _Boolean_
- ##### **subscriptionStarted**: _String_ - ##### **subscriptionStarted**: _String_
- ##### **subscriptionDue**: _String_ - ##### **subscriptionDue**: _String_
- ##### **categories**: [String]
- ##### **lunchMenu**: [*mongoose.Types.ObjectId*]
- ##### **dishes**: [*mongoose.Types.ObjectId*] - ##### **dishes**: [*mongoose.Types.ObjectId*]
<br> <br>
@@ -63,6 +72,8 @@
- ##### **peanuts**: _Boolean_ - ##### **peanuts**: _Boolean_
- ##### **sesame**: _Boolean_ - ##### **sesame**: _Boolean_
- ##### **ingredients**: [*String*] - ##### **ingredients**: [*String*]
- ##### **glicemicIndex**: String
- ##### **kCal**: String
- ##### **vegan**: _Boolean_ - ##### **vegan**: _Boolean_
- ##### **vegetarian**: _Boolean_ - ##### **vegetarian**: _Boolean_
<br> <br>
@@ -94,9 +105,18 @@
- #### **PUT** - #### **PUT**
Takes in **dishId**, **restaurantId**, **dish** document, and a JWT **token (header)** and tries to update specified document in a database. Returns **304** on success. Else returns **204** on bad document, or **401** on bad token. Takes in **dishId**, **restaurantId**, **dish** document, and a JWT **token (header)** and tries to update specified document in a database. Returns **304** on success. Else returns **204** on bad document, or **401** on bad token.
- #### **DELETE** - #### **DELETE**
Takes in **dishId**, and JWT **token (header)** and tries to remove specified dish from database. If everything goes OK, it returns **200**. Takes in **dishId**, and JWT **token (header)** and tries to remove specified dish from database. If everything goes OK, it returns **200**.
<br> <br>
* ### **/dish/hidden**
- #### **POST**
Takes a **dishId, visible(bool)** parameters, and JWT **token (header)**, tries to set dish visibility. Returns **200** on success.
<br>
* ### **/restaurant** * ### **/restaurant**
- #### **GET** - #### **GET**
@@ -108,6 +128,20 @@
<br> <br>
- ### **/restaurant/category**
* #### **POST**
Takes a **restaurantId, category, action (add / delete)** parameters, and JWT **token (header)**, tries to create or remove a supplied category.
<br>
- ### **/restaurant/lunch**
* #### **POST**
Takes a **restaurantId, dishId, action (add / delete)** parameters, and JWT **token (header)**, tries to create or remove a supplied dish from/to the lunch menu.
<br>
- ### **/restaurant/dishes** - ### **/restaurant/dishes**
- #### **GET** - #### **GET**
@@ -120,7 +154,7 @@
- #### **POST** - #### **POST**
Takes a **restaurantId** parameter and a **JWT token(header)**, and tries to remove the restaurant from the database and from user. If successfull returns **200**, if failed returns error with a code. Takes a **restaurantId** parameter **!!!should also check password!!!** and a **JWT token(header)**, and tries to remove the restaurant from the database and from user. If successfull returns **200**, if failed returns error with a code.
<br> <br>
@@ -164,6 +198,14 @@
<br> <br>
* ### **/user/changepass**
- #### **POST**
Takes **token, email, newPass, pass** parameters and if everything checks out, changes user password to the supplied **newPass**.
<br>
- ### **/search** - ### **/search**
- #### **GET** - #### **GET**

View File

@@ -33,8 +33,13 @@ const restaurantSchema = mongoose.Schema({
type: String, type: String,
}, },
workingHours: { workingHours: {
type: String, pn: String,
required: true, wt: String,
sr: String,
cz: String,
pt: String,
sb: String,
nd: String,
}, },
description: { description: {
type: String, type: String,
@@ -58,6 +63,8 @@ const restaurantSchema = mongoose.Schema({
subscriptionActive: Boolean, subscriptionActive: Boolean,
subscriptionStarted: Date, subscriptionStarted: Date,
subscriptionDue: Date, subscriptionDue: Date,
categories: [String],
lunchMenu: [mongoose.Types.ObjectId],
dishes: [mongoose.Types.ObjectId], dishes: [mongoose.Types.ObjectId],
}); });

View File

@@ -38,6 +38,7 @@ const userSchema = mongoose.Schema({
}, },
}, },
restaurants: [mongoose.Types.ObjectId], restaurants: [mongoose.Types.ObjectId],
trialUsed: Boolean,
}); });
export default mongoose.model("User", userSchema); export default mongoose.model("User", userSchema);

View File

@@ -3,8 +3,15 @@ import { createDish } from "../services/dataPrepServices.js";
import { import {
removeDish, removeDish,
addDishToRestaurant, addDishToRestaurant,
setDishVisibility,
} from "../services/databaseServices.js"; } from "../services/databaseServices.js";
import * as services from "../services/services.js"; import {
validateRestaurant,
validateUserToken,
validateDishId,
handleError,
verifyDishAccess,
} from "../services/services.js";
import Dish from "../models/dish.js"; import Dish from "../models/dish.js";
var router = express.Router(); var router = express.Router();
@@ -23,15 +30,29 @@ router.get("/", (req, res) => {
router.post("/", async (req, res) => { router.post("/", async (req, res) => {
try { try {
await services.validateRestaurant(req.body.restaurantId); await validateRestaurant(req.body.restaurantId);
const token = req.headers["x-auth-token"]; const token = req.headers["x-auth-token"];
services.validateUserToken(token); validateUserToken(token);
const dish = createDish(req.body.dish, req.body.restaurantId, true); const dish = createDish(req.body.dish, req.body.restaurantId, true);
await dish.save(); await dish.save();
await addDishToRestaurant(req.body.restaurantId, dish._id); await addDishToRestaurant(req.body.restaurantId, dish._id);
res.status(201).send(dish._id); res.status(201).send(dish._id);
} catch (error) { } catch (error) {
services.handleError(error, res); handleError(error, res);
}
});
// HIDE, UNHIDE DISH
router.post("/hidden", async (req, res) => {
try {
await validateDishId(req.body.dishId);
const token = req.headers["x-auth-token"];
validateUserToken(token);
await setDishVisibility(req.body.dishId, req.body.visible);
res.sendStatus(200);
} catch (error) {
handleError(error, res);
} }
}); });
@@ -39,14 +60,14 @@ router.post("/", async (req, res) => {
router.delete("/", async (req, res) => { router.delete("/", async (req, res) => {
try { try {
await services.validateDishId(req.body.dishId); await validateDishId(req.body.dishId);
const token = req.headers["x-auth-token"]; const token = req.headers["x-auth-token"];
const decodedToken = services.validateUserToken(token); const decodedToken = validateUserToken(token);
await services.verifyDishAccess(req.body.dishId, decodedToken); await verifyDishAccess(req.body.dishId, decodedToken);
await removeDish(req.body.dishId); await removeDish(req.body.dishId);
res.sendStatus(200); res.sendStatus(200);
} catch (error) { } catch (error) {
services.handleError(error, res); handleError(error, res);
} }
}); });
@@ -54,14 +75,14 @@ router.delete("/", async (req, res) => {
router.put("/", async (req, res) => { router.put("/", async (req, res) => {
try { try {
await services.validateDishId(req.body.dishId); await validateDishId(req.body.dishId);
const token = req.headers["x-auth-token"]; const token = req.headers["x-auth-token"];
services.validateUserToken(token); validateUserToken(token);
const dish = createDish(req.body.dish, req.body.restaurantId, false); const dish = createDish(req.body.dish, req.body.restaurantId, false);
await Dish.replaceOne({ _id: req.body.dishId }, dish); await Dish.replaceOne({ _id: req.body.dishId }, dish);
res.sendStatus(200); res.sendStatus(200);
} catch (error) { } catch (error) {
services.handleError(error, res); handleError(error, res);
} }
}); });

View File

@@ -5,6 +5,8 @@ import {
fetchRestaurant, fetchRestaurant,
fetchAllDishesForRestaurant, fetchAllDishesForRestaurant,
removeRestaurant, removeRestaurant,
changeCategory,
changeLunchMenu,
} from "../services/databaseServices.js"; } from "../services/databaseServices.js";
import { import {
decodeAndSanitize, decodeAndSanitize,
@@ -76,6 +78,44 @@ router.get("/dishes", async (req, res) => {
} }
}); });
// CHANGE CATEGORY
router.post("/category", async (req, res) => {
try {
const token = req.headers["x-auth-token"];
const user = validateUserToken(token);
await validateRestaurant(req.body.restaurantId);
await verifyRestaurantAccess(req.body.restaurantId, user);
await changeCategory(
req.body.restaurantId,
req.body.category,
req.body.action
);
res.send("Kategoria zmieniona pomyślnie");
} catch (error) {
handleError(error, res);
}
});
// CHANGE LUNCH MENU
router.post("/lunch", async (req, res) => {
try {
const token = req.headers["x-auth-token"];
const user = validateUserToken(token);
await validateRestaurant(req.body.restaurantId);
await verifyRestaurantAccess(req.body.restaurantId, user);
await changeLunchMenu(
req.body.restaurantId,
req.body.dishId,
req.body.action
);
res.send("Lunch menu zmienione pomyślnie.");
} catch (error) {
handleError(error, res);
}
});
// DELETE RESTAURANT // DELETE RESTAURANT
router.post("/delete", async (req, res) => { router.post("/delete", async (req, res) => {

View File

@@ -1,16 +1,10 @@
import express from "express"; import express from "express";
import * as services from "../services/services.js";
import * as databaseServices from "../services/databaseServices.js";
var router = express.Router(); var router = express.Router();
router.post("/", async (req, res) => { router.post("/", async (req, res) => {
try { try {
const newDate = await databaseServices.renewSubscription( console.log("test");
req.body.restaurantId,
1
);
res.send(`Subskrypcja przedłużona do: ${newDate}`);
} catch (error) { } catch (error) {
services.handleError(error, res); services.handleError(error, res);
} }

View File

@@ -104,6 +104,72 @@ export async function renewSubscription(restaurantId, monthsToAdd) {
return dueDateBasedOnSubscription(restaurant, monthsToAdd); return dueDateBasedOnSubscription(restaurant, monthsToAdd);
} }
async function checkIfCategoryExists(restaurant, category) {
const categories = restaurant.categories;
if (categories.includes(category)) {
throw newError("Podana kategoria już istnieje", 200);
}
}
async function checkIfAlreadyInLunchMenu(restaurant, dishId) {
const lunchMenu = restaurant.lunchMenu;
if (lunchMenu.includes(dishId)) {
throw newError("Podane danie jest już w lunch menu", 200);
}
}
export async function changeCategory(restaurantId, categoryName, action) {
if (action === "add") {
const restaurant = await Restaurant.findById(restaurantId).catch((err) => {
throw newError("Nie udało się pobrać restauracji.", 404);
});
await checkIfCategoryExists(restaurant, categoryName);
await Restaurant.findByIdAndUpdate(restaurantId, {
$push: { categories: categoryName },
}).catch((e) => {
throw newError("Nie udało się dodać kategorii.", 500);
});
} else if (action === "delete") {
await Restaurant.findByIdAndUpdate(restaurantId, {
$pull: { categories: categoryName },
}).catch((e) => {
throw newError("Nie udało się usunąć kategorii.", 500);
});
} else {
throw newError("Nieznany błąd.", 500);
}
}
export async function setDishVisibility(dishId, visible) {
await Dish.findByIdAndUpdate(dishId, { $set: { hidden: !visible } }).catch(
(e) => {
throw newError("Nie udało się zmienić dania.", 500);
}
);
}
export async function changeLunchMenu(restaurantId, dishId, action) {
if (action === "add") {
const restaurant = await Restaurant.findById(restaurantId).catch((err) => {
throw newError("Nie udało się pobrać restauracji.", 404);
});
await checkIfAlreadyInLunchMenu(restaurant, dishId);
await Restaurant.findByIdAndUpdate(restaurantId, {
$push: { lunchMenu: dishId },
}).catch((e) => {
throw newError("Nie udało się dodać dania do lunch menu.", 500);
});
} else if (action === "delete") {
await Restaurant.findByIdAndUpdate(restaurantId, {
$pull: { lunchMenu: dishId },
}).catch((e) => {
throw newError("Nie udało się usunąć dania.", 500);
});
} else {
throw newError("Nie sprecyzowano akcji", 500);
}
}
export async function fetchRestaurant(id) { export async function fetchRestaurant(id) {
const data = await Restaurant.findById(id).catch((e) => { const data = await Restaurant.findById(id).catch((e) => {
throw newError("Nie udało się pobrać restauracji.", 500); throw newError("Nie udało się pobrać restauracji.", 500);