Backend Development with NodeJs
Architecture
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>