Skip to main content

Register new User, Login User, Delete user, Update User Profile , Forgot/Reset password, Change Password - Node Js , MERN Stack Post 101



Project Folder Architecture will look like this (Setup your Node JS in folder)


========install required package using command - npm install packegeName  for example 
    npm install express 
npm install jsonwebtoken 
npm install bcryptjs  etc. etc.

==================================================================

First create a file  config.env  inwhich we will set various variable with info  

PORT=4000

Database_url = "mongodb://localhost:27017/E-com"

JWT_SECRET = KILVISHKJDKFJKDFJKDKDFKJDSKFSDFKJ  

JWT_EXPIRE = 5d

COOKIE_EXPIRE = 5

SMTP_SERVICE = "gmail"

SMTP_MAIL = 'vasubirla@gmail.com'

SMTP_PASSWORD = 'mtvrqzmxlaroeizh'
//create your own app pass from your google security setting, this is wrong pass

First create Server -  Server.js 
const app = require('./app');
const dotenv = require('dotenv');
const connectDatabase = require('./config/database')

//Uncaught Exception Handling
process.on("uncaughtException",err=>{

    console.log(`error:${err.message}`);
    console.log( `Shutting Down the server due to Uncaught Exception`);
    server.close(()=>{
        process.exit(1)
    })
})


//env File added
dotenv.config({path:"backend/config/config.env"});

//added Database
connectDatabase();


const server=  app.listen(process.env.PORT,()=>{
    console.log(" Server Started at port"+process.env.PORT);
})


//unhandled Promis rejection
process.on("unhandledRejection",err=>{

    console.log(`error:${err.message}`);
    console.log("Shutting Down the server due to unhandled Promise Rejection");

    server.close(()=>{
        process.exit(1)
    })
})




//app.js 
const express = require('express');
const app = express ();

const cookieParser = require('cookie-parser');

const errorMiddleware = require('./middleware/error.js');

const user = require('./routes/userRoute');

//============= middleware section start  ======
app.use(express.json());
app.use(cookieParser());

app.use('/api/v1',user);
app.use('/api/v1',order)

app.use(errorMiddleware); //middleware for error handling


//============= middleware section end ===========
module.exports = app




//Create utils folder and inside it create following supporting files - 
1. errorhander.js - this file is for handling error once so that we dont have  to write error code again and again . 
2. jwttoken.js - this file is to generate unique Token to user and save user info into cookies for authentication for different services like login , change pass, create order , delete Profile - 
without JWT token - it cant not be done -  
3. sendEmail.js -  This file is for sending verification link or reset password link to user's email - 

=========== 1. /utilsfolder/errorhander.js ======================== 
//errorhander.js
class ErrorHander extends Error{

    constructor(message,statusCode){

        super(message)
        this.statuscode = statusCode

        Error.captureStackTrace(this,this.constructor)
    }
}

module.exports = ErrorHander

=================2. /utils/jwtToken.js file ==================== 
// Creating Token and saving in Cookie - jwtToken.js
const sendToken = (user, statusCode, res)=>{

    const token = user.getJWTToken();

    //options for tokens  
        const options = {
            expires: new Date(
                Date.now() + process.env.COOKIE_EXPIRE*24*60*60*1000
            ),
            httpOnly:true
        }

        res.status(statusCode).cookie('token',token,options).json({

            success: true,
            user,
            token
        })
}

module.exports = sendToken


==============3. /utils/sendEmail.js  file ==================   

const nodemailer = require('nodemailer');

const sendEmail = async (options)=>{
     
      process.env.NODE_TLS_REJECT_UNAUTHORIZED='0'

    const transporter = nodemailer.createTransport({
        service: process.env.SMTP_SERVICE,
        auth: {
          user: process.env.SMTP_MAIL,
          pass: process.env.SMTP_PASSWORD
        }
      });


      const mailOptions = {
        from: process.env.SMTP_MAIL,
        to: options.email,
        subject: options.subject,
        html: options.message,
     
      }

      await transporter.sendMail(mailOptions)

}

module.exports = sendEmail



//  Create User Model.js 

//UserModel.js
const mongoose = require('mongoose');
const validator = require('validator');
const { default: isEmail } = require('validator/lib/isemail');
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken');
const crypto = require('crypto')

const userSchema = new mongoose.Schema({

    name: {
        type:String,
        required:[true,"please enter Your name"],
        trim:true
    },
    email: {
        type:String,
        required:[true,"Email is Required"],
        unique:true,
        validate:[validator.isEmail,"Please Enter Valid Email"] ,
        trim:true
    },
    password: {
        type:String,
        required:[true,"please enter Your name"],
        minLength:[6,"Password should be greater than 8 char"],
        select:false
    },
    avatar:{
            public_id:{
                type:String,
                required:true
            },
            url:{
                type:String,
                required:true
            }
        },
    role:{
        type:String,
        default:"user"
    },
    resetPasswordToken:String,
    resetPasswordExpire:Date
})


// convert plain password into hash before(pre) saving user
userSchema.pre("save",async function(next){
    //don't hash on update already existing User
    if(!this.isModified("password")){
        next()
    }
    this.password = await bcrypt.hash(this.password,10)

})

//JWN Token - Generate jwt and store in cookie storage

userSchema.methods.getJWTToken = function(){
        //first parameter is Payload unique ID , second is Secret Key, third is token expire time
    return jwt.sign({id:this._id},process.env.JWT_SECRET,{
        expiresIn: process.env.JWT_EXPIRE
    })
}

//compare Password

userSchema.methods.comparePassword = async function(enteredPassword){

    return await bcrypt.compare(enteredPassword,this.password)

}


// create Token to reset Password

userSchema.methods.getResetPasswordToken = function(){

    const resetToken = crypto.randomBytes(20).toString('hex');

    //hashing and adding to userSchema

    this.resetPasswordToken = crypto.createHash("sha256").update(resetToken).digest("hex");

    this.resetPasswordExpire = Date.now() + 15 * 60 * 1000 ;

    return resetToken;
}



module.exports = mongoose.model("User",userSchema)



//======= create user controller--- UserController.js is below============

const ErrorHander = require('../utils/errorhander');
const catchAsyncError = require('../middleware/catchAsyncError');
const User = require('../models/userModel.js');
const sendToken = require('../utils/jwtToken');
const sendEmail = require('../utils/sendEmail.js')

const crypto = require('crypto');
const { access } = require('fs');


//Register a new User

exports.registerUser = catchAsyncError(async(req,res,next)=>{

    const{name,email,password} = req.body
    const user = await User.create({
        name,email,password,
        avatar:{
            public_id:"this is temp id",
            url:"profilepicsample url",
        }
    })

    sendToken(user,200,res)
})
//===== after creating each module import and use it in UserRoute.js
then test it on postman (refer following Image of testing register API)



//Login user

exports.loginUser = catchAsyncError(async(req,res,next)=>{

        const {email,password} = req.body;

        //if user don't enter email password
        if(!email || !password){
            next(new ErrorHander("Please Enter Email and Password",400))
        }

         const user =await User.findOne({email}).select("+password") ; // select because we set false in UserModel Password selection

        if(!user){
            next(new ErrorHander("Invalid Email & Password",401))
        }

        const isPasswordMatched = await user.comparePassword(password);

        if(!isPasswordMatched){
            next(new ErrorHander("Invalid Password",401))
        }

        else{
           sendToken(user,200,res)
        }
     

})
// Testing Login API =



//Logout User

exports.logoutUser= catchAsyncError(async(req,res,next)=>{

        res.cookie("token",null,{
            expires : new Date(Date.now()),
            httpOnly:true
        })

        res.status(200).json({
            success:true,
            message:"Logged Out!"
        })
})

// Testing Logout User API



//forgot Password

exports.forgotPassword = catchAsyncError(async(req,res,next)=>{

    const user = await User.findOne({email:req.body.email});

        if(!user){

           return next( new ErrorHander("Account Does not exists !! please Enter Valid Email",404))

        }
        // get resetToken Password

       const resetToken =  user.getResetPasswordToken();
       
       await user.save({validateBeforeSave:false});

       //creating link to send user to reset password
       
       const resetPasswordUrl = `${req.protocol}://${req.host}/api/v1/password/reset/${resetToken}`

       const message = `Your Reset Password Link is :- \n \n ${resetPasswordUrl} \n\n If you have not requested it then ignore`

   
    try {

        await sendEmail({

            email:user.email,
            subject: `Kilvish.com Password Recovery `,
            message

        })

        res.status(200).json({
            success:true ,
            message: `email sent to ${user.email} successfully !`
        })
       
    } catch (error) {
        user.resetPasswordToken = undefined ;
        user.resetPasswordExpire = undefined;

        await user.save({validateBeforeSave:false});

        return next(new ErrorHander(error.message))
    }


})

//Forgot Password API - sent link to email




//reset password after sending link

exports.resetPassword = catchAsyncError(async (req,res,next)=>{

    const resetPasswordToken = crypto.createHash("sha256").update(req.params.token).digest("hex");

        const user = await User.findOne({ resetPasswordToken, resetPasswordExpire:{$gt : Date.now()}})

        if(!user){
            return next(new ErrorHander("Reset Link is Invalid or Expired Please Request Again",400));
        }

        if(req.body.password !== req.body.confirmPassword){
            return next(new ErrorHander("Password Mismached !",400));
        }

    user.password = req.body.password;

    user.resetPasswordToken = undefined ;
    user.resetPasswordExpire = undefined;

    await user.save()

    sendToken(user,200,res);

})
//After Receiving Link on Email - reset testing is below but here link is expire



//View User Details - by user

  exports.getUserDetails =  catchAsyncError(async (req,res,next)=>{

    const user = await User.findById(req.user.id)

        res.status(200).json({
            success:true,
            user
        })
  })

//Tesing view User Details -by user




  //Change/Update Password  

  exports.updatePassword = catchAsyncError(async (req,res,next)=>{

    const user =await User.findById(req.user.id).select("+password") ;

    const isPasswordMatched = await user.comparePassword(req.body.oldPassword);

    if(!isPasswordMatched){
        next(new ErrorHander("Invalid OldPassword",401))
    }

    if(req.body.newPassword !== req.body.confirmPassword){
        return next(new ErrorHander("Password Mismached !",400));
    }


    user.password = req.body.confirmPassword ;

    await user.save();

    sendToken(user,200,res);


  })

//==========Testing Change Password API ==========






    // Update User profile

    exports.updateProfile = catchAsyncError(async (req,res,next)=>{

         const newUserData= {
            nameL: req.body.name,
            email:req.body.email,
         }
         console.log(req.user.id);
         console.log(newUserData);

         const user = await User.findByIdAndUpdate(req.user.id, newUserData,{
            new:true,
            runValidators :true,
            useFindandModify:false
         })

         console.log(user)
        res.status(200).json({
            success:true,
            user
        })
   
   
      })
//get all users (admin)

exports.getAllUser = catchAsyncError(async (req,res,next)=>{

        const users = await User.find();

        res.status(200).json({
            success:true,
            users
        })
})

//get Single User (admin)

exports.getSingleUser = catchAsyncError(async (req,res,next)=>{

    const user = await User.findById(req.params.id)


        if(!user){
            return next(new ErrorHander("User Not Found ! ",400))
        }
        else {
            res.status(200).json({
                success:true,
                user
            })
        }
           
       
   
})

//Get Single user - admin Testing - but here user is login



 // Update User's Role - Admin
 exports.updateUserRole = catchAsyncError(async (req,res,next)=>{

    const newUserData= {
       email:req.body.email,
       role: req.body.role
    }
    console.log(req.user.id);
    console.log(newUserData);

    const user = await User.findByIdAndUpdate(req.params.id, newUserData,{
       new:true,
       runValidators :true,
       useFindandModify:false
    })

    console.log(user)
   res.status(200).json({
       success:true,
       user
   })


 })

//=========Testing APi - Update user's role to admin ----



  // Delete User - Admin

  exports.deleteUser = catchAsyncError(async (req,res,next)=>{

   
    const user = await User.findById(req.params.id)

    if(!user){
        return next( new ErrorHander("User not found",400))
    }
   
    user.remove();

    console.log(user)
   res.status(200).json({
       success:true,
       message:"User Deleted Successfully !!"
   })


 })

===========Tesing Api - Delete user - Only Admin can do this -





============Create user router == UserRoute.js  is below  ====================

const express = require("express");
const { registerUser,
     loginUser,
     logoutUser,
     forgotPassword,
    resetPassword,
     getUserDetails,
    updatePassword,
     updateProfile,
      getAllUser,
      getSingleUser,
      updateUserRole,
      deleteUser
     } = require("../controllers/userController");
const router = express.Router();

const { isAuthenticatedUser, authorizeRoles } = require('../middleware/auth.js');

router.route("/register").post(registerUser)

router.route("/login").post(loginUser)

router.route("/password/forgot").post(forgotPassword)

router.route("/password/reset/:token").put(resetPassword)

router.route('/logout').get(logoutUser)

router.route('/me').get(isAuthenticatedUser ,getUserDetails)

router.route('/password/update').put(isAuthenticatedUser, updatePassword)

router.route('/me/update').put(isAuthenticatedUser, updateProfile)

router.route('/admin/users').get(isAuthenticatedUser,authorizeRoles("admin"),getAllUser)

router.route('/admin/user/:id').get(isAuthenticatedUser,authorizeRoles("admin"), getSingleUser)

router.route('/admin/user/:id').put(isAuthenticatedUser,authorizeRoles("admin"), updateUserRole)

router.route('/admin/user/:id').delete(isAuthenticatedUser,authorizeRoles("admin"), deleteUser)



module.exports = router;







==================End===============

Comments

Popular posts from this blog

Part 15- What is Repeater (Networking Devices)- Computer Networking- CCNA

Repeater  hello friends i am Vasu Birla and today i am starting new segment of CCNA computer networking  its a Networking Devices. we will discuss every important Devices used in networks. Repeater is a first networking devices. What is Repeater  Repeater is a device that receives signals and re-transmits by amplifying or regenerating signals. Repeater has two port one is for receive signals from previous network and second port is for retransmit signals to the next extended network. Two Port Repeater Repeater is a device which is used to Regenerate or replicate signal (Pichhe se aa rahe signal ko regenerate karke ya amplify karke aage strong signals bhej sakte he) Analog and digital both type of signals can be retransmitted by repeater. Here there is difference between regeneration and amplifying.  Amplification means , received signals will be amplified as it is , whether there are impurities in signals  and Regeneration means repeate...

How to Kill the Process: ( Port Process )

If you are seeing a Error like  -   Error: listen EADDRINUSE: address already in use :::3000   then you can easily kill it by running these commands  Find the Process Using Port 3006 : On Windows   netstat -ano | findstr :3000 On Linux/macOS lsof -i :3000       Terminate the Process :       On Windows taskkill /PID <PID> /F    means       taskkill /PID 17780 /F On Linux/macOS kill -9 <PID>     means kill -9 17780                ==============END ==========  

Part 19- Router (Networking Devices)- Computer Networking- CCNA

Hello friends...i am Vasu Birla and today will discuss about the most important Networking Device ..Router.  so let's start... ROUTER Router is a device which connect two or more networks together, which is why router is also known is Inter-networking device also. Inter-networking means two or more networks are connected together with the help of router. one more thing router is just like a computer  but it is designed for routing only, our computer can be router also but that are software router while hardware router which are specialize for routing is more efficient and fast than software router.  There is a Operating System installed on router which get moves data from one network to another network with the help of routing table.  Router does work on Network layer or Layer 3 of the OSI model.  Cisco Router There many companies which manufacture Router but main companies are - Cisco , Juniper , HP, 3com and Nortel  ...