├── vercel.json ├── .gitignore ├── models ├── Product.js ├── Cart.js ├── Wishlist.js ├── Review.js ├── Payment.js └── User.js ├── config.js ├── routes ├── forgotPassword.js ├── paymentRoute.js ├── wishlist.js ├── cart.js ├── review.js ├── product.js ├── auth.js └── Admin │ └── AdminAuth.js ├── middleware ├── authUser.js └── authAdmin.js ├── package.json ├── controller ├── AllProductInfo.js ├── deleteUser.js ├── AdminControl.js ├── paymentController.js └── forgotPasswordController.js ├── index.js └── README.md /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "backend", 4 | "builds": [ 5 | { 6 | "src": "index.js", 7 | "use": "@vercel/node" 8 | } 9 | ], 10 | "routes": [ 11 | { 12 | "src": "/(.*)", 13 | "dest": "/index.js" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .env 7 | .pnp.js 8 | 9 | # testing 10 | /coverage 11 | 12 | # production 13 | /build 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /models/Product.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { Schema } = mongoose; 3 | const ProductSchema = new Schema({ 4 | name: String, 5 | brand: String, 6 | price: Number, 7 | category: String, 8 | image: String, 9 | rating: Number, 10 | type: String, 11 | author: String, 12 | description: String, 13 | gender: String, 14 | }) 15 | 16 | module.exports = mongoose.model("product", ProductSchema) -------------------------------------------------------------------------------- /models/Cart.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { Schema } = mongoose; 3 | const CartSchema = new Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'user' 7 | }, 8 | productId: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | ref: 'product' 11 | }, 12 | quantity: { 13 | type: Number 14 | } 15 | 16 | }, { timestamps: true }) 17 | 18 | module.exports = mongoose.model("cart", CartSchema) -------------------------------------------------------------------------------- /models/Wishlist.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { Schema } = mongoose; 3 | const WishlistSchema = new Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'user' 7 | }, 8 | productId: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | ref: 'product' 11 | }, 12 | date: { 13 | type: Date, 14 | default: Date.now 15 | }, 16 | }) 17 | 18 | module.exports = mongoose.model("wishlist", WishlistSchema) -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const dotenv = require('dotenv'); 3 | dotenv.config() 4 | 5 | const URL = process.env.MONGO_URL 6 | mongoose.set('strictQuery', true) 7 | const connectToMongo = async () => { 8 | try { 9 | let db = await mongoose.connect(URL) 10 | console.log(db.connection.host); 11 | } catch (error) { 12 | console.log(error); 13 | } 14 | 15 | // const f = await User.find(); 16 | // console.log(f); 17 | } 18 | 19 | module.exports = connectToMongo; -------------------------------------------------------------------------------- /routes/forgotPassword.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const authUser = require('../middleware/authUser'); 4 | 5 | const dotenv = require('dotenv'); 6 | const { sendEmailLink, resetPassword,setNewPassword } = require('../controller/forgotPasswordController'); 7 | dotenv.config() 8 | 9 | router.post('/forgot-password', sendEmailLink); 10 | router.post('/forgot-password/:id/:token',setNewPassword ); 11 | router.post('/reset/password', authUser, resetPassword); 12 | module.exports = router -------------------------------------------------------------------------------- /models/Review.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { Schema } = mongoose; 3 | const ReviewSchema = new Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'user' 7 | }, 8 | productId: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | ref: 'product' 11 | }, 12 | rating: { 13 | type: Number, 14 | }, 15 | comment: { 16 | type: String 17 | }, 18 | 19 | 20 | }, { timestamps: true }) 21 | 22 | 23 | module.exports = mongoose.model("review", ReviewSchema) -------------------------------------------------------------------------------- /middleware/authUser.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const dotenv = require('dotenv'); 3 | dotenv.config() 4 | 5 | const fetchUser = (req, res, next) => { 6 | // get the user from the jwt token and id to req objectPosition: 7 | const token = req.header('Authorization'); 8 | if (!token) { 9 | return res.status(400).send("Access denied" ) 10 | } 11 | try { 12 | const data = jwt.verify(token, process.env.JWT_SECRET) 13 | req.user = data.user 14 | next() 15 | } catch (error) { 16 | res.status(400).send( "Access denied" ) 17 | 18 | } 19 | 20 | 21 | } 22 | 23 | module.exports = fetchUser -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "server": "nodemon index.js", 9 | "start": "node index.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "bcrypt": "^5.1.0", 16 | "body-parser": "^1.20.1", 17 | "cors": "^2.8.5", 18 | "dotenv": "^16.0.3", 19 | "express": "^4.18.2", 20 | "express-validator": "^6.14.2", 21 | "jsonwebtoken": "^8.5.1", 22 | "mongoose": "^6.10.4", 23 | "nodemailer": "^6.9.1", 24 | "nodemon": "^2.0.20", 25 | "razorpay": "^2.8.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /controller/AllProductInfo.js: -------------------------------------------------------------------------------- 1 | const User = require("../models/User"); 2 | const Cart = require("../models/Cart"); 3 | const Wishlist = require("../models/Wishlist"); 4 | const Review = require("../models/Review"); 5 | const Payment = require("../models/Payment") 6 | const Product = require("../models/Product") 7 | 8 | 9 | const chartData = async (req, res) => { 10 | try { 11 | const cart = await Cart.find().populate("productId"); 12 | const wishlist = await Wishlist.find().populate("productId"); 13 | 14 | const payment = await Payment.find(); 15 | const product = await Product.find(); 16 | const review = await Review.find(); 17 | res.send({ review, product, payment, wishlist, cart }); 18 | } catch (error) { 19 | res.send(error); 20 | 21 | } 22 | } 23 | module.exports = { chartData } -------------------------------------------------------------------------------- /models/Payment.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { Schema } = mongoose; 3 | const PaymentSchema = new Schema({ 4 | razorpay_order_id: { 5 | type: String, 6 | required: true, 7 | }, 8 | razorpay_payment_id: { 9 | type: String, 10 | required: true, 11 | }, 12 | razorpay_signature: { 13 | type: String, 14 | required: true, 15 | }, 16 | productData: { 17 | type: Object, 18 | required: true, 19 | }, 20 | userData: { 21 | type: Object, 22 | required: true, 23 | }, 24 | user: { 25 | type: mongoose.Schema.Types.ObjectId, 26 | ref: 'user' 27 | }, 28 | totalAmount: { 29 | type: Number, 30 | }, 31 | 32 | 33 | }, { timestamps: true }) 34 | 35 | module.exports = mongoose.model("payment", PaymentSchema) -------------------------------------------------------------------------------- /middleware/authAdmin.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const dotenv = require('dotenv'); 3 | const User = require('../models/User.js') 4 | dotenv.config() 5 | 6 | const checkAdmin = async (req, res, next) => { 7 | // get the user from the jwt token and id to req objectPosition: 8 | const token = req.header('Authorization'); 9 | if (!token) { 10 | return res.status(401).send("Access denied") 11 | } 12 | try { 13 | const data = jwt.verify(token, process.env.JWT_SECRET) 14 | req.user = data.user 15 | const checkAdmin = await User.findById(req.user.id) 16 | if (checkAdmin.isAdmin == true) { 17 | next() 18 | } 19 | else { 20 | res.status(401).send("Access denied") 21 | } 22 | } catch (error) { 23 | res.status(401).send("Access denied") 24 | 25 | } 26 | 27 | 28 | } 29 | 30 | module.exports = checkAdmin -------------------------------------------------------------------------------- /routes/paymentRoute.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { checkout, paymentVerification } = require('../controller/paymentController'); 3 | const router = express.Router() 4 | const Payment = require('../models/Payment') 5 | const User = require('../models/User') 6 | const authUser = require('../middleware/authUser') 7 | const dotenv = require('dotenv'); 8 | dotenv.config() 9 | 10 | router.route('/checkout').post(checkout) 11 | router.route('/paymentverification').post(paymentVerification) 12 | router.route('/getkey').get((req, res) => res.status(200).json({ key: process.env.RAZORPAY_API_KEY })) 13 | 14 | 15 | 16 | router.get('/getPreviousOrders', authUser, async (req, res) => { 17 | try { 18 | const data = await Payment.find({ user: req.user.id }).sort({ createdAt: -1 }) 19 | res.send(data) 20 | } 21 | catch (error) { 22 | res.status(500).send("Something went wrong") 23 | } 24 | }) 25 | 26 | module.exports = router -------------------------------------------------------------------------------- /controller/deleteUser.js: -------------------------------------------------------------------------------- 1 | const User = require("../models/User"); 2 | const Cart = require("../models/Cart"); 3 | const Wishlist = require("../models/Wishlist"); 4 | const Review = require("../models/Review"); 5 | 6 | const deleteAllUserData = async (req, res) => { 7 | const { userId } = req.params; 8 | const findUser = await User.findById(userId) 9 | if (findUser) { 10 | try { 11 | const deleteUser = await User.findByIdAndDelete(userId); 12 | const deleteCart = await Cart.deleteMany({ user: userId }); 13 | const deleteWishlist = await Wishlist.deleteMany({ user: userId }); 14 | const deleteReview = await Review.deleteMany({ user: userId }); 15 | res.send("delete successfully") 16 | } catch (error) { 17 | res.send("Something went wrong") 18 | } 19 | } 20 | else { 21 | res.status(400).send("User Not Found") 22 | } 23 | 24 | } 25 | module.exports = { deleteAllUserData } -------------------------------------------------------------------------------- /models/User.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { Schema } = mongoose; 3 | 4 | const UserSchema = new Schema({ 5 | firstName: { 6 | type: String, 7 | required: true 8 | }, 9 | lastName: { 10 | type: String, 11 | required: true 12 | }, 13 | phoneNumber: { 14 | type: Number, 15 | required: true, 16 | unique: true, 17 | }, 18 | email: { 19 | type: String, 20 | required: true, 21 | unique: true 22 | }, 23 | password: { 24 | type: String, 25 | required: true 26 | }, 27 | isAdmin:{ 28 | default:false, 29 | type:Boolean 30 | }, 31 | address: { 32 | type: String 33 | }, 34 | zipCode: { 35 | type: String 36 | }, 37 | city: { 38 | type: String 39 | }, 40 | userState: { 41 | type: String 42 | } 43 | 44 | }, { timestamps: true }); 45 | module.exports = mongoose.model('user', UserSchema) -------------------------------------------------------------------------------- /routes/wishlist.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const Wishlist = require('../models/Wishlist') 4 | const authUser = require('../middleware/authUser') 5 | 6 | 7 | router.get('/fetchwishlist', authUser, async (req, res) => { 8 | try { 9 | const wishlistData = await Wishlist.find({ user: req.user.id }).populate("productId") 10 | res.send(wishlistData) 11 | } 12 | catch (error) { 13 | res.status(500).send("Something went wrong") 14 | } 15 | }) 16 | router.post('/addwishlist', authUser, async (req, res) => { 17 | 18 | try { 19 | const { _id } = req.body 20 | const user = req.header 21 | const findProduct = await Wishlist.findOne({ $and: [{ productId: _id }, { user: req.user.id }] }) 22 | if (findProduct) { 23 | return res.status(400).json({ msg: "Product already in a wishlist" }) 24 | } 25 | else { 26 | const wishlistData = new Wishlist({ user: req.user.id, productId: _id }) 27 | const savedWishlist = await wishlistData.save() 28 | res.send(savedWishlist) 29 | } 30 | } 31 | catch (error) { 32 | res.status(500).send("Something went wrong") 33 | } 34 | }) 35 | router.delete('/deletewishlist/:id', authUser, async (req, res) => { 36 | const { id } = req.params; 37 | try { 38 | const result = await Wishlist.findByIdAndDelete(id) 39 | res.send(result) 40 | } catch (error) { 41 | res.status(500).send("Something went wrong") 42 | } 43 | 44 | 45 | 46 | }) 47 | module.exports = router -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const connectToMongo = require('./config'); 2 | const bodyParser = require('body-parser') 3 | const express = require('express') 4 | const cors = require('cors') 5 | const path = require('path'); 6 | 7 | const auth = require('./routes/auth'); 8 | const cart = require('./routes/cart') 9 | const wishlist = require('./routes/wishlist') 10 | const product = require('./routes/product') 11 | const review = require('./routes/review') 12 | const paymentRoute = require('./routes/paymentRoute') 13 | const forgotPassword = require('./routes/forgotPassword') 14 | const AdminRoute = require('./routes/Admin/AdminAuth') 15 | const dotenv = require('dotenv'); 16 | dotenv.config() 17 | 18 | connectToMongo(); 19 | 20 | const port = 5000 21 | 22 | const app = express() 23 | 24 | // create application/json parser 25 | app.use(bodyParser.json()) 26 | // create application/x-www-form-urlencoded parser 27 | app.use(bodyParser.urlencoded({ extended: false })) 28 | app.use(express.urlencoded({ extended: true })) 29 | 30 | 31 | 32 | app.use(express.json()) 33 | app.use(cors()); 34 | app.use(express.static(path.join(__dirname, 'build'))); 35 | 36 | // Available Routes 37 | app.use('/api/auth', auth) 38 | 39 | app.use('/api/product', product) 40 | 41 | app.use('/api/cart', cart) 42 | 43 | app.use('/api/wishlist', wishlist) 44 | 45 | app.use('/api/review', review) 46 | app.use('/api/admin', AdminRoute) 47 | // payment route 48 | app.use('/api', paymentRoute) 49 | 50 | // forgot Password route 51 | app.use('/api/password', forgotPassword) 52 | 53 | app.listen(port, () => { 54 | console.log(`E-commerce backend listening at http://localhost:${port}`) 55 | }) 56 | -------------------------------------------------------------------------------- /routes/cart.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | const Cart = require("../models/Cart"); 4 | const authUser = require("../middleware/authUser"); 5 | 6 | // get all cart products 7 | router.get("/fetchcart", authUser, async (req, res) => { 8 | try { 9 | const cart = await Cart.find({ user: req.user.id }) 10 | .populate("productId", "name price image rating type") 11 | .populate("user", "name email"); 12 | res.send(cart); 13 | } catch (error) { 14 | res.status(500).send("Internal server error"); 15 | } 16 | }); 17 | 18 | // add to cart 19 | 20 | router.post("/addcart", authUser, async (req, res) => { 21 | try { 22 | const { _id, quantity } = req.body; 23 | const findProduct = await Cart.findOne({ $and: [{ productId: _id }, { user: req.user.id }] }) 24 | if (findProduct) { 25 | return res.status(400).json({ msg: "Product already in a cart" }) 26 | } 27 | else { 28 | const user = req.header; 29 | const cart = new Cart({ 30 | user: req.user.id, 31 | productId: _id, 32 | quantity, 33 | }); 34 | const savedCart = await cart.save(); 35 | res.send(savedCart); 36 | } 37 | } catch (error) { 38 | res.status(500).send("Internal server error"); 39 | } 40 | }); 41 | 42 | // remove from cart 43 | router.delete("/deletecart/:id", authUser, async (req, res) => { 44 | const { id } = req.params; 45 | try { 46 | const result = await Cart.findByIdAndDelete(id) 47 | res.send(result); 48 | } catch (error) { 49 | res.status(500).send("Internal server error"); 50 | } 51 | }); 52 | module.exports = router; 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Live Link 2 | 3 | You can access the live application at [https://e-shopit.vercel.app/](https://e-shopit.vercel.app/). 4 | 5 | # MERN-E-Commerce-Backend 6 | 7 | MERN-E-Commerce-Backend is the backend of an e-commerce web application built with MongoDB, NodeJS, and ExpressJS. 8 | 9 | The frontend of the application is built with ReactJS, Material UI, React-router-dom,ContextAPI. The source code for the frontend can be found at [https://github.com/luckypenny1632333/E-Shopit-Frontend.git](https://github.com/luckypenny1632333/E-Shopit-Frontend.git). 10 | 11 | ## Features 12 | 13 | - User authentication and authorization(JWT) 14 | - Admin dashboard for managing products, orders, users and to show statistics 15 | - Payemnt Gateway 16 | - Mail Service 17 | - Forgot Password & Reset Password 18 | - Product listing and search 19 | - Product details and reviews 20 | - Cart management 21 | - Order history 22 | 23 | ## Tech Stack 24 | 25 | - ReactJS 26 | - MongoDB 27 | - NodeJS 28 | - ExpressJS 29 | 30 | ## Images 31 | 32 |  33 |  34 |  35 |  36 |  37 |  38 |  39 |  40 |  41 |  42 |  43 | 44 | ## Tech Stack 45 | 46 | - ReactJS 47 | - MongoDB 48 | - NodeJS 49 | - ExpressJS 50 | 51 | ## Installation and Usage 52 | 53 | To run the backend server on your local machine, follow these steps: 54 | 55 | 1. Clone the repository: 56 | 57 | ``` 58 | git clone https://github.com/luckypenny1632333/E-Shopit-Backend.git 59 | ``` 60 | 61 | 2. Install the dependencies: 62 | 63 | ``` 64 | cd E-Shopit-Backend 65 | npm install 66 | ``` 67 | 68 | 3. Start the development server: 69 | 70 | ``` 71 | npm run server 72 | ``` 73 | 74 | ## Contributing 75 | 76 | Contributions to the project are welcome. If you find a bug or want to add a new feature, please create a new issue or pull request. 77 | 78 | ## License 79 | 80 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information. 81 | -------------------------------------------------------------------------------- /routes/review.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const Review = require('../models/Review') 4 | const authUser = require('../middleware/authUser') 5 | 6 | router.post('/fetchreview/:id', async (req, res) => { 7 | const { filterType } = req.body 8 | try { 9 | if (filterType === 'all') { 10 | const reviewData = await Review.find({ productId: req.params.id }).populate("user", "firstName lastName") 11 | res.send(reviewData) 12 | } 13 | else if (filterType === 'mostrecent') { 14 | const reviewData = await Review.find({ productId: req.params.id }).populate("user", "firstName lastName").sort({ createdAt: -1 }) 15 | res.send(reviewData) 16 | } 17 | else if (filterType === 'old') { 18 | const reviewData = await Review.find({ productId: req.params.id }).populate("user", "firstName lastName").sort({ createdAt: 1 }) 19 | res.send(reviewData) 20 | } 21 | else if (filterType === 'positivefirst') { 22 | const reviewData = await Review.find({ productId: req.params.id, }).populate("user", "firstName lastName").sort({ rating: -1 }) 23 | res.send(reviewData) 24 | } 25 | else if (filterType === 'negativefirst') { 26 | const reviewData = await Review.find({ productId: req.params.id }).populate("user", "firstName lastName").sort({ rating: 1 }) 27 | res.send(reviewData) 28 | } 29 | else { 30 | const reviewData = await Review.find({ productId: req.params.id }).populate("user", "firstName lastName") 31 | res.send(reviewData) 32 | } 33 | 34 | } 35 | catch (error) { 36 | res.status(500).send("Internal server error") 37 | } 38 | }) 39 | 40 | router.post('/addreview', authUser, async (req, res) => { 41 | try { 42 | const { id, comment, rating } = req.body 43 | const user = req.header 44 | const findReview = await Review.findOne({ $and: [{ user: req.user.id }, { productId: id }] }) 45 | if (findReview) { 46 | return res.status(400).json({ msg: "Already reviewed that product " }) 47 | } 48 | else { 49 | const reviewData = new Review({ user: req.user.id, productId: id, comment: comment, rating: rating }) 50 | const savedReview = await reviewData.save() 51 | res.send({ msg: "Review added successfully" }) 52 | } 53 | } 54 | catch (error) { 55 | res.status(500).send("Something went wrong") 56 | } 57 | }) 58 | 59 | 60 | 61 | router.delete('/deletereview/:id', authUser, async (req, res) => { 62 | const { id } = req.params 63 | try { 64 | let deleteReview = await Review.deleteOne({ $and: [{ user: req.user.id }, { _id: id }] }) 65 | res.send({ msg: "Review deleted successfully" }) 66 | } catch (error) { 67 | res.send({ msg: "Something went wrong,Please try again letter" }) 68 | } 69 | 70 | }) 71 | 72 | 73 | 74 | router.put('/editreview', authUser, async (req, res) => { 75 | const { id, comment, rating } = req.body 76 | 77 | const review = await Review.findById(id) 78 | try { 79 | if (review) { 80 | let updateDetails = await Review.findByIdAndUpdate(id, { $set: { rating: rating, comment: comment } }) 81 | success = true 82 | res.status(200).send({ success, msg: "Review edited successfully" }) 83 | } 84 | else { 85 | return res.status(400).send({ success, error: "User Not Found" }) 86 | } 87 | } catch (error) { 88 | res.send("Something went wrong") 89 | } 90 | }) 91 | module.exports = router -------------------------------------------------------------------------------- /routes/product.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const Product = require('../models/Product') 4 | 5 | // to fetch all products 6 | router.get('/fetchproduct', async (req, res) => { 7 | try { 8 | 9 | const product = await Product.find() 10 | res.send(product) 11 | } 12 | catch (error) { 13 | 14 | res.status(500).send("Something went wrong") 15 | } 16 | }) 17 | // To get Single product 18 | router.get('/fetchproduct/:id', async (req, res) => { 19 | try { 20 | const product = await Product.findById(req.params.id) 21 | 22 | res.send(product) 23 | } catch (error) { 24 | res.status(500).send("Something went wrong") 25 | } 26 | }) 27 | // to get products for single category 28 | router.post('/fetchproduct/type', async (req, res) => { 29 | const { userType } = req.body 30 | try { 31 | const product = await Product.find({ type: userType }) 32 | res.send(product) 33 | } catch (error) { 34 | res.status(500).send("Something went wrong") 35 | } 36 | }) 37 | // to get products category wise 38 | router.post('/fetchproduct/category', async (req, res) => { 39 | const { userType, userCategory } = req.body 40 | try { 41 | if (userCategory == "all") { 42 | const product = await Product.find({ type: userType }) 43 | res.send(product) 44 | } 45 | else if (userCategory == "pricelowtohigh") { 46 | const product = await Product.find({ type: userType }).sort({ price: 1 }) 47 | res.send(product) 48 | } 49 | else if (userCategory == "pricehightolow") { 50 | const product = await Product.find({ type: userType }).sort({ price: -1 }) 51 | res.send(product) 52 | } 53 | else if (userCategory == "highrated") { 54 | const product = await Product.find({ type: userType }).sort({ rating: -1 }) 55 | res.send(product) 56 | } 57 | else if (userCategory == "lowrated") { 58 | const product = await Product.find({ type: userType }).sort({ rating: 1 }) 59 | res.send(product) 60 | } 61 | else { 62 | const product = await Product.find({ type: userType, category: userCategory }) 63 | res.send(product) 64 | } 65 | } catch (error) { 66 | res.status(500).send("Something went wrong") 67 | } 68 | }) 69 | // to search products added search filters on frontend so no need to create separate api for this 70 | 71 | // router.get('/search/:key', async (req, res) => { 72 | // const { key } = req.params 73 | // try { 74 | // if (key.length > 0) { 75 | // const product = await Product.find({ 76 | // $or: [ 77 | // { name: { $regex: key, $options: "i" } }, 78 | // { type: { $regex: key, $options: "i" } }, 79 | // { brand: { $regex: key, $options: "i" } }, 80 | // { category: { $regex: key, $options: "i" } }, 81 | // { author: { $regex: key, $options: "i" } }, 82 | // { description: { $regex: key, $options: "i" } }, 83 | // { gender: { $regex: key, $options: "i" } }, 84 | // ] 85 | // }) 86 | // if (product.length <= 0) { 87 | // res.status(400).send("Product not found") 88 | // } 89 | // else { 90 | // res.send(product) 91 | // } 92 | // } 93 | 94 | // } catch (error) { 95 | // res.status(400).send("Something went wrong") 96 | // } 97 | // }) 98 | 99 | 100 | 101 | 102 | module.exports = router -------------------------------------------------------------------------------- /routes/auth.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const jwt = require("jsonwebtoken"); 3 | const User = require('../models/User'); 4 | const router = express.Router(); 5 | const bcrypt = require('bcrypt'); 6 | const { body, validationResult } = require('express-validator'); 7 | const authUser = require('../middleware/authUser'); 8 | const dotenv = require('dotenv'); 9 | const { deleteAllUserData } = require('../controller/deleteUser'); 10 | dotenv.config() 11 | 12 | 13 | // create a user :post "/auth",!auth 14 | let success = false 15 | router.post('/register', [ 16 | 17 | body('firstName', 'Enter a valid name').isLength({ min: 1 }), 18 | body('lastName', 'Enter a valid name').isLength({ min: 1 }), 19 | body('email', 'Enter a valid email').isEmail(), 20 | body('password', 'Password must be at least 5 characters').isLength({ min: 5 }), 21 | body('phoneNumber', 'Enter a valid phone number').isLength({ min: 10, max: 10 }) 22 | 23 | 24 | ], async (req, res) => { 25 | 26 | res.c 27 | const errors = validationResult(req); 28 | if (!errors.isEmpty()) { 29 | 30 | return res.status(400).json({ error: errors.array() }) 31 | } 32 | const { firstName, lastName, email, phoneNumber, password,isAdmin } = req.body 33 | 34 | try { 35 | let user = await User.findOne({ $or: [{ email: email }, { phoneNumber: phoneNumber }] }); 36 | if (user) { 37 | return res.status(400).send({ error: "Sorry a user already exists" }) 38 | } 39 | 40 | // password hashing 41 | const salt = await bcrypt.genSalt(10) 42 | const secPass = await bcrypt.hash(password, salt) 43 | 44 | // create a new user 45 | user = await User.create({ 46 | firstName, 47 | lastName, 48 | email, 49 | phoneNumber, 50 | password: secPass, 51 | isAdmin 52 | }) 53 | const data = { 54 | user: { 55 | id: user.id 56 | } 57 | } 58 | success = true 59 | const authToken = jwt.sign(data, process.env.JWT_SECRET) 60 | res.send({ success, authToken }) 61 | } 62 | catch (error) { 63 | res.status(500).send("Internal server error") 64 | } 65 | }) 66 | 67 | 68 | // login Route 69 | router.post('/login', [ 70 | 71 | body('email', 'Enter a valid email').isEmail(), 72 | body('password', 'Password cannot be blank').exists(), 73 | 74 | ], async (req, res) => { 75 | const errors = validationResult(req); 76 | if (!errors.isEmpty()) { 77 | return res.status(400).json({ error: errors.array() }) 78 | } 79 | 80 | const { email, password, } = req.body; 81 | try { 82 | let user = await User.findOne({ email }); 83 | if (!user) { 84 | 85 | return res.status(400).send({ success, error: "User not found" }) 86 | } 87 | const passComp = await bcrypt.compare(password, user.password) 88 | if (!passComp) { 89 | return res.status(400).send({ success, error: "Please try to login with correct credentials" }) 90 | } 91 | 92 | const data = { 93 | user: { 94 | id: user._id 95 | } 96 | } 97 | 98 | const authToken = jwt.sign(data, process.env.JWT_SECRET) 99 | success = true 100 | res.send({ success, authToken }) 101 | } 102 | catch (error) { 103 | res.status(500).send("Internal server error002") 104 | } 105 | } 106 | ); 107 | // logged in user details 108 | 109 | router.get('/getuser', authUser, async (req, res) => { 110 | 111 | try { 112 | const user = await User.findById(req.user.id).select("-password") 113 | success = true 114 | res.send(user) 115 | 116 | } catch (error) { 117 | res.status(400).send("Something went wrong") 118 | } 119 | } 120 | ) 121 | 122 | 123 | // update user details 124 | router.put('/updateuser', authUser, async (req, res) => { 125 | const { userDetails } = req.body 126 | let convertData = JSON.parse(userDetails) 127 | try { 128 | const user = await User.findById(req.user.id) 129 | if (user) { 130 | let updateDetails = await User.findByIdAndUpdate(req.user.id, { $set: convertData }) 131 | success = true 132 | res.status(200).send({ success }) 133 | } 134 | else { 135 | return res.status(400).send("User Not Found") 136 | } 137 | } catch (error) { 138 | res.send("Something went wrong") 139 | } 140 | }) 141 | 142 | // delete user and user data 143 | router.delete('/delete/user/:userId', authUser, deleteAllUserData) 144 | module.exports = router -------------------------------------------------------------------------------- /routes/Admin/AdminAuth.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const jwt = require("jsonwebtoken"); 3 | const User = require('../../models/User'); 4 | const router = express.Router(); 5 | const bcrypt = require('bcrypt'); 6 | const authAdmin = require("../../middleware/authAdmin"); 7 | const { body, validationResult } = require('express-validator'); 8 | const dotenv = require('dotenv'); 9 | const { getAllUsersInfo, getSingleUserInfo, getUserCart, getUserWishlist, getUserReview, deleteUserReview, deleteUserCartItem, deleteUserWishlistItem, updateProductDetails, userPaymentDetails, addProduct, deleteProduct } = require('../../controller/AdminControl'); 10 | const { chartData } = require('../../controller/AllProductInfo'); 11 | dotenv.config() 12 | 13 | 14 | let success = false 15 | let adminKey = process.env.ADMIN_KEY 16 | router.get('/getusers', authAdmin, getAllUsersInfo); 17 | router.get('/geteuser/:userId', authAdmin, getSingleUserInfo); 18 | router.get('/getcart/:userId', authAdmin, getUserCart); 19 | router.get('/getwishlist/:userId', authAdmin, getUserWishlist); 20 | router.get('/getreview/:userId', authAdmin, getUserReview); 21 | router.get('/getorder/:id', authAdmin, userPaymentDetails); 22 | router.get('/chartdata', chartData); 23 | 24 | router.post('/login', [ 25 | body('email', 'Enter a valid email').isEmail(), 26 | body('password', 'Password cannot be blank').exists(), 27 | 28 | ], async (req, res) => { 29 | const errors = validationResult(req); 30 | if (!errors.isEmpty()) { 31 | return res.status(400).json({ error: errors.array() }) 32 | } 33 | 34 | const { email, password, key } = req.body; 35 | try { 36 | let user = await User.findOne({ email }); 37 | if (user && user.isAdmin == true && key == adminKey) { 38 | 39 | const passComp = await bcrypt.compare(password, user.password) 40 | if (!passComp) { 41 | return res.status(400).send({ success, error: "Please try to login with correct credentials" }) 42 | } 43 | 44 | const data = { 45 | user: { 46 | id: user._id 47 | } 48 | } 49 | 50 | const authToken = jwt.sign(data, process.env.JWT_SECRET) 51 | success = true 52 | res.send({ success, authToken }) 53 | } 54 | 55 | else { 56 | return res.status(400).send({ success, error: "Invalid User" }) 57 | } 58 | 59 | } 60 | catch (error) { 61 | res.status(500).send("Internal server error002") 62 | } 63 | } 64 | ); 65 | router.post('/register', [ 66 | 67 | body('firstName', 'Enter a valid name').isLength({ min: 3 }), 68 | body('lastName', 'Enter a valid name').isLength({ min: 3 }), 69 | body('email', 'Enter a valid email').isEmail(), 70 | body('password', 'Password must be at least 5 characters').isLength({ min: 5 }), 71 | body('phoneNumber', 'Enter a valid phone number').isLength({ min: 10, max: 10 }) 72 | 73 | 74 | ], async (req, res) => { 75 | const errors = validationResult(req); 76 | if (!errors.isEmpty()) { 77 | 78 | return res.status(400).json({ error: errors.array() }) 79 | } 80 | const { firstName, lastName, email, phoneNumber, password, key } = req.body 81 | 82 | try { 83 | let user = await User.findOne({ $or: [{ email: email }, { phoneNumber: phoneNumber }] }); 84 | if (user) { 85 | return res.status(400).send({ error: "Sorry a user already exists" }) 86 | } 87 | 88 | if (key != adminKey) { 89 | return res.status(400).send({ error: "Invalid User" }) 90 | } 91 | // password hashing 92 | const salt = await bcrypt.genSalt(10) 93 | const secPass = await bcrypt.hash(password, salt) 94 | 95 | // create a new user 96 | user = await User.create({ 97 | firstName, 98 | lastName, 99 | email, 100 | phoneNumber, 101 | password: secPass, 102 | isAdmin: true 103 | }) 104 | const data = { 105 | user: { 106 | id: user.id 107 | } 108 | } 109 | success = true 110 | const authToken = jwt.sign(data, process.env.JWT_SECRET) 111 | res.send({ success, authToken }) 112 | } 113 | catch (error) { 114 | res.status(500).send("Internal server error") 115 | } 116 | }) 117 | router.post('/addproduct', authAdmin, addProduct); 118 | 119 | 120 | 121 | router.put('/updateproduct/:id', authAdmin, updateProductDetails) 122 | 123 | 124 | 125 | router.delete('/review/:id', authAdmin, deleteUserReview); 126 | router.delete('/usercart/:id', authAdmin, deleteUserCartItem); 127 | router.delete('/userwishlist/:id', authAdmin, deleteUserWishlistItem); 128 | router.delete('/deleteproduct/:id', authAdmin, deleteProduct); 129 | 130 | 131 | module.exports = router -------------------------------------------------------------------------------- /controller/AdminControl.js: -------------------------------------------------------------------------------- 1 | const User = require("../models/User"); 2 | const Cart = require("../models/Cart"); 3 | const Wishlist = require("../models/Wishlist"); 4 | const Review = require("../models/Review"); 5 | const Product = require("../models/Product"); 6 | const Payment = require("../models/Payment"); 7 | let success = false; 8 | const getAllUsersInfo = async (req, res) => { 9 | try { 10 | const data = await User.find().select('-password'); 11 | // console.log(data); 12 | res.send(data) 13 | 14 | } catch (error) { 15 | console.log(error); 16 | res.status(400).send("Something went wrong") 17 | } 18 | } 19 | const getSingleUserInfo = async (req, res) => { 20 | const { userId } = req.params; 21 | const findUser = await User.findById(userId) 22 | if (findUser) { 23 | try { 24 | const findUser = await User.findById(userId).select('-password'); 25 | res.send(findUser); 26 | } catch (error) { 27 | res.send("Something went wrong") 28 | } 29 | } 30 | else { 31 | res.status(400).send("User Not Found") 32 | } 33 | 34 | } 35 | const getUserCart = async (req, res) => { 36 | const { userId } = req.params; 37 | const findUser = await User.findById(userId) 38 | if (findUser) { 39 | try { 40 | const findUserCart = await Cart.find({ user: userId }) 41 | .populate("productId", "name price image rating type") 42 | .populate("user", "name email"); 43 | res.send(findUserCart); 44 | } catch (error) { 45 | res.send("Something went wrong") 46 | } 47 | } 48 | else { 49 | res.status(400).send("User Not Found") 50 | } 51 | 52 | } 53 | const getUserWishlist = async (req, res) => { 54 | const { userId } = req.params; 55 | const findUser = await User.findById(userId) 56 | if (findUser) { 57 | try { 58 | const findUserWishlist = await Wishlist.find({ user: userId }).populate("productId") 59 | res.send(findUserWishlist); 60 | } catch (error) { 61 | res.send("Something went wrong") 62 | } 63 | } 64 | else { 65 | res.status(400).send("User Not Found") 66 | } 67 | 68 | } 69 | const getUserReview = async (req, res) => { 70 | const { userId } = req.params; 71 | const findUser = await User.findById(userId) 72 | if (findUser) { 73 | try { 74 | 75 | const findUserReview = await Review.find({ user: userId }) 76 | .populate("productId", "name price image rating type") 77 | .populate("user", "firstName lastName"); 78 | res.send(findUserReview); 79 | } catch (error) { 80 | res.send("Something went wrong") 81 | } 82 | } 83 | else { 84 | res.status(400).send("User Not Found") 85 | } 86 | 87 | } 88 | 89 | const deleteUserReview = async (req, res) => { 90 | const { id } = req.params; 91 | try { 92 | let deleteReview = await Review.findByIdAndDelete(id) 93 | res.send({ msg: "Review deleted successfully" }) 94 | } catch (error) { 95 | res.status(400).send({ msg: "Something went wrong,Please try again letter", error }) 96 | } 97 | } 98 | 99 | 100 | const deleteUserCartItem = async (req, res) => { 101 | const { id } = req.params; 102 | try { 103 | let deleteCart = await Cart.findByIdAndDelete(id) 104 | success = true 105 | res.send({ success, msg: "Review deleted successfully" }) 106 | } catch (error) { 107 | res.status(400).send({ msg: "Something went wrong,Please try again letter1" }) 108 | } 109 | } 110 | const deleteUserWishlistItem = async (req, res) => { 111 | const { id } = req.params; 112 | console.log(id); 113 | try { 114 | let deleteCart = await Wishlist.findByIdAndDelete(id) 115 | success = true 116 | res.send({ success, msg: "Review deleted successfully" }) 117 | } catch (error) { 118 | res.status(400).send({ msg: "Something went wrong,Please try again letter" }) 119 | } 120 | } 121 | 122 | 123 | const updateProductDetails = async (req, res) => { 124 | const updateProduct = req.body.productDetails; 125 | updateProduct.price = parseFloat(updateProduct.price); 126 | updateProduct.rating = parseFloat(updateProduct.rating); 127 | const { id } = req.params; 128 | const product = await Product.findById(id) 129 | if (product) { 130 | try { 131 | let update = await Product.findByIdAndUpdate(id, { $set: updateProduct }) 132 | success = true 133 | const findType = await Product.find({ type: "book" }).distinct('category') 134 | 135 | res.send({ success, msg: "Product updated successfully", findType }) 136 | 137 | } catch (error) { 138 | // return res.status(400).send({ success, error: error }) 139 | return res.status(400).send(error) 140 | } 141 | } 142 | else { 143 | return res.status(400).send({ success, error: "Product not found" }) 144 | } 145 | 146 | } 147 | 148 | const userPaymentDetails = async (req, res) => { 149 | const { id } = req.params; 150 | const findPayment = await Payment.find({ user: id }) 151 | if (findPayment) { 152 | try { 153 | res.send(findPayment) 154 | } catch (error) { 155 | return res.status(400).send(error) 156 | } 157 | } 158 | else { 159 | return res.status(400).send({ total: 0 }) 160 | } 161 | } 162 | 163 | const addProduct = async (req, res) => { 164 | const { name, brand, price, category, image, rating, type, author, description, gender } = req.body; 165 | try { 166 | await Product.create({ name, brand, price, category, image, rating, type, author, description, gender }) 167 | success = true 168 | res.send(success) 169 | 170 | } catch (error) { 171 | console.log(error); 172 | return res.status(400).send(error) 173 | } 174 | } 175 | 176 | const deleteProduct = async (req, res) => { 177 | const { id } = req.params; 178 | let findProduct = await Product.findById(id); 179 | if (findProduct) { 180 | try { 181 | await Product.findByIdAndDelete(id) 182 | success = true 183 | res.send(success) 184 | } catch (error) { 185 | return res.status(400).send(error) 186 | } 187 | } 188 | else { 189 | return res.status(400).send({ success, msg: "Product Not Found" }) 190 | } 191 | } 192 | 193 | module.exports = { 194 | getAllUsersInfo, getSingleUserInfo, 195 | getUserCart, getUserWishlist, 196 | getUserReview, deleteUserReview, 197 | deleteUserCartItem, deleteUserWishlistItem, 198 | updateProductDetails, userPaymentDetails, addProduct, deleteProduct 199 | } -------------------------------------------------------------------------------- /controller/paymentController.js: -------------------------------------------------------------------------------- 1 | const Razorpay = require('razorpay'); 2 | const crypto = require('crypto'); 3 | const Payment = require('../models/Payment'); 4 | const Cart = require('../models/Cart'); 5 | const nodemailer = require('nodemailer'); 6 | const dotenv = require('dotenv'); 7 | dotenv.config() 8 | 9 | 10 | let productInfo = {}; 11 | let userData = {}; 12 | let userInfo; 13 | let totalAmount; 14 | const instance = new Razorpay({ 15 | key_id: process.env.RAZORPAY_API_KEY, 16 | key_secret: process.env.RAZORPAY_API_SECRET, 17 | }); 18 | const checkout = async (req, res) => { 19 | 20 | try { 21 | const { amount, userId, productDetails, userDetails } = req.body 22 | totalAmount = Number(amount) 23 | userInfo = userId 24 | productInfo = JSON.parse(productDetails) 25 | userData = JSON.parse(userDetails) 26 | 27 | 28 | const options = { 29 | amount: Number(amount * 100), 30 | currency: "INR", 31 | }; 32 | const order = await instance.orders.create(options); 33 | 34 | 35 | res.status(200).json({ 36 | success: true, 37 | order 38 | }); 39 | 40 | } catch (error) { 41 | console.log(error); 42 | } 43 | 44 | 45 | }; 46 | // 47 | 48 | const paymentVerification = async (req, res) => { 49 | 50 | const { razorpay_order_id, razorpay_payment_id, razorpay_signature } = req.body; 51 | 52 | const body = razorpay_order_id + "|" + razorpay_payment_id; 53 | 54 | const expectedSignature = crypto 55 | .createHmac("sha256", process.env.RAZORPAY_API_SECRET) 56 | .update(body.toString()) 57 | .digest("hex"); 58 | 59 | const isAuthentic = expectedSignature === razorpay_signature; 60 | try { 61 | if (isAuthentic) { 62 | // Database comes here 63 | const transport = nodemailer.createTransport({ 64 | service: "gmail", 65 | host: "smtp.gmail.email", 66 | port: 465, 67 | auth: { 68 | user: process.env.EMAIL, 69 | pass: process.env.EMAIL_PASSWORD 70 | }, 71 | }) 72 | const mailOptions = { 73 | from: process.env.EMAIL, 74 | to: userData.userEmail, 75 | subject: "Order Confirm", 76 | html: ` 77 | 78 |
79 | 80 |Dear ${userData.firstName} ${userData.lastName},
148 |Thank you for your recent purchase on our website. We have received your payment of ₹${totalAmount} and have processed your order.
149 || Product Name | 153 |Quantity | 154 |Price | 155 |
|---|---|---|
| ${product.productId.name} | 162 |${product.quantity} | 163 |₹${product.productId.price} | 164 |
| Shipping Charge | 170 |171 | | ₹100 | 172 |
| Total | 175 |176 | | ₹${totalAmount} | 177 |
${userData.firstName} ${userData.lastName}
183 |${userData.address}
184 |${userData.city}-${userData.zipCode}
185 |${userData.userState}
186 |Thank you for choosing our website. If you have any questions or concerns, please don't hesitate to contact us.
188 |Best regards,
190 | 191 |Dear ${userData.firstName} ${userData.lastName},
267 |Thank you for your recent purchase on our website. We have received your payment of ₹${totalAmount} and have processed your order.
268 || Product Name | 272 |Quantity | 273 |Price | 274 |
|---|---|---|
| ${product.productId.name} | 281 |${product.quantity} | 282 |₹${product.productId.price} | 283 |
| Shipping Charge | 289 |290 | | ₹100 | 291 |
| Total | 294 |295 | | ₹${totalAmount} | 296 |
${userData.firstName} ${userData.lastName}
302 |${userData.address}
303 |${userData.city}-${userData.zipCode}
304 |${userData.userState}
305 |Thank you for choosing our website. If you have any questions or concerns, please don't hesitate to contact us.
307 |Best regards,
309 | 310 ||
130 |
131 |
132 |
133 |
134 |
175 |
176 |
177 |
178 |
135 |
174 |
136 |
137 |
138 |
139 |
173 |
140 |
170 |
171 |
172 |
141 |
169 |
142 |
143 |
168 |
179 |
226 |
227 |
228 |
229 |
180 |
225 |
181 |
182 |
183 |
184 |
224 |
185 |
221 |
222 |
223 |
186 |
220 |
187 |
188 |
219 |
230 |
267 |
268 |
269 |
270 |
231 |
266 |
232 |
233 |
234 |
235 |
265 |
236 |
262 |
263 |
264 |
237 |
261 |
238 |
239 |
260 |
|
271 |
302 |
303 |
304 |
305 | |
306 |
|
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
|