Backend Development with NodeJs

Hritik Khurana
9 min readJun 17, 2022

Architecture

Architecture of the Project

app.js

const express = require(‘express’);

const port = process.env.PORT || 4000;

const app = express();

const path = require(‘path’);

const passport = require(‘passport’);

const LocalStrategy = require(‘passport-local’);

const bodyparser = require(‘body-parser’);

const User = require(‘./models/user’);

const session = require(‘express-session’)

const mongoose = require(‘mongoose’);

const config = require(‘./config’);

const middleware = require(‘./middleware/index’);

const ejs = require(‘ejs’);

const mailer = require(‘./mailers/comment’);

const upload = require(‘./multer’);

const cookieParser = require(‘cookie-parser’);

const flash = require(‘connect-flash’);

// passportJWT

const jwt = require(‘jsonwebtoken’);

const passportJWT = require(‘./config/passport-jwt-strategy’);

// socket.io setup

const http = require(‘http’);

const socketio = require(‘socket.io’);

const server = http.createServer(app);

const io = socketio(server);

io.on(‘connection’ , socket=>{

// only to the user who signed in

console.log(‘New Connection Setup’);

socket.emit(‘message’ , “Hey Welcome to the CodersHub”)

})

//flash

app.use(cookieParser(“This is my secret!”));

app.use(flash());

// setting the view engine

app.set(‘view engine’ , ‘ejs’);

app.set(‘views’ , path.join(__dirname , “views”));

app.use(‘/uploads’ , express.static(path.join(__dirname , ‘uploads’)));

// to get the data in the request

app.use(bodyparser.urlencoded({

extended:true

}))

//we need express session before we use passport session

app.use(

session({

secret: “Hello, This is secret line”,

resave: false,

saveUninitialized: false,

cookie: {

maxAge: 3600000,

secure: false,

httpOnly: true

}

})

);

//passport setup

app.use(passport.initialize());

// passport will need a session for how much time user needs to be login

// for that we use express session

app.use(passport.session());

passport.use(new LocalStrategy(User.authenticate()));

passport.serializeUser(User.serializeUser());

passport.deserializeUser(User.deserializeUser());

// mongodb setup

mongoose

.connect(config.dbUrl, {

useNewUrlParser: true

})

.then(() => {

console.log(“DataBase Connected Successfully”);

})

.catch(err => console.log(err));

// routes and controllers

app.get(‘/’ , function(req , res){

res.render(‘index’);

})

app.get(‘/home’ ,middleware.isLoggedIn , function(req , res){

res.render(‘home’ , {

success : req.flash(‘success’),

error : req.flash(‘error’)

});

});

app.post(‘/uploadpic’ , upload.single(‘file’) , function(req , res){

req.user.file = req.file.filename;

req.user.save();

res.render(‘home’ , {

success : req.flash(‘success’),

error : req.flash(‘error’)

});

});

//get sign in page

app.get(‘/signin’ , function(req , res){

res.render(‘signin’);

})

app.post(‘/signin’ , function(req , res , next){

// mailer.newComment(“hritikkhurana10sm@gmail.com”);

passport.authenticate(“local” , (err , user , info)=>{

if(err){

return res.redirect(‘/signin’);

}

if(!user){

return res.redirect(‘/signin’);

}

req.login(user , err=>{

if(err){

return res.redirect(‘/signin’);

}

req.flash(‘success’ , ‘Successfully Signed In’);

return res.redirect(‘/home’);

});

})(req , res , next);

});

// get sign up page

app.get(‘/signup’ , function(req , res){

res.render(‘signup’);

})

// sign up data upload

app.post(‘/signup’ , function(req , res){

console.log(‘req data ‘ , req.body);

const user = new User({

username : req.body.username,

email : req.body.email,

password : req.body.password

})

User.register(user , req.body.password , function(err , user){

if(err){

console.log(‘Error while creating user’ , err);

res.json({

success : false,

message : “Your account can not be made”

});

}else{

console.log(‘Users details are as follows : ‘ , user);

req.flash(‘success’ , ‘Successfully Signed Up’);

res.render(‘signin’);

}

});

});

app.get(‘/showusers’ ,middleware.isLoggedIn ,async function(req , res){

const users = await User.find({});

console.log(‘users ‘, users);

res.render(‘showusers’ , {

users : users

})

});

// sign out

app.get(‘/signout’ , function(req , res){

req.logout(function(err) {

if (err) { return next(err); }

// did not work

res.clearCookie(‘connect.sid’, { path: ‘/’ });

res.redirect(‘/’);

});

})

// getting the ‘/update’ page

app.get(‘/update’ , middleware.isLoggedIn , function(req , res){

return res.render(‘update’);

})

// updating the details

app.post(‘/update’ , function(req , res){

req.user.username = req.body.username || req.user.username;

req.user.email = req.body.email || req.user.email;

req.user.file = req.file.filename|| req.user.file;

req.user.save((err , user)=> console.log(‘error in saving the changing ‘ , err));

res.render(‘showusers’);

});

app.get(‘/forget’ , middleware.isLoggedIn, function(req , res){

return res.render(‘forget’);

})

// forward password and reset password

app.post(‘/resetpassword’ , async function(req , res){

if(req.body.password != req.body.confirm_password){

return res.json({

message : “Password not equal to confirm password”

});

}else{

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

await user.setPassword(req.body.password);

req.user.password = req.body.password || req.user.password;

await req.user.save();

const updatedUser = await user.save();

res.json({

message : “Successfully Changed passwor”

})

}

})

// delete the user or delete user

app.get(‘/deleteUser’ , middleware.isLoggedIn , function(req , res){

res.render(‘deleteUser’ , {

user : req.user

});

})

app.get(‘/deleteUser/:id’ , function(req , res ,next){

let id = req.params.id;

const user = User.findByIdAndDelete(id , (err , user)=>{

if(err){

console.log(‘Error in deleting the user’ , err);

}

console.log(‘user is successfully deleted’);

})

req.logout(function(err) {

if (err) { return next(err); }

res.redirect(‘/’);

});

})

// api’s

app.get(‘/api/v1’ , async function(req , res){

const users = await User.find({});

res.status(200).json({

message : “A list of users”,

users : users

});

})

// to create authentication and authorization of api, we will use passport-jwt

// we should verify password

// first created the session , so as to verify the user and providing the token to start request and response cycle

app.post(‘/createSession’ , async function(req ,res){

let user = await User.findOne({username : req.body.username});

if(!user || user.password != req.body.password){

res.status(422).json({

message : “Password is incorrect”

})

}else{

return res.status(200).json({

message : “Sing in successfully”,

data : {

// encypted

token : jwt.sign(user.toJSON() , ‘novel’ ,{

expiresIn : ‘100000’

} )

}

})

}

});

// delete the user through api

app.get(‘/api/v1/:id’ ,passport.authenticate(‘jwt’ , {session : false}) , function(req , res){

let id = req.params.id;

const user = User.findByIdAndDelete(id , (err , user)=>{

if(err){

console.log(‘Error while deleting the user’ , err);

}else{

res.status(200).json({

message : `A user is deleted successfully ${user}`

})

}

})

});

// chat box

app.get(‘/chatbox’ , function(req , res){

return res.render(‘chatbox’);

})

server.listen(port , function(err){

if(err){

console.log(‘Error in running the server’ , err);

}

console.log(‘Server is listening on port ‘ , port);

})

models

user.js (model)

var mongoose = require(‘mongoose’);

var Schema = mongoose.Schema;

var passportLocalMongoose = require(‘passport-local-mongoose’);

var UserSchema = new Schema({

email : {type : String , required : true , unique : true},

username : {type : String , unique: true, required:true},

password : {type:String , required: true},

file : {type : String , default : “file-1655418263289.jpg” , required : true}

});

UserSchema.plugin(passportLocalMongoose);

module.exports = mongoose.model(“User” , UserSchema);

config

nodemailer.js (config)

const nodemailer = require(‘nodemailer’);

const ejs = require(‘ejs’);

const path = require(‘path’);

const { model } = require(‘mongoose’);

let transporter = nodemailer.createTransport({

service : ‘gmail’,

host : ‘smtp.gmail.com’,

port : 587,

secure : false,

auth : {

user : ‘duperhritik@gmail.com’,

pass : ‘iyenozwtonxqeahw’

}

});

let renderTemplate = (data , relativePath) =>{

let mailHTML;

ejs.renderFile(

path.join(__dirname , ‘../views/mailers’ ,relativePath),

data,

function(err , template){

if(err){

console.log(‘Error in rendering template’ , err);

}else{

mailHTML = template;

}

}

)

return mailHTML;

}

module.exports = {

transporter : transporter,

renderTemplate : renderTemplate

}

passport-jwt-strategy.js (config)

const passport = require(‘passport’);

const JWTStrategy = require(‘passport-jwt’).Strategy;

const ExtractJWT = require(‘passport-jwt’).ExtractJwt;

const User = require(‘../models/user’);

let opts = {

jwtFromRequest : ExtractJWT.fromAuthHeaderAsBearerToken(),

secretOrKey : “novel”

}

passport.use(new JWTStrategy(opts, function(jwt_payload, done) {

User.findOne(jwt_payload.id, function(err, user) {

if (err) {

return done(err, false);

}

if (user) {

return done(null, user);

} else {

return done(null, false);

// or you could create a new account

}

});

}));

module.exports = passport;

mailers / comment.js

const nodemailer = require(‘../config/nodemailer’);

exports.newComment = (comment) => {

// console.log(‘Inside the new Comment mailer’);

//for rendering email

let htmlstring = nodemailer.renderTemplate({comment:comment} , ‘comment.ejs’)

console.log(‘cooment ‘ , comment);

nodemailer.transporter.sendMail({

from : ‘duperhritik@gmail.com’,

to: comment,

subject : “New Comment Published”,

html : htmlstring // earlier hardcoded

} , (err , info)=>{

if(err){

console.log(‘Error in sending mail’ , err);

}

console.log(‘Message Sent’ , info);

return;

})

}

middleware / index.js

var middlewareObj = {

// middleware to check login

isLoggedIn : function(req , res , next){

if(req.isAuthenticated()){

return next();

}

res.redirect(‘/’);

}

};

module.exports = middlewareObj;

config.js

const dbUrl = ‘mongodb://localhost:27017/final’;

module.exports = {

dbUrl : dbUrl

}

multer.js

‘using strict’;

const multer = require(‘multer’);

const path = require(‘path’);

const storage = multer.diskStorage({

destination : (req ,file , cb) => {

cb(null , ‘uploads’);

},

filename : (req , file , cb) => {

// remove forward slashes

cb(null , file.fieldname + “-” + Date.now()+”.jpg”);

}

});

// specific file like jpqg , png we want to store

const fileFilter = (req , file , cb) => {

if(file.mimetype === ‘image/png’ || file.mimetype === ‘image/jpg’ || file.mimetype === ‘image/jpeg’ ){

cb(null , true);

}else{

cb(null , false);

}

}

const upload = multer({storage : storage , fileFilter : fileFilter});

module.exports = upload;

views/

signin.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Sign In Page</title>

</head>

<body>

<h1>Welcome to Coders Place</h1>

<form action=”/signin” method=”POST”>

<input type=”text” name=”username” placeholder=”username” >

<input type=”password” name=”password” placeholder=”password”>

<input type=”submit”>

</form>

<p>Dont have an account, Create One Now</p>

<a href=”/signup”>Sign Up</a>

</body>

</html>

signup.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Sign Up Page</title>

</head>

<body>

<h1>Welcome to Coders Place</h1>

<form action=”/signup” method=”POST”>

<input type=”text” name=”username” placeholder=”username”>

<input type=”email” name=”email” placeholder=”email”>

<input type=”password” name=”password” placeholder=”password”>

<input type=”submit”>

</form>

<p>Already have an account, Sign In Directly</p>

<a href=”/signin”>Sign In</a>

</body>

</html>

update.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Document</title>

</head>

<body>

<form action=”/update” method=”POST” enctype=”multipart/form-data”>

<input type=”text” name=”username” placeholder=”username”>

<input type=”email” name=”email” placeholder=”email”>

<input type=”file” name=”file”>

<input type=”submit” >

</form>

</body>

</html>

forget.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Document</title>

</head>

<body>

<p>Forgot your password , dont worry you can reset your password</p>

<br>

<p>Fill the form to reset the password</p>

<form action=”/resetpassword” method=”POST”>

<input type=”password” name = “password” placeholder=”password”>

<input type=”password” name=”confirm_password” placeholder=”confirm_password” >

<input type=”submit” >

</form>

</body>

</html>

deleteUser.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Document</title>

</head>

<body>

<p>Are you sure you want to delete your account</p>

<a href=”/deleteUser/<%= user._id%>”>Delete Account Permanently</a>

</body>

</html>

home.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Home Page</title>

<link href=”https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel=”stylesheet”

integrity=”sha384–0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor” crossorigin=”anonymous”>

</head>

<body>

<! — flash messages using Toaster →

<% if(error && error.length> 0) { %>

<div class=”toast-container top-0 end-0 p-3">

<div class=”toast align-items-center fade show text-bg-danger” role=”alert” aria-live=”assertive”

aria-atomic=”true”>

<div class=”d-flex”>

<div class=”toast-body”>

<%= error %>

</div>

<button type=”button” class=”btn-close me-2 m-auto” data-bs-dismiss=”toast”

aria-label=”Close”></button>

</div>

</div>

</div>

<% } if(success && success.length> 0) { %>

<div class=”toast-container top-0 end-0 p-3">

<div class=”toast align-items-center fade show text-bg-danger” role=”alert” aria-live=”assertive”

aria-atomic=”true”>

<div class=”d-flex”>

<div class=”toast-body”>

<%= success %>

</div>

<button type=”button” class=”btn-close me-2 m-auto” data-bs-dismiss=”toast”

aria-label=”Close”></button>

</div>

</div>

</div>

<% } %>

<h2>Hey, you have successfully signed In</h2>

<form action=”/uploadpic” enctype=”multipart/form-data” method=”POST”>

<input type=”file” name=”file” required>

<input type=”submit”>

</form>

<h1>Sign Out</h1>

<a href=”/signout”>Sign Out</a>

<! — JavaScript Bundle with Popper →

<script src=”https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js"

integrity=”sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2"

crossorigin=”anonymous”></script>

</body>

</html>

showusers.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Show Users</title>

</head>

<body>

<h1>Users</h1>

<ul style=”list-style: none;”>

<% users.forEach(function(user){%>

<li><%=user.username%></li>

<li><%=user.email%></li>

<li><img src=”../uploads/<%= user.file %>” alt=”” width=”200px” height=”200px”></li>

<%})%>

<br><br><br><br>

</ul>

</body>

</html>

index.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Index Page</title>

</head>

<body>

<P>Welcome to the Jupitar Planet</P>

<h1>Sign In Page</h1>

<a href=”/signin”>Sign In</a>

<br>

<h1>Sign Up Page</h1>

<a href=”/signup”>Sign Up</a>

</body>

</html>

mailers/comment.ejs

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0">

<title>Social Media Application</title>

</head>

<body>

<h3>Nodejs Application with Nodemailer</h3>

<div>

<img src=”../../uploads/file-1655418493304.jpg” alt=”” width=”100vw” height=”50vh”>

<br>

<p>Respected</p>

<p>We at Google Developer Students Club invite you to join us on <b>8 July</b> in the Gurugram office of the Google. We really appreciated your contribution to the GDSC community and hereby declare a farewell party for you people. We welcome you and waiting for the event.</p>

<p>Thanks and Regards</p>

<p>Google Student Developers Group</p>

</div>

</body>

</html>

--

--

Hritik Khurana
0 Followers

Competitive Programmer . Full Stack Web Developer . Google DSC Lead