├── .gitignore ├── package.json └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bistro-boss-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cors": "^2.8.5", 14 | "dotenv": "^16.0.3", 15 | "express": "^4.18.2", 16 | "jsonwebtoken": "^9.0.0", 17 | "mongodb": "^5.5.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const cors = require('cors'); 4 | const jwt = require('jsonwebtoken'); 5 | require('dotenv').config() 6 | const port = process.env.PORT || 5000; 7 | 8 | // middleware 9 | app.use(cors()); 10 | app.use(express.json()); 11 | 12 | const verifyJWT = (req, res, next) => { 13 | const authorization = req.headers.authorization; 14 | if (!authorization) { 15 | return res.status(401).send({ error: true, message: 'unauthorized access' }); 16 | } 17 | // bearer token 18 | const token = authorization.split(' ')[1]; 19 | 20 | jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, decoded) => { 21 | if (err) { 22 | return res.status(401).send({ error: true, message: 'unauthorized access' }) 23 | } 24 | req.decoded = decoded; 25 | next(); 26 | }) 27 | } 28 | 29 | 30 | const { MongoClient, ServerApiVersion, ObjectId } = require('mongodb'); 31 | const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}@cluster0.swu9d.mongodb.net/?retryWrites=true&w=majority`; 32 | 33 | // Create a MongoClient with a MongoClientOptions object to set the Stable API version 34 | const client = new MongoClient(uri, { 35 | serverApi: { 36 | version: ServerApiVersion.v1, 37 | strict: true, 38 | deprecationErrors: true, 39 | } 40 | }); 41 | 42 | async function run() { 43 | try { 44 | // Connect the client to the server (optional starting in v4.7) 45 | await client.connect(); 46 | 47 | const usersCollection = client.db("bistroDb").collection("users"); 48 | const menuCollection = client.db("bistroDb").collection("menu"); 49 | const reviewCollection = client.db("bistroDb").collection("reviews"); 50 | const cartCollection = client.db("bistroDb").collection("carts"); 51 | 52 | app.post('/jwt', (req, res) => { 53 | const user = req.body; 54 | const token = jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, { expiresIn: '1h' }) 55 | 56 | res.send({ token }) 57 | }) 58 | 59 | // Warning: use verifyJWT before using verifyAdmin 60 | const verifyAdmin = async (req, res, next) => { 61 | const email = req.decoded.email; 62 | const query = { email: email } 63 | const user = await usersCollection.findOne(query); 64 | if (user?.role !== 'admin') { 65 | return res.status(403).send({ error: true, message: 'forbidden message' }); 66 | } 67 | next(); 68 | } 69 | 70 | /** 71 | * 0. do not show secure links to those who should not see the links 72 | * 1. use jwt token: verifyJWT 73 | * 2. use verifyAdmin middleware 74 | */ 75 | 76 | // users related apis 77 | app.get('/users', verifyJWT, verifyAdmin, async (req, res) => { 78 | const result = await usersCollection.find().toArray(); 79 | res.send(result); 80 | }); 81 | 82 | app.post('/users', async (req, res) => { 83 | const user = req.body; 84 | const query = { email: user.email } 85 | const existingUser = await usersCollection.findOne(query); 86 | 87 | if (existingUser) { 88 | return res.send({ message: 'user already exists' }) 89 | } 90 | 91 | const result = await usersCollection.insertOne(user); 92 | res.send(result); 93 | }); 94 | 95 | // security layer: verifyJWT 96 | // email same 97 | // check admin 98 | app.get('/users/admin/:email', verifyJWT, async (req, res) => { 99 | const email = req.params.email; 100 | 101 | if (req.decoded.email !== email) { 102 | res.send({ admin: false }) 103 | } 104 | 105 | const query = { email: email } 106 | const user = await usersCollection.findOne(query); 107 | const result = { admin: user?.role === 'admin' } 108 | res.send(result); 109 | }) 110 | 111 | app.patch('/users/admin/:id', async (req, res) => { 112 | const id = req.params.id; 113 | console.log(id); 114 | const filter = { _id: new ObjectId(id) }; 115 | const updateDoc = { 116 | $set: { 117 | role: 'admin' 118 | }, 119 | }; 120 | 121 | const result = await usersCollection.updateOne(filter, updateDoc); 122 | res.send(result); 123 | 124 | }) 125 | 126 | 127 | // menu related apis 128 | app.get('/menu', async (req, res) => { 129 | const result = await menuCollection.find().toArray(); 130 | res.send(result); 131 | }) 132 | 133 | // review related apis 134 | app.get('/reviews', async (req, res) => { 135 | const result = await reviewCollection.find().toArray(); 136 | res.send(result); 137 | }) 138 | 139 | 140 | // cart collection apis 141 | app.get('/carts', verifyJWT, async (req, res) => { 142 | const email = req.query.email; 143 | 144 | if (!email) { 145 | res.send([]); 146 | } 147 | 148 | const decodedEmail = req.decoded.email; 149 | if (email !== decodedEmail) { 150 | return res.status(403).send({ error: true, message: 'porviden access' }) 151 | } 152 | 153 | const query = { email: email }; 154 | const result = await cartCollection.find(query).toArray(); 155 | res.send(result); 156 | }); 157 | 158 | app.post('/carts', async (req, res) => { 159 | const item = req.body; 160 | const result = await cartCollection.insertOne(item); 161 | res.send(result); 162 | }) 163 | 164 | app.delete('/carts/:id', async (req, res) => { 165 | const id = req.params.id; 166 | const query = { _id: new ObjectId(id) }; 167 | const result = await cartCollection.deleteOne(query); 168 | res.send(result); 169 | }) 170 | 171 | // Send a ping to confirm a successful connection 172 | await client.db("admin").command({ ping: 1 }); 173 | console.log("Pinged your deployment. You successfully connected to MongoDB!"); 174 | } finally { 175 | // Ensures that the client will close when you finish/error 176 | // await client.close(); 177 | } 178 | } 179 | run().catch(console.dir); 180 | 181 | 182 | app.get('/', (req, res) => { 183 | res.send('boss is sitting') 184 | }) 185 | 186 | app.listen(port, () => { 187 | console.log(`Bistro boss is sitting on port ${port}`); 188 | }) 189 | 190 | 191 | /** 192 | * -------------------------------- 193 | * NAMING CONVENTION 194 | * -------------------------------- 195 | * users : userCollection 196 | * app.get('/users') 197 | * app.get('/users/:id') 198 | * app.post('/users') 199 | * app.patch('/users/:id') 200 | * app.put('/users/:id') 201 | * app.delete('/users/:id') 202 | */ --------------------------------------------------------------------------------