diff --git a/app.js b/app.js index 2bbcbd2..c942f4e 100644 --- a/app.js +++ b/app.js @@ -33,18 +33,21 @@ app.use( rateLimiter({ windowsMs: 15 * 60 * 1000, max: 60, - }) + }), ); app.use(helmet()); -app.use(cors({ origin: ["http://localhost:3000", "https://deployed_to_netlify_url.com"], credentials: true })); //CHAGE TO REAL URL ON NETLIFY +app.use(cors({ + origin: ['http://localhost:3000', 'https://deployed_to_netlify_url.com'], + credentials: true, +})); //CHAGE TO REAL URL ON NETLIFY <--have you done this? app.use(xss()); app.use(mongoSanitize()); -//app.use(morgan('tiny')); //log in terminal every request methode + statuscode +app.use(morgan('tiny')); //log in terminal every request methode + statuscode // Why not using morgan? app.use(express.json()); app.use(cookieParser(process.env.JWT_SECRET)); //access cookies coming back from the browser- with each request the browser will send cookie + we're signing cookies with jwt secret -app.use(express.static('./public')); +app.use(express.static('./public', { extensions: ['html'] })); // a way for /docs to work being served from public folder instead of needing its own dedicated route definition (also fix issue with js not working) app.use(fileUpload()); // //testing in postman if the token is stored in a cookie @@ -54,9 +57,9 @@ app.use(fileUpload()); // res.send('ecommerce api'); // }); -app.get('/docs', (req, res) => { - res.sendFile(path.join(__dirname, 'docs.html')); -}); +// app.get('/docs', (req, res) => { +// res.sendFile(path.join(__dirname, 'docs.html')); +// }); // Could get this with just the public folder app.use('/api/v1/auth', authRouter); app.use('/api/v1/users', userRouter); diff --git a/controllers/orderController.js b/controllers/orderController.js index cea6724..41b5453 100644 --- a/controllers/orderController.js +++ b/controllers/orderController.js @@ -23,17 +23,18 @@ const createOrder = async (req, res) => { //initial state const initialValue = { subtotal: 0, orderItems: [] }; + // this reduce function is probably worth refactoring/extracting into its own function since its somewhat long. // Loop through each item in `cartItems` array (if the array is empty, this will just be skipped) - const { subtotal: subtotal, orderItems: orderItems } = await cartItems.reduce( + const { subtotal, orderItems } = await cartItems.reduce( async (resultsMap, item) => { - // Each iteration, item will be the next item in the array. + // Each iteration, item will be the next item in the array. //resultsMap will be whatever we return at the end of the reduce function, and the first time it will be equal to `initialValue` (because we pass that to reduce as the second argument on line 63) const dbProduct = await Product.findOne({ _id: item.product }); console.log( `looping through: resultsMap=${JSON.stringify( - await resultsMap - )} | item=${JSON.stringify(item)} | dbProduct=${dbProduct}` + await resultsMap, + )} | item=${JSON.stringify(item)} | dbProduct=${dbProduct}`, ); if (!dbProduct) { @@ -42,6 +43,7 @@ const createOrder = async (req, res) => { ); } + // this could potentially also be extracted to a helper function const { name, price, image, _id } = dbProduct; const singleOrderItem = { amount: item.amount, @@ -96,7 +98,7 @@ const createOrder = async (req, res) => { - + //calculate total const total = tax + shippingFee + subtotal; //get client Secret @@ -116,7 +118,7 @@ const createOrder = async (req, res) => { }); res .status(StatusCodes.CREATED) - .json({ order, clientSecret: order.clientSecret }); + .json({ order, clientSecret: order.clientSecret }); // any particular reason to return clientSecret at top-level when it's already part of the order object? }; const getAllOrders = async (req, res) => { @@ -139,6 +141,7 @@ const getCurrentUserOrders = async (req, res) => { res.status(StatusCodes.OK).json({ orders, count: orders.length }); }; +// it's a bit misleading to name this route updateOrder, since it seems like the only thing you can do is set an order to "paid" (by passing in an intent id) const updateOrder = async (req, res) => { const { id: orderId } = req.params; const { paymentIntentId } = req.body; diff --git a/controllers/reviewController.js b/controllers/reviewController.js index 4337d7f..ca69000 100644 --- a/controllers/reviewController.js +++ b/controllers/reviewController.js @@ -79,21 +79,28 @@ const updateReview = async (req, res) => { // res.status(StatusCodes.OK).json({ review }); //OPTION 2 -const { id: reviewId } = req.params; //TAKE ID FROM REQ.PARAMS AND ASSIGN IT TO REVIEWiD -const { rating, title, comment } = req.body; -const review = await Review.findOne({ _id: reviewId }); + const { id: reviewId } = req.params; //TAKE ID FROM REQ.PARAMS AND ASSIGN IT TO REVIEWiD + const { rating, title, comment } = req.body; // don't need this + const review = await Review.findOne({ _id: reviewId }); -if (!review) { - throw new CustomError.NotFoundError(`No review with id ${reviewId}`); -} - -checkPermissions(req.user, review.user); -review.rating = req.body.hasOwnProperty('rating') ? req.body.rating : review.rating -review.title = req.body.hasOwnProperty('title') ? req.body.title : review.title -review.comment = req.body.hasOwnProperty('comment') ? req.body.comment : review.comment + if (!review) { + throw new CustomError.NotFoundError(`No review with id ${reviewId}`); + } -await review.save(); -res.status(StatusCodes.OK).json({ review }); + checkPermissions(req.user, review.user); +// can simplify with: review.rating = req.body?.rating || review.rating (but hasOwnProperty is better because then that allows us to send/unset values like this: {rating: null}) + review.rating = req.body.hasOwnProperty('rating') + ? req.body.rating + : review.rating; + review.title = req.body.hasOwnProperty('title') + ? req.body.title + : review.title; + review.comment = req.body.hasOwnProperty('comment') + ? req.body.comment + : review.comment; + + await review.save(); + res.status(StatusCodes.OK).json({ review }); //option 3 //When we do the object destructuring (const { rating, title, comment } = req.body;), then any fields that didn't exist in req.body will just be saved to the variables on the left-hand-side as undefined. diff --git a/controllers/userController.js b/controllers/userController.js index 4614121..ce4199b 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -38,6 +38,7 @@ const updateUser = async (req, res) => { } const user = await User.findOne({ _id: req.user.userId }); //get user + // Will this set email/name to undefined if tehy weren't given? user.email = email; //update properties manually user.name = name; diff --git a/models/Order.js b/models/Order.js index c8b1593..b7fbc48 100644 --- a/models/Order.js +++ b/models/Order.js @@ -14,6 +14,7 @@ const SingleOrderItemSchema = mongoose.Schema({ const OrderSchema = mongoose.Schema( { + // validations on min for the number fields? tax: { type: Number, required: true, diff --git a/models/Product.js b/models/Product.js index 0cae908..83ff37a 100644 --- a/models/Product.js +++ b/models/Product.js @@ -10,6 +10,7 @@ const ProductSchema = new mongoose.Schema( price: { type: Number, required: [true, 'Please provide product price'], + // might be good to have min price validation }, description: { type: String, diff --git a/models/Review.js b/models/Review.js index 2491abf..5b7a132 100644 --- a/models/Review.js +++ b/models/Review.js @@ -11,7 +11,7 @@ const ReviewSchema = mongoose.Schema( title: { type: String, trim: true, - required: [true, 'Please provide reviw title'], + required: [true, 'Please provide review title'], maxlength: 100, }, comment: { diff --git a/browser-app.js b/public/browser-app.js similarity index 100% rename from browser-app.js rename to public/browser-app.js diff --git a/docs.html b/public/docs.html similarity index 99% rename from docs.html rename to public/docs.html index c15f450..8b0e162 100644 --- a/docs.html +++ b/public/docs.html @@ -9040,12 +9040,13 @@