E-Commerce API Heroku URL
Setup Basic Express Server
[] import express and assign to variable
[] setup start port variable (5000) and start function
[] get connection string
[] setup .env with MONGO_URL variable and assign the value
[] import 'dotenv' and setup package
[] import connect() and invoke in the starter
[] restart the server
[] mongoose V6 info
Basic Routes and Middleware
[] setup / GET Route
[] setup express.json() middleware
[] setup 404 and errorHandler middleware
[] import 'exress-async-errors' package
404 vs ErrorHandler Middleware
[] create models folder and User.js file
[] create schema with name,email, password (all type:String)
[] export mongoose model
[] create controllers folder
[] add authController file
[] export (register,login,logout) functions
[] res.send('some string value')
[] create routes folder
[] setup authRoutes file
[] import all controllers
[] setup three routes
[] post('/register') post('/login') get('/logout')
[] import authRoutes as authRouter in the app.js
[] setup app.use('/api/v1/auth', authRouter)
[] create user
[] send response with entire user (only while testing)
[] check if email already in use (schema and controller)
[] ignore 'role'
[] alternative 'admin' setup
[] UserSchema.pre('save') - hook
this points to User
bcrypt.genSalt - number of rounds
bcrypt.hash
[] require 'jsonwebtoken' package
[] create jwt - jwt.sign(payload,secret,options)
[] verify jwt - jwt.verify(token,secret)
[] add variables in .env JWT_SECRET=jwtSecret and JWT_LIFETIME=1d
[] restart the server !!!!
[] refactor code, create jwt functions in utils
[] refactor cookie code
[] setup func attachCookiesToResponse
[] accept payload(res, tokenUser)
[] create token, setup cookie
[] optionally send back the response
[] check if email and password exist, if one missing return 400
[] find user, if no user return 401
[] check password, if does not match return 401
[] if everything is correct, attach cookie
and send back the same response as in register
[] set token cookie equal to some string value
[] set expires:new Date(Date.now())
[] add userController file
[] export (getAllUsers,getSingleUser,showCurrentUser,updateUser,updateUserPassword) functions
[] res.send('some string value')
[] setup userRoutes file
[] import all controllers
[] setup just one route - router.route('/').get(getAllUsers);
[] import userRoutes as userRouter in the app.js
[] setup app.use('/api/v1/users', userRouter)
GetAllUsers and GetSingleUser
[] Get all users where role is 'user' and remove password
[] Get Single User where id matches id param and remove password
[] If no user 404
Authorize Permissions Setup
Authorize Permissions Complete
[] get user from req
[] send response with user
[] almost identical to login user
[] add authenticateUser middleware in the route
[] check for oldPassword and newPassword in the body
[] if one missing 400
[] look for user with req.user.userId
[] check if oldPassword matches with user.comparePassword
[] if no match 401
[] if everything good set user.password equal to newPassword
[] await user.save()
[] create a file in utils (createTokenUser)
[] setup a function that accepts user object and returns userToken object
[] export as default
[] setup all the correct imports/exports and refactor existing code
updateUser with User.findOneAndUpdate()
[] add authenticateUser middleware in the route
[] check for name and email in the body
[] if one is missing, send 400 (optional)
[] use findOneAndUpdate()
[] create token user, attachCookiesToResponse and send back the tokenUser
updateUser with user.save()
Setup and Apply checkPermissions()
[] create Product.js in models folder
[] create Schema
[] name : {type:String}
[] price: {type:Number}
[] description: {type:String}
[] image: {type:String}
[] category: {type:String}
[] company: {type:String}
[] colors: {type:[]}
[] featured: {type:Boolean}
[] freeShipping: {type:Boolean}
[] inventory:{type:Number}
[] averageRating:{type:Number}
[] user
[] set timestamps
[] export Product model
[] add productController file in controllers
[] export (createProduct, getAllProducts,
getSingleProduct, updateProduct, deleteProduct, uploadImage) functions
[] res.send('function name')
[] setup productRoutes file in routes
[] import all controllers
[] only getAllProducts and getSingleProduct accessible to public
[] rest only by admin (setup middlewares)
[] typical setup
[] router.route('/uploadImage').post(uploadImage)
[] import productRoutes as productRouter in the app.js
[] setup app.use('/api/v1/products', productRouter)
Product Routes in Postman
[] create user property on req.body and set it equal to userId (req.user)
[] pass req.body into Product.create
[] send back the product
Remaining Controllers (apart from uploadImage)
[] getAllProducts
[] getSingleProduct
[] updateProduct
[] deleteProduct
[] typical CRUD, utilize (task or job) project
[] remember we check already for role 'admin'
[] if some question, re-watch 07-file-upload
[] images folder with two images
[] create Review.js in models folder
[] create Schema
[] rating : {type:Number}
[] title: {type:String}
[] comment: {type:String}
[] user
[] product
[] set timestamps
[] export Review model
[] add reviewController file in controllers
[] export (createReview, getAllReviews, getSingleReview, updateReview, deleteReview) functions
[] res.send('function name')
[] setup reviewRoutes file in routes
[] import all controllers
[] only getAllReviews and getSingleReview accessible to public
[] rest only to users (setup middleware)
[] typical REST setup
[] import reviewRoutes as reviewRouter in the app.js
[] setup app.use('/api/v1/reviews', reviewRouter)
[] check for product in the req.body
[] attach user property (set it equal to req.user.userId) on to req.body
[] create review
[] don't test yet
Get All Reviews and Get Single Review
[] both public routes, typical setup
[] get id from req.params
[] check if review exists
[] if no review, 404
[] check permissions (req.user, review.user)
[] use await review.remove()
[] send back 200
[] get id from req.params
[] get {rating, title comment} from req.body
[] check if review exists
[] if no review, 404
[] check permissions
[] set review properties equal to rating, title, comment
[] use await review.save()
[] send back 200
Get Single Product Reviews
Aggregation Pipeline - Atlas and Code
[] create Order.js in models folder
[] create Schema
[] tax : {type:Number}
[] shippingFee: {type:Number}
[] subtotal: {type:Number}
[] total: {type:Number}
[] orderItems:[]
[] status:{type:String}
[] user
[] clientSecret:{type:String}
[] paymentId:{type:String}
[] set timestamps
[] export Order model
[] add orderController file in controllers
[] export (getAllOrders, getSingleOrder, getCurrentUserOrders,
createOrder, updateOrder) functions
[] res.send('function name')
[] setup orderRoutes file in routes
[] import all controllers
[] authenticate user in all routes
[] getAllOrders admin only
[] typical REST setup
[] router.route('/showAllMyOrders').get(getCurrentUserOrders)
[] import orderRoutes as orderRouter in the app.js
[] setup app.use('/api/v1/orders', orderRouter)
Get All Orders and Get Single Order
[] getAllOrders - admin only
[] getSingleOrder - chechPermissions
[] find orders where user is equal to req.user.userId
[] get order id
[] get paymentIntentId (req.body)
[] get order
[] if does not exist - 404
[] check permissions
[] set paymentIntentId and status as 'paid'
[] order.save()
[] express-rate-limiter
[] helmet
[] xss-clean
[] express-mongo-sanitize
[] cors (cookies!!!!)
[] heroku account and heroku cli
[] remove/copy from the main repo
[] add dev command "nodemon app.js"
[] change start to "node app.js"
[] setup node version in package.json
[] "engines": {"node": "14.x"}
[] Procfile "web: node app.js"
[] remove existing git repo
[] rm -rf .git - mac,
[] git init
[] git add .
[] git commit -m "initial commit"
[] heroku login
[] heroku create "App Name"
[] git remote -v
[] setup env vars in GUI
[] git push heroku master/main