From 46a43561eef76209a07f8bc289b012c0fa014e46 Mon Sep 17 00:00:00 2001 From: sujal Date: Sat, 18 May 2024 13:53:56 +0530 Subject: [PATCH 1/2] ADDED NEW API --- New_APIs/Ecom/.gitignore | 8 ++ New_APIs/Ecom/Readme.md | 28 +++++++ New_APIs/Ecom/index.js | 35 +++++++++ New_APIs/Ecom/models/cart.js | 14 ++++ New_APIs/Ecom/models/order.js | 17 +++++ New_APIs/Ecom/models/product.js | 14 ++++ New_APIs/Ecom/models/user.js | 13 ++++ New_APIs/Ecom/package.json | 21 ++++++ New_APIs/Ecom/routes/auth.js | 54 ++++++++++++++ New_APIs/Ecom/routes/car.js | 79 ++++++++++++++++++++ New_APIs/Ecom/routes/ord.js | 109 ++++++++++++++++++++++++++++ New_APIs/Ecom/routes/prod.js | 92 +++++++++++++++++++++++ New_APIs/Ecom/routes/user.js | 100 +++++++++++++++++++++++++ New_APIs/Ecom/routes/verifytoken.js | 44 +++++++++++ 14 files changed, 628 insertions(+) create mode 100644 New_APIs/Ecom/.gitignore create mode 100644 New_APIs/Ecom/Readme.md create mode 100644 New_APIs/Ecom/index.js create mode 100644 New_APIs/Ecom/models/cart.js create mode 100644 New_APIs/Ecom/models/order.js create mode 100644 New_APIs/Ecom/models/product.js create mode 100644 New_APIs/Ecom/models/user.js create mode 100644 New_APIs/Ecom/package.json create mode 100644 New_APIs/Ecom/routes/auth.js create mode 100644 New_APIs/Ecom/routes/car.js create mode 100644 New_APIs/Ecom/routes/ord.js create mode 100644 New_APIs/Ecom/routes/prod.js create mode 100644 New_APIs/Ecom/routes/user.js create mode 100644 New_APIs/Ecom/routes/verifytoken.js diff --git a/New_APIs/Ecom/.gitignore b/New_APIs/Ecom/.gitignore new file mode 100644 index 0000000..833994f --- /dev/null +++ b/New_APIs/Ecom/.gitignore @@ -0,0 +1,8 @@ +# Ignore node_modules directory +node_modules/ + +# Ignore .env files +.env + + +package-lock.json \ No newline at end of file diff --git a/New_APIs/Ecom/Readme.md b/New_APIs/Ecom/Readme.md new file mode 100644 index 0000000..3784bc7 --- /dev/null +++ b/New_APIs/Ecom/Readme.md @@ -0,0 +1,28 @@ +# **Ecom API** + +### Overview +This project is an Express.js based API for managing users, authentication, products, carts, and orders. It provides endpoints for CRUD operations on these resources and includes authentication and authorization middleware. + +### Prerequisites +Before you begin, ensure you have met the following requirements: + +Node.js installed +MongoDB installed and running +npm installed + +### Installation + +**Clone the repository:** + git clone https://github.com/your-username/repository-name.git + cd repository-name + +**Install dependencies:** + npm install + + +### Create a .env file in the root directory and add your environment variables: + + PORT=Your_Desired_Port + MONGO_URL=your_mongodb_connection_string + JWT_SECRET=your_jwt_secret + SECRET_PHRASE=your_secret_phrase \ No newline at end of file diff --git a/New_APIs/Ecom/index.js b/New_APIs/Ecom/index.js new file mode 100644 index 0000000..42d1c39 --- /dev/null +++ b/New_APIs/Ecom/index.js @@ -0,0 +1,35 @@ +const express=require('express'); +const app=express(); +const dotenv=require('dotenv') +dotenv.config(); +const mongoose=require('mongoose') +const userRoute=require('./routes/user') +const authRoute=require('./routes/auth') +const prodRoute=require('./routes/prod') +const carRoute=require('./routes/car') +const orderRoute=require('./routes/ord') + + + +mongoose.connect(process.env.url +).then(()=>{ + console.log("Db connection successfull" + ) +}).catch((err)=>{ + console.log(err); +}) + + +//middlewares + +app.use(express.json()) +app.use("/api/auth",authRoute) +app.use("/api/user",userRoute) +app.use("/api/prod",prodRoute) +app.use("/api/car",carRoute) +app.use("/api/ord",orderRoute) + + +app.listen(process.env.Port,()=>{ + console.log("server running"); +}) diff --git a/New_APIs/Ecom/models/cart.js b/New_APIs/Ecom/models/cart.js new file mode 100644 index 0000000..8364785 --- /dev/null +++ b/New_APIs/Ecom/models/cart.js @@ -0,0 +1,14 @@ +const mongoose=require('mongoose') + +const CartSchema=new mongoose.Schema({ + userId:{type:String,required:true}, + products:[{ + product:{type:String,required:true}, + quantity:{ + type:Number, + default:1 + } + }] +},{timestamps:true}); + +module.exports=mongoose.model('Cart',CartSchema) \ No newline at end of file diff --git a/New_APIs/Ecom/models/order.js b/New_APIs/Ecom/models/order.js new file mode 100644 index 0000000..28dc926 --- /dev/null +++ b/New_APIs/Ecom/models/order.js @@ -0,0 +1,17 @@ +const mongoose=require('mongoose') + +const OrderSchema=new mongoose.Schema({ + userId:{type:String,required:true}, + products:[{ + product:{type:String,required:true}, + quantity:{ + type:Number, + default:1 + } + }], + amount:{type:Number,required:true}, + address:{type:Object,required:true}, + status:{type:String, default:"pending"} +},{timeStamps:true}); + +module.exports=mongoose.model('order',OrderSchema) \ No newline at end of file diff --git a/New_APIs/Ecom/models/product.js b/New_APIs/Ecom/models/product.js new file mode 100644 index 0000000..8093774 --- /dev/null +++ b/New_APIs/Ecom/models/product.js @@ -0,0 +1,14 @@ +const mongoose=require('mongoose') + +const ProductSchema=new mongoose.Schema({ + title:{type:String,required:true,unique:true}, + description:{type:String,required:true,unique:true}, + img:{type:String,required:true,unique:true}, + categories:{type:Array}, + size:{type:String}, + color:{type:String}, + price:{type:String,required:true,unique:true}, + +},{timestamps:true}); + +module.exports=mongoose.model('Product',ProductSchema) \ No newline at end of file diff --git a/New_APIs/Ecom/models/user.js b/New_APIs/Ecom/models/user.js new file mode 100644 index 0000000..525109b --- /dev/null +++ b/New_APIs/Ecom/models/user.js @@ -0,0 +1,13 @@ +const mongoose=require('mongoose') + +const UserSchema=new mongoose.Schema({ + username:{type:String,required:true,unique:true}, + email:{type:String,required:true,unique:true}, + password:{type:String,required:true,unique:true}, + isAdmin:{ + type:Boolean, + default: false + }, +},{timestamps:true}); + +module.exports=mongoose.model('User',UserSchema) \ No newline at end of file diff --git a/New_APIs/Ecom/package.json b/New_APIs/Ecom/package.json new file mode 100644 index 0000000..d3df11f --- /dev/null +++ b/New_APIs/Ecom/package.json @@ -0,0 +1,21 @@ +{ + "name": "ecom", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "nodemon index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "cors": "^2.8.5", + "crypto-js": "^4.2.0", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.3.1", + "stripe": "^15.0.0" + } +} diff --git a/New_APIs/Ecom/routes/auth.js b/New_APIs/Ecom/routes/auth.js new file mode 100644 index 0000000..2fd92ca --- /dev/null +++ b/New_APIs/Ecom/routes/auth.js @@ -0,0 +1,54 @@ +const router=require('express').Router(); +const User=require('../models/user') +const crypto=require("crypto-js") +const jwt=require('jsonwebtoken') + +router.post("/register",async(req,res)=>{ + const newuser=new User({ + username:req.body.username, + email:req.body.email, + password:crypto.AES.encrypt(req.body.password,process.env.secretphrase).toString() + }); + try{ + const saved=await newuser.save(); + res.status(201).json(saved)} + catch(err){ + res.status(500).json(err); + } +}) + +//login route +router.post("/login", async (req, res, next) => { + try { + const user = await User.findOne({ username: req.body.username }); + + if (!user) { + return res.status(401).json("Wrong credentials1"); + } + + const hash = crypto.AES.decrypt(user.password, process.env.secretphrase); + let originalpass = hash.toString(crypto.enc.Utf8); + + if (originalpass !== req.body.password) { + return res.status(401).json("Wrong credentials2"); + } + + const access=jwt.sign({ + id:user._id, + isAdmin:user.isAdmin, + }, + process.env.jwtsecret, + {expiresIn:'3d'} + ) + console.log(user._doc) + const { password, ...others } = user._doc; + + res.status(200).json({...others,access}); + } catch (err) { + res.status(500).json(err); + } +}); + + + +module.exports=router; \ No newline at end of file diff --git a/New_APIs/Ecom/routes/car.js b/New_APIs/Ecom/routes/car.js new file mode 100644 index 0000000..400adfa --- /dev/null +++ b/New_APIs/Ecom/routes/car.js @@ -0,0 +1,79 @@ +const router=require('express').Router(); +const cart = require('../models/cart'); +const { verifyToken, verifynauth, verifynadmin } = require('./verifytoken'); + +//create + +router.post("/add",verifyToken,async (req,res)=>{ + const newc=new cart(req.body) + try{ + const saved=await newc.save(); + res.status(200).json(saved) + }catch(err){ + res.status(500).json(err); + } +}) + +//updates + +router.put("/upd/:id",verifyToken,async (req,res)=>{ + try { + const updated = await cart.findByIdAndUpdate(req.params.id, { $set: req.body }, { new: true }); + if (!updated) { + return res.status(404).json({ error: "product not found" }); + } + res.status(200).json(updated); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } + } +) + + +//delete +router.delete("/del/:id",verifyToken,async (req,res)=>{ + try{ + await cart.findByIdAndDelete(req.params.id) + res.status(200).json("product has been deleted") + } + catch(err){ + res.status(500).json(err) + }} +) + +//get products + +router.get("/find/:id",async(req,res)=>{ + try{ + console.log(req.params.id) + const a=await cart.findOne({userId:req.params.id}) + console.log(a) + if(!a){ + res.status(405).json("Not found") + } + console.log(a._doc) + const { password, ...others } = a._doc; + res.status(200).json({others}); + } + catch(err){ + res.status(500).json("sorry again") + } +}) + +//get all prod + +router.get("/",verifynadmin,async(req,res)=>{ + try{ + + const cart=await cart.find() + res.statusMessage(200).json(cart) + + }catch(err){ + res.status(500).json(err) + } + +}) + + +module.exports=router; \ No newline at end of file diff --git a/New_APIs/Ecom/routes/ord.js b/New_APIs/Ecom/routes/ord.js new file mode 100644 index 0000000..20febe1 --- /dev/null +++ b/New_APIs/Ecom/routes/ord.js @@ -0,0 +1,109 @@ +const router=require('express').Router(); +const order = require('../models/cart'); +const { verifyToken, verifynauth, verifynadmin } = require('./verifytoken'); + +//create + +router.post("/add",verifyToken,async (req,res)=>{ + const newo=new order(req.body) + try{ + const saved=await newo.save(); + res.status(200).json(saved) + }catch(err){ + res.status(500).json(err); + } +}) + +//updates + +router.put("/upd/:id",verifynadmin,async (req,res)=>{ + try { + const updated = await order.findByIdAndUpdate(req.params.id, { $set: req.body }, { new: true }); + if (!updated) { + return res.status(404).json({ error: "product not found" }); + } + res.status(200).json(updated); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } + } +) + + +//delete +router.delete("/del/:id",verifynadmin,async (req,res)=>{ + try{ + await order.findByIdAndDelete(req.params.id) + res.status(200).json("product has been deleted") + } + catch(err){ + res.status(500).json(err) + }} +) + +//get products + +router.get("/find/:id",async(req,res)=>{ + try{ + console.log(req.params.id) + const a=await order.findOne({userId:req.params.id}) + console.log(a) + if(!a){ + res.status(405).json("Not found") + } + console.log(a._doc) + const { password, ...others } = a._doc; + res.status(200).json({others}); + } + catch(err){ + res.status(500).json("sorry again") + } +}) + +//get all prod + +router.get("/",verifynadmin,async(req,res)=>{ + try{ + + const orders=await order.find() + res.statusMessage(200).json(orders) + + }catch(err){ + res.status(500).json(err) + } + +}) + +//get monthly income + +router.get("/income",verifynadmin,async (req,res)=>{ + const date = new Date(); + const lastMonth = new Date(date.setMonth(date.getMonth() - 1)); + const prevMonth = new Date(new Date().setMonth(lastMonth.getMonth() - 1)); + + try { + const income = await order.aggregate([ + { $match: { createdAt: { $gte: prevMonth, $lt: lastMonth } } }, + { + $project: { + month: { $month: "$createdAt" }, + sales: "$amount" + } + }, + { + $group: { + _id: null, + totalSales: { $sum: "$sales" } + } + } + ]); + + res.status(200).json(income); + } catch (err) { + res.status(500).json(err); + } +}) + + +module.exports=router; \ No newline at end of file diff --git a/New_APIs/Ecom/routes/prod.js b/New_APIs/Ecom/routes/prod.js new file mode 100644 index 0000000..49fab4a --- /dev/null +++ b/New_APIs/Ecom/routes/prod.js @@ -0,0 +1,92 @@ +const router=require('express').Router(); +const product = require('../models/product'); +const { verifyToken, verifynauth, verifynadmin } = require('./verifytoken'); + +//create +router.post("/add",verifynadmin,async (req,res)=>{ + const newp=new product(req.body) + try{ + const saved=await newp.save(); + res.status(200).json(saved) + }catch(err){ + res.status(500).json(err); + } +}) + +//updates +router.put("/upd/:id",verifynadmin,async (req,res)=>{ + try { + const updated = await product.findByIdAndUpdate(req.params.id, { $set: req.body }, { new: true }); + if (!updated) { + return res.status(404).json({ error: "product not found" }); + } + res.status(200).json(updated); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } + } +) + + +//delete +router.delete("/del/:id",verifynadmin,async (req,res)=>{ + try{ + await product.findByIdAndDelete(req.params.id) + res.status(200).json("product has been deleted") + } + catch(err){ + res.status(500).json(err) + }} +) + +//get products + +router.get("/find/:id",async(req,res)=>{ + try{ + console.log(req.params.id) + const a=await product.findById(req.params.id) + console.log(a) + if(!a){ + res.status(405).json("Not found") + } + console.log(a._doc) + const { password, ...others } = a._doc; + res.status(200).json({others}); + } + catch(err){ + res.status(500).json("sorry again") + } +}) + +//get all products + +router.get("/",async(req,res)=>{ + const querynew=req.query.new + const querycat=req.query.category + try{ + let prod; + if(querynew){ + prod=await product.find().sort({createdAt:-1}).limit(5) + }else if(querycat){ + prod=await product.find({ + categories:{ + $in:[querycat] + } + }) + } + else{ + prod=await product.find(); + } + if(!prod){ + res.status(405).json("Not found") + } + res.status(200).json(prod); + } + catch(err){ + res.status(500).json("sorry again") + } +}) + + +module.exports=router; \ No newline at end of file diff --git a/New_APIs/Ecom/routes/user.js b/New_APIs/Ecom/routes/user.js new file mode 100644 index 0000000..6a3216e --- /dev/null +++ b/New_APIs/Ecom/routes/user.js @@ -0,0 +1,100 @@ +const router=require('express').Router(); +const user = require('../models/user'); +const auth=require('./auth'); +const { verifyToken, verifynauth, verifynadmin } = require('./verifytoken'); + +router.put("/:id",verifynauth,async (req,res)=>{ + if(req.body.password){ + req.body.password=crypto.AES.encrypt(req.body.password,process.env.secretphrase).toString() + } + try { + const updated = await user.findByIdAndUpdate(req.params.id, { $set: req.body }, { new: true }); + if (!updated) { + return res.status(404).json({ error: "User not found" }); + } + res.status(200).json(updated); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } + } +) + +//delete + +router.delete("/:id",verifynauth,async(req,res)=>{ + try{ + await user.findByIdAndDelete(req.params.id) + res.status(200).json("user has been deleted") + } + catch(err){ + res.status(500).json(err) + } +}) + +//get + +router.get("/find/:id",verifynadmin,async(req,res)=>{ + try{ + console.log(req.params.id) + const a=await user.findById(req.params.id) + console.log(a) + if(!a){ + res.status(405).json("Not found") + } + console.log(user._doc) + const { password, ...others } = a._doc; + res.status(200).json({others}); + } + catch(err){ + res.status(500).json("sorry again") + } +}) + +//get all users + +router.get("/",verifynadmin,async(req,res)=>{ + const query=req.query.new + try{ + console.log(req.params.id) + const a=query ? await user.find().sort({_id:-1}).limit(5) :await user.find(); + console.log(a) + if(!a){ + res.status(405).json("Not found") + } + res.status(200).json(a); + } + catch(err){ + res.status(500).json("sorry again") + } +}) + +//get user stats + +router.get("/stats",verifynadmin,async (req,res)=>{ + const date=new Date(); + const lyear=new Date(date.setFullYear(date.getFullYear()-1)) //last year today + try{ + const data=await user.aggregate([ + {$match:{createdAt:{$gte: lyear}}}, + { + $project:{ + month:{ + $month:{$toDate:"$createdAt"} + } + } + }, + { + $group:{ + _id:"$month", + total:{$sum:1}, + } + } + ]) + res.status(200).json(data); + }catch(err){ + res.status(500).json(err) + } +}) + +module.exports=router; \ No newline at end of file diff --git a/New_APIs/Ecom/routes/verifytoken.js b/New_APIs/Ecom/routes/verifytoken.js new file mode 100644 index 0000000..facf964 --- /dev/null +++ b/New_APIs/Ecom/routes/verifytoken.js @@ -0,0 +1,44 @@ +const jwt=require('jsonwebtoken') + + +const verifyToken=(req,res,next)=>{ + const authhead=req.headers.token + if(authhead){ + const token=authhead; + console.log(token) + jwt.verify(token,process.env.jwtsecret,(err,user)=>{ + if(err) res.status(403).json("Token is not valid!"); + req.user=user + next(); + }) + } + else{ + res.status(401).json("You have not authenticated") + } +} + +const verifynauth=(req,res,next)=>{ + verifyToken(req,res,()=>{ + if(req.user.id===req.params.id || req.user.isAdmin){ + next(); + } + else{ + res.status(403).json("You are not allowed to do that!") + } + }) +} + +const verifynadmin=(req,res,next)=>{ + verifyToken(req,res,()=>{ + if(req.user.isAdmin){ + console.log(req.user) + next(); + } + else{ + res.status(403).json("You are not allowed to do that!") + } + }) +} + + +module.exports={verifyToken,verifynauth,verifynadmin} \ No newline at end of file From f56e525e08969f11cf0f4f8b7f5bf52e07703731 Mon Sep 17 00:00:00 2001 From: sujal Date: Sat, 18 May 2024 14:21:18 +0530 Subject: [PATCH 2/2] Improved readme --- New_APIs/Ecom/Readme.md | 151 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/New_APIs/Ecom/Readme.md b/New_APIs/Ecom/Readme.md index 3784bc7..fba790d 100644 --- a/New_APIs/Ecom/Readme.md +++ b/New_APIs/Ecom/Readme.md @@ -21,8 +21,155 @@ npm installed ### Create a .env file in the root directory and add your environment variables: - PORT=Your_Desired_Port MONGO_URL=your_mongodb_connection_string JWT_SECRET=your_jwt_secret - SECRET_PHRASE=your_secret_phrase \ No newline at end of file + SECRET_PHRASE=your_secret_phrase + +### API ENDPOINTS + +**Authentication** +- Register + Endpoint: /api/auth/register + Method: POST + Description: Register a new user. + Body: + { + "username": "exampleuser", + "email": "user@example.com", + "password": "password" + } + +- Login + Endpoint: /api/auth/login + Method: POST + Description: Login a user. + Body: + { + "username": "exampleuser", + "password": "password" + } + +**User Management** + +- Update User + Endpoint: /api/user/:id + Method: PUT + Description: Update a user's information. + Authorization: Requires token verification. + +- Delete User + Endpoint: /api/user/:id + Method: DELETE + Description: Delete a user. + Authorization: Requires token verification. + +- Get User + Endpoint: /api/user/find/:id + Method: GET + Description: Get a user's information. + Authorization: Requires admin verification. + +- Get All Users + Endpoint: /api/user + Method: GET + Description: Get all users. + Authorization: Requires admin verification. + +**Product Management** + +- Add Product + Endpoint: /api/prod/add + Method: POST + Description: Add a new product. + Authorization: Requires admin verification. + +- Update Product + Endpoint: /api/prod/upd/:id + Method: PUT + Description: Update a product. + Authorization: Requires admin verification. + +- Delete Product + Endpoint: /api/prod/del/:id + Method: DELETE + Description: Delete a product. + Authorization: Requires admin verification. + +- Get Product + Endpoint: /api/prod/find/:id + Method: GET + Description: Get a product by ID. + +- Get All Products + Endpoint: /api/prod + Method: GET + Description: Get all products, with optional filtering by new or category. + +**Cart Management** + +- Add to Cart + Endpoint: /api/car/add + Method: POST + Description: Add a new item to the cart. + Authorization: Requires token verification. + +- Update Cart + Endpoint: /api/car/upd/:id + Method: PUT + Description: Update a cart item. + Authorization: Requires token verification. + +- Delete Cart Item + Endpoint: /api/car/del/:id + Method: DELETE + Description: Delete a cart item. + Authorization: Requires token verification. + +- Get Cart + Endpoint: /api/car/find/:id + Method: GET + Description: Get cart items for a user. + +- Get All Carts + Endpoint: /api/car + Method: GET + Description: Get all cart items. + Authorization: Requires admin verification. + +**Order Management** + +- Add Order + Endpoint: /api/ord/add + Method: POST + Description: Add a new order. + Authorization: Requires token verification. + +- Update Order + Endpoint: /api/ord/upd/:id + Method: PUT + Description: Update an order. + Authorization: Requires admin verification. + +- Delete Order + Endpoint: /api/ord/del/:id + Method: DELETE + Description: Delete an order. + Authorization: Requires admin verification. + +- Get Order + Endpoint: /api/ord/find/:id + Method: GET + Description: Get an order by user ID. + +- Get All Orders + Endpoint: /api/ord + Method: GET + Description: Get all orders. + Authorization: Requires admin verification. + +- Get Monthly Income + Endpoint: /api/ord/income + Method: GET + Description: Get monthly income. + Authorization: Requires admin verification. \ No newline at end of file