Done Capstone 2

master
Ron Reciproco 1 year ago
parent 4b003da8da
commit a7656ebf9e

@ -51,3 +51,17 @@ exports.verifyAdmin = (req, res, next) => {
} }
} }
exports.verifyUser = (req, res, next) => {
const authenticatedUserId = req.user.userId;
const requestedUserId = req.body.userId;
if (authenticatedUserId && authenticatedUserId === requestedUserId) {
// User is authenticated, and the requested userId matches the authenticated userId
next();
} else {
return res.status(403).json({
message: "Permission denied.",
});
}
};

@ -0,0 +1,72 @@
// userController.js
const User = require('../model/Cart');
exports.addToCart = async (req, res) => {
try {
const { userId, productId, quantity } = req.body;
// Check if the user exists
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({ message: 'User not found.' });
}
// Check if the product exists
const product = await Product.findById(productId);
if (!product) {
return res.status(404).json({ message: 'Product not found.' });
}
// Check if the product is active
if (!product.isActive) {
return res.status(400).json({ message: 'Product is not active.' });
}
// Check if the quantity is valid
if (quantity <= 0) {
return res.status(400).json({ message: 'Invalid quantity.' });
}
// Check if the user already has a cart
let cart = await Cart.findOne({ userId });
// If the user doesn't have a cart, create a new one
if (!cart) {
cart = new Cart({ userId, products: [], totalAmount: 0 });
}
// Check if the product is already in the cart
const existingProduct = cart.products.find(
(cartProduct) => cartProduct.productId.toString() === productId
);
// If the product is already in the cart, update the quantity and subtotal
if (existingProduct) {
existingProduct.quantity += quantity;
existingProduct.subtotal = existingProduct.quantity * existingProduct.price;
} else {
// If the product is not in the cart, add it
cart.products.push({
productId,
productName: product.name,
quantity,
price: product.price,
subtotal: quantity * product.price,
});
}
// Update the total amount in the cart
cart.totalAmount = cart.products.reduce(
(total, product) => total + product.subtotal,
0
);
// Save the updated cart
await cart.save();
return res.status(200).json({ message: 'Product added to cart successfully.' });
} catch (error) {
console.error(error);
return res.status(500).json({ message: 'Internal server error.' });
}
}

@ -10,6 +10,13 @@ exports.createOrder = async (req, res) => {
return res.status(404).json({ message: "User not found" }) return res.status(404).json({ message: "User not found" })
} }
// Check if the user is an admin
if (user.isAdmin) {
return res
.status(403)
.json({ message: "Admins cannot create orders" })
}
const newOrder = { const newOrder = {
products: products, products: products,
totalAmount: totalAmount, totalAmount: totalAmount,
@ -28,3 +35,31 @@ exports.createOrder = async (req, res) => {
res.status(500).json({ message: "Internal Server Error" }) res.status(500).json({ message: "Internal Server Error" })
} }
} }
// Retrieve authenticated user's orders
exports.getOrders = async (req, res) => {
try {
const { userId } = req.body
const user = await User.findById(userId)
if (!user) {
return res.status(404).json({ message: "User not found" })
}
// Return the user details in the response
res.send({ orderedProducts: user.orderedProducts })
} catch (error) {
console.error(error)
res.status(500).json({ message: "Internal server error" })
}
}
exports.getAllOrders = async (req, res) => {
try {
const orders = await User.find({ "orderedProducts.0": { $exists: true } }, "orderedProducts");
res.status(200).json({ success: true, data: orders });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};

@ -1,9 +1,12 @@
const jwt = require('jsonwebtoken'); const jwt = require("jsonwebtoken")
const bcrypt = require("bcrypt") const bcrypt = require("bcrypt")
const faker = require("faker") const faker = require("faker")
const User = require("../model/User") const User = require("../model/User")
const auth = require("../auth") const auth = require("../auth")
// Secret Sauce
require("dotenv").config()
// Controller function for user registration // Controller function for user registration
exports.registerUser = async (req, res) => { exports.registerUser = async (req, res) => {
try { try {
@ -47,32 +50,34 @@ exports.registerUser = async (req, res) => {
// Controller function for user authentication // Controller function for user authentication
exports.authenticateUser = async (req, res) => { exports.authenticateUser = async (req, res) => {
try { try {
const { email, password } = req.body; const { email, password } = req.body
const user = await User.findOne({ email }); const user = await User.findOne({ email })
if (!user) { if (!user) {
return res.status(401).json({ message: 'Invalid credentials' }); return res.status(401).json({ message: "Invalid credentials" })
} }
const passwordMatch = await bcrypt.compare(password, user.password); const passwordMatch = await bcrypt.compare(password, user.password)
if (!passwordMatch) { if (!passwordMatch) {
return res.status(401).json({ message: 'Invalid credentials' }); return res.status(401).json({ message: "Invalid credentials" })
} }
// Generate JWT token using the function from auth.js // Generate JWT token using the function from auth.js
const token = auth.generateToken(user._id, user.email, user.isAdmin); const token = auth.generateToken(user._id, user.email, user.isAdmin)
// Decode JWT token to get expiration time // Decode JWT token to get expiration time
const decodedToken = jwt.decode(token); const decodedToken = jwt.decode(token)
if (decodedToken) { if (decodedToken) {
const expiration = new Date(decodedToken.exp * 1000); // Convert seconds to milliseconds const expiration = new Date(decodedToken.exp * 1000) // Convert seconds to milliseconds
// Log token expiration // Log token expiration
console.log(`Login success. Token will expire on: ${expiration}`); console.log(
`Authenticate success. Token will expire on: ${expiration}`
)
} else { } else {
console.error('Error decoding token'); console.error("Error decoding token")
} }
// Return user details and token // Return user details and token
@ -83,12 +88,13 @@ exports.authenticateUser = async (req, res) => {
lastName: user.lastName, lastName: user.lastName,
isAdmin: user.isAdmin, isAdmin: user.isAdmin,
token: token, token: token,
}); })
} catch (error) { } catch (error) {
console.error(error); console.error(error)
res.status(500).json({ message: 'Internal server error' }); res.status(500).json({ message: "Internal server error" })
} }
}; }
// Controller function for updating user data (including email, firstName, lastName, and password) // Controller function for updating user data (including email, firstName, lastName, and password)
exports.updateUserData = async (req, res) => { exports.updateUserData = async (req, res) => {
try { try {
@ -149,15 +155,7 @@ exports.updateUserData = async (req, res) => {
exports.getUserDetails = async (req, res) => { exports.getUserDetails = async (req, res) => {
try { try {
const { userId } = req.params; const { userId } = req.body;
const userIdFromToken = req.user.userId;
if (userIdFromToken !== userId) {
return res.status(403).json({
message: "Permission denied. You can only retrieve your own data.",
});
}
const user = await User.findById(userId); const user = await User.findById(userId);
@ -174,3 +172,33 @@ exports.getUserDetails = async (req, res) => {
res.status(500).json({ message: "Internal server error" }); res.status(500).json({ message: "Internal server error" });
} }
}; };
exports.setAdmin = async (req, res) => {
try {
const { userId } = req.body // assuming userId is sent in the request body
const user = await User.findById(userId)
if (!user) {
return res.status(404).json({ error: "User not found." })
}
user.isAdmin = true
await user.save()
res.json({ message: "User is now an admin." })
} catch (error) {
console.error(error)
res.status(500).json({ error: "Internal server error" })
}
}
exports.getAllOrders = async (req, res) => {
try {
const orders = await User.find({}, "orderedProducts");
res.status(200).json({ success: true, data: orders });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};

@ -5,6 +5,7 @@ const cors = require("cors")
require("dotenv").config() require("dotenv").config()
const userRoute = require("./routes/user") const userRoute = require("./routes/user")
const productRoute = require("./routes/product") const productRoute = require("./routes/product")
const cartRoute = require("./routes/cart")
// Server start // Server start
const app = express() const app = express()
@ -31,6 +32,7 @@ mongoose
// Routes // Routes
app.use("/user", userRoute, productRoute) app.use("/user", userRoute, productRoute)
app.use("/cart", cartRoute)
// Server up // Server up
app.listen(process.env.PORT || 3000, () => { app.listen(process.env.PORT || 3000, () => {

@ -0,0 +1,27 @@
const mongoose = require('mongoose');
const cartProductSchema = new mongoose.Schema({
productId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product',
required: true,
},
productName: { type: String, required: true },
quantity: { type: Number, required: true },
price: { type: Number, required: true },
subtotal: { type: Number, required: true },
});
const cartSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
products: [cartProductSchema],
totalAmount: { type: Number, required: true },
});
const Cart = mongoose.model('Cart', cartSchema);
module.exports = Cart;

@ -1,3 +1,16 @@
<!-- To start use: npm start -->
**** Stretch Goals ****
+ Set user as Admin ( Admin Only )
+ Retrieve Authenticated User's Orders
+ Retrieve all orders ( Admin Only )
+ Add to Cart ( Added Products, Change Product Quantities, Remove Products From Cart, Subtotal for each item, Total price for all items)
+ Authentication Token with expiration (1hr)
+ dotenv
+ faker (Auto Generate Names)
+ getUserDetails function ( Detects if the user tries to get the details of the other useId's + Token auth)
+ Secure verification that match Token and UserId to next()
**** Accounts **** **** Accounts ****
User: ( Password: wapatu ) User: ( Password: wapatu )
@ -86,4 +99,8 @@ http://localhost:3000/user/products/65545a1e6fa9d841e1518d1d
RETRIEVE OWN USER DATA RETRIEVE OWN USER DATA
--> Use Get --> Use Get
http://localhost:3000/user/65535cb526b586a3e2fd56cc http://localhost:3000/user/retrieveUser
{
"userId": "6554ac8dd7fbf9ee90217e77"
}

@ -0,0 +1,10 @@
const express = require('express');
const router = express.Router();
const cart = require('../controllers/cart');
const auth = require("../auth")
const { authenticateToken, } = auth
// Add route to handle adding a product to the cart
router.post('/add-to-cart', authenticateToken, cart.addToCart);
module.exports = router;

@ -4,13 +4,13 @@ const userController = require("../controllers/user")
const orderController = require("../controllers/order") const orderController = require("../controllers/order")
const auth = require("../auth"); const auth = require("../auth");
const { authenticateToken, } = auth; const { authenticateToken, verifyAdmin, verifyUser } = auth;
// User registration route // User registration route
router.post("/register", userController.registerUser) router.post("/register", userController.registerUser)
// User authentication route // User authentication route
router.post("/login", userController.authenticateUser) router.post("/authenticate", userController.authenticateUser)
// Update user data route // Update user data route
router.put("/update", authenticateToken, userController.updateUserData) router.put("/update", authenticateToken, userController.updateUserData)
@ -19,6 +19,16 @@ router.put("/update", authenticateToken, userController.updateUserData)
router.post("/order", orderController.createOrder); router.post("/order", orderController.createOrder);
// Retrieve user details // Retrieve user details
router.get('/:userId', authenticateToken, userController.getUserDetails); router.get('/retrieveUser', authenticateToken, verifyUser, userController.getUserDetails);
// EXCLUSIVE ADMIN ACCOUNT
// Set user to Admin User
router.post('/set-admin', authenticateToken, verifyAdmin, userController.setAdmin);
// Route to retrieve authenticated user's orders
router.post("/getOrders", authenticateToken, verifyUser, orderController.getOrders);
// Route to retrieve all orders
router.get("/orders-all", authenticateToken, verifyAdmin, orderController.getAllOrders);
module.exports = router module.exports = router

Loading…
Cancel
Save