├── README.md ├── routes ├── auth.route.js ├── product.route.js ├── routes.js └── user.route.js ├── dbConnect └── dbConnection.js ├── server.js ├── package.json ├── models ├── cart.model.js ├── user.model.js ├── product.model.js └── order.model.js ├── controllers ├── product.controller.js ├── auth.controller.js └── user.controller.js └── middleware └── verifyToken.js /README.md: -------------------------------------------------------------------------------- 1 | # yt-ecommerce-shop 2 | A youtube Tutorial 3 | -------------------------------------------------------------------------------- /routes/auth.route.js: -------------------------------------------------------------------------------- 1 | const { register, login } = require("../controllers/auth.controller.js"); 2 | 3 | const router = require("express").Router(); 4 | 5 | router.post("/register", register); 6 | 7 | router.post("/login", login); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/product.route.js: -------------------------------------------------------------------------------- 1 | const { createProduct } = require("../controllers/product.controller"); 2 | const { verifyAdmin } = require("../middleware/verifyToken"); 3 | 4 | const router = require("express").Router(); 5 | 6 | router.post("/", verifyAdmin, createProduct); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /dbConnect/dbConnection.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const dotenv = require("dotenv"); 3 | dotenv.config(); 4 | 5 | const dbConnect = async () => { 6 | try { 7 | await mongoose.connect(process.env.DB_URL); 8 | console.log("Database has been connected successfully"); 9 | } catch (err) { 10 | console.log(err); 11 | } 12 | }; 13 | 14 | module.exports = dbConnect; 15 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const dbConnect = require("./dbConnect/dbConnection"); 3 | const app = express(); 4 | const routes = require("./routes/routes.js"); 5 | 6 | app.use(express.json()); 7 | 8 | app.use("/", routes); 9 | 10 | app.get("/", (req, res) => { 11 | res.send("My backend Works"); 12 | }); 13 | app.listen(process.env.PORT || 5000, () => { 14 | console.log(`Server is running on ${process.env.PORT || 5000}`); 15 | dbConnect(); 16 | }); 17 | -------------------------------------------------------------------------------- /routes/routes.js: -------------------------------------------------------------------------------- 1 | const router = require("express").Router(); 2 | const userRoutes = require("./user.route.js"); 3 | const authRoutes = require("./auth.route.js"); 4 | const productRoutes = require("./product.route.js"); 5 | 6 | const base = "/api/v1"; 7 | 8 | router.use(`${base}/users`, userRoutes); 9 | router.use(`${base}/auth`, authRoutes); 10 | router.use(`${base}/products`, productRoutes); 11 | 12 | module.exports = router; 13 | 14 | //http:localhost:4000/api/v1/auth/register 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "nodemon server.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^5.1.1", 14 | "body-parser": "^1.20.2", 15 | "dotenv": "^16.3.1", 16 | "express": "^4.18.2", 17 | "jsonwebtoken": "^9.0.2", 18 | "mongoose": "^5.12.15", 19 | "nodemon": "^3.0.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /models/cart.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const cartModel = new Schema( 5 | { 6 | userId: { 7 | type: String, 8 | required: true, 9 | }, 10 | product: [ 11 | { 12 | productId: { 13 | type: String, 14 | }, 15 | quantity: { 16 | type: Number, 17 | default: 1, 18 | }, 19 | }, 20 | ], 21 | }, 22 | { 23 | timestamps: true, 24 | } 25 | ); 26 | 27 | module.exports = mongoose.model("Cart", cartModel); 28 | -------------------------------------------------------------------------------- /controllers/product.controller.js: -------------------------------------------------------------------------------- 1 | const Product = require("../models/product.model.js"); 2 | 3 | const createProduct = async (req, res) => { 4 | try { 5 | const newProduct = new Product(req.body); 6 | await newProduct.save(); 7 | res.status(200).json({ 8 | message: "Product created Successfully", 9 | newProduct, 10 | }); 11 | } catch (error) { 12 | console.log(error); 13 | res.status(500).json({ 14 | message: "An Error Occurred while Creatng the Product", 15 | error: error.message, 16 | }); 17 | } 18 | }; 19 | 20 | module.exports = { 21 | createProduct, 22 | }; 23 | -------------------------------------------------------------------------------- /models/user.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const userModel = new Schema( 5 | { 6 | username: { 7 | type: String, 8 | required: true, 9 | unique: true, 10 | }, 11 | email: { 12 | type: String, 13 | required: true, 14 | unique: true, 15 | }, 16 | password: { 17 | type: String, 18 | required: true, 19 | }, 20 | isAdmin: { 21 | type: Boolean, 22 | default: false, 23 | }, 24 | }, 25 | { 26 | timestamps: true, 27 | } 28 | ); 29 | 30 | module.exports = mongoose.model("User", userModel); 31 | -------------------------------------------------------------------------------- /routes/user.route.js: -------------------------------------------------------------------------------- 1 | const { 2 | updateUser, 3 | deleteUser, 4 | getAdmin, 5 | getAllUsers, 6 | getUserStats, 7 | } = require("../controllers/user.controller"); 8 | const { verifyToken, verifyAdmin } = require("../middleware/verifyToken"); 9 | 10 | const router = require("express").Router(); 11 | 12 | router.get("/get-users", (req, res) => { 13 | res.send("user has been gotten"); 14 | }); 15 | 16 | router.put("/update/:id", verifyToken, updateUser); 17 | router.delete("/delete/:id", verifyAdmin, deleteUser); 18 | router.get("/get-admin/:id", verifyAdmin, getAdmin); 19 | router.get("/", verifyToken, getAllUsers); 20 | router.get("/stats", verifyAdmin, getUserStats); 21 | 22 | module.exports = router; 23 | -------------------------------------------------------------------------------- /models/product.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const productModel = new Schema( 5 | { 6 | title: { 7 | type: String, 8 | required: true, 9 | unique: true, 10 | }, 11 | desc: { 12 | type: String, 13 | required: true, 14 | }, 15 | image: { 16 | type: String, 17 | required: true, 18 | }, 19 | categories: { 20 | type: Array, 21 | default: [], 22 | }, 23 | size: { 24 | type: String, 25 | }, 26 | color: { 27 | type: String, 28 | }, 29 | price: { 30 | type: String, 31 | }, 32 | }, 33 | { 34 | timestamps: true, 35 | } 36 | ); 37 | 38 | module.exports = mongoose.model("Product", productModel); 39 | -------------------------------------------------------------------------------- /models/order.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const orderModel = new Schema( 5 | { 6 | userId: { 7 | type: String, 8 | required: true, 9 | }, 10 | product: [ 11 | { 12 | productId: { 13 | type: String, 14 | }, 15 | quantity: { 16 | type: Number, 17 | default: 1, 18 | }, 19 | }, 20 | ], 21 | amount: { 22 | type: Number, 23 | required: true, 24 | }, 25 | address: { 26 | type: Object, 27 | required: true, 28 | }, 29 | status: { 30 | type: String, 31 | default: "pending", 32 | }, 33 | }, 34 | { 35 | timestamps: true, 36 | } 37 | ); 38 | 39 | module.exports = mongoose.model("order", orderModel); 40 | -------------------------------------------------------------------------------- /middleware/verifyToken.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | 3 | const verifyToken = (req, res, next) => { 4 | const authHeader = req.headers["authorization"]; 5 | const token = authHeader && authHeader.split(" ")[1]; 6 | 7 | if (!token) return res.status(401).send("Access Denied"); 8 | 9 | try { 10 | const verified = jwt.verify(token, process.env.JWT_KEY); 11 | req.user = verified; 12 | next(); 13 | } catch (error) { 14 | console.log(error); 15 | res.status(400).send("Invalid Token"); 16 | } 17 | }; 18 | 19 | const verifyAdmin = (req, res, next) => { 20 | verifyToken(req, res, () => { 21 | if (req.user.isAdmin) { 22 | next(); 23 | } else { 24 | return res.status(500).send("User is not an Admin"); 25 | } 26 | }); 27 | }; 28 | 29 | module.exports = { 30 | verifyToken, 31 | verifyAdmin, 32 | }; 33 | -------------------------------------------------------------------------------- /controllers/auth.controller.js: -------------------------------------------------------------------------------- 1 | const bcrypt = require("bcrypt"); 2 | const jwt = require("jsonwebtoken"); 3 | const User = require("../models/user.model.js"); 4 | 5 | const register = async (req, res) => { 6 | try { 7 | const hashedPassword = bcrypt.hashSync(req.body.password, 10); 8 | const newUser = new User({ 9 | username: req.body.username, 10 | email: req.body.email, 11 | password: hashedPassword, 12 | }); 13 | 14 | await newUser.save(); 15 | 16 | const { password, ...info } = newUser._doc; 17 | res.status(200).json({ 18 | message: "User Created Successfully", 19 | data: info, 20 | }); 21 | } catch (error) { 22 | console.log(error); 23 | res.status(500).json({ 24 | message: "User Creation failed", 25 | error: error, 26 | }); 27 | } 28 | }; 29 | 30 | const login = async (req, res) => { 31 | try { 32 | const user = await User.findOne({ email: req.body.email }); 33 | if (!user) { 34 | return res.status(404).json({ 35 | message: "Email does not exist", 36 | }); 37 | } 38 | 39 | const comparedPassword = await bcrypt.compare( 40 | req.body.password, 41 | user.password 42 | ); 43 | if (!comparedPassword) { 44 | return res.status(404).json({ 45 | message: "Email Or Password is incorrect", 46 | }); 47 | } 48 | 49 | const token = jwt.sign( 50 | { 51 | userId: user._id, 52 | isAdmin: user.isAdmin, 53 | }, 54 | process.env.JWT_KEY, 55 | { 56 | expiresIn: "5d", 57 | } 58 | ); 59 | 60 | const { password, ...info } = user._doc; 61 | 62 | res.status(200).json({ 63 | data: { ...info, token }, 64 | massage: "login successful", 65 | }); 66 | } catch (error) { 67 | console.log(error); 68 | res.status(500).json({ 69 | message: "Login Failed", 70 | error: error, 71 | }); 72 | } 73 | }; 74 | 75 | module.exports = { 76 | register, 77 | login, 78 | }; 79 | -------------------------------------------------------------------------------- /controllers/user.controller.js: -------------------------------------------------------------------------------- 1 | const User = require("../models/user.model.js"); 2 | 3 | const updateUser = async (req, res) => { 4 | try { 5 | const updatedUser = await User.findByIdAndUpdate( 6 | req.params.id, 7 | { 8 | $set: req.body, 9 | }, 10 | { 11 | new: true, 12 | } 13 | ); 14 | if (!updatedUser) { 15 | return res.status(404).json({ 16 | message: "User not Found!", 17 | }); 18 | } 19 | res.status(200).json({ 20 | message: "User has been Updated Successfully", 21 | data: updatedUser, 22 | }); 23 | } catch (err) { 24 | console.log(err); 25 | res.status(500).json({ 26 | message: "User Update Failed", 27 | error: err, 28 | }); 29 | } 30 | }; 31 | 32 | const deleteUser = async (req, res) => { 33 | try { 34 | await User.findByIdAndDelete(req.params.id); 35 | res.status(200).json({ 36 | message: "User has been deleted Successfully", 37 | }); 38 | } catch (error) { 39 | console.log(error); 40 | res.status(500).json({ 41 | message: "User Deletion Failed!", 42 | }); 43 | } 44 | }; 45 | 46 | const getAdmin = async (req, res) => { 47 | try { 48 | const admin = await User.findById(req.params.id); 49 | if (!admin) { 50 | return res.status(404).json({ 51 | message: "User can't be found", 52 | }); 53 | } 54 | const { password, ...info } = admin._doc; 55 | res.status(200).json({ 56 | message: "User has been found successfully", 57 | data: info, 58 | }); 59 | } catch (error) { 60 | console.log(error); 61 | res.status(500).json({ 62 | message: "User query failed", 63 | error: error, 64 | }); 65 | } 66 | }; 67 | 68 | const getAllUsers = async (req, res) => { 69 | const query = req.query.latest; 70 | try { 71 | const users = query 72 | ? await User.find().sort({ _id: -1 }).limit(3) 73 | : await User.find(); 74 | 75 | res.status(200).json({ 76 | message: "Users have been found successfully", 77 | data: users, 78 | }); 79 | } catch (error) { 80 | console.log(error); 81 | res.status(500).json({ 82 | message: "User query failed", 83 | error: error, 84 | }); 85 | } 86 | }; 87 | 88 | const getUserStats = async (req, res) => { 89 | try { 90 | const date = new Date(); 91 | const lastYear = new Date(date.setFullYear(date.getFullYear() - 1)); 92 | 93 | const userStats = await User.aggregate([ 94 | { 95 | $match: { createdAt: { $gte: lastYear } }, 96 | }, 97 | { 98 | $project: { 99 | month: { $month: "$createdAt" }, 100 | }, 101 | }, 102 | { 103 | $group: { 104 | _id: "$month", 105 | total: { $sum: 1 }, 106 | }, 107 | }, 108 | ]); 109 | res.status(200).json({ 110 | message: "User Stats Retrieved Successfully", 111 | userStats 112 | }) 113 | } catch (error) { 114 | console.log(error); 115 | res.status(500).json({ 116 | message: "An error occurred aquiring User Statistics", 117 | error: error.message, 118 | }); 119 | } 120 | }; 121 | 122 | module.exports = { 123 | updateUser, 124 | deleteUser, 125 | getAdmin, 126 | getAllUsers, 127 | getUserStats, 128 | }; 129 | --------------------------------------------------------------------------------