Open In App

Library Management Application Backend

Library Management System backend using Express and MongoDB contains various endpoints that will help to manage library users and work with library data. The application will provide an endpoint for user management. API will be able to register users, authenticate users, borrow books, return books, create books, pay fine . We’ll be using NodeJS, Express and MongoDB. So, let’s get started with building the backend.

Note: Follow given link to build a Web application on Library Management System.

Preview of final output: Let us have a look at how the final application will look like.



Prerequisites:

Approach to create Library Management Application Backend:

Functionalities:

Steps to create a project:

Step 1: First, we will initiate the Node project using below command. Go to project folder and run below command.



npm init -y

Step 2: Install the required dependencies as mentioned below using below npm command.

npm i express body-parser connect-mongo express-session jsonwebtoken mongoose
nodemon passport passport-jwt passport-local

Project Structure:

The updated dependencies in package.json file will look like:

"dependencies":{
"body-parser": "^1.20.2",
"connect-mongo": "^5.1.0",
"express": "^4.18.2",
"express-session": "^1.17.3",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.0.3",
"nodemon": "^3.0.2",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0"
}

Example: Add the following codes in respective files.




//index.js
 
const express = require('express');
const bodyParser = require('body-parser');
var session = require('express-session');
const MongoStore = require("connect-mongo");
const port = 5000;
const app = express();
var { db } = require('./db');
var authRouter = require('./auth');
var libraryRouter = require('./library');
//body-parser configuration
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
    extended: true
}))
 
//session configuration
app.use(session({
    secret: 'gfgsecret',
    resave: false,
    saveUninitialized: true,
    store: MongoStore.create({
        client: db.getClient(),
        dbName: 'testdb',
        collectionName: "sessions",
        stringify: false,
        autoRemove: "interval",
        autoRemoveInterval: 1
    })
}));
 
app.use('/', authRouter);
app.use('/', libraryRouter);
 
//server listening
app.listen(port, () => {
    console.log(`server started on ${port}`);
});




//db.js
 
const mongoose = require('mongoose');
 
//database connection
mongoose.connect("<YOUR MONGODB CONNECTION URL>");
 
const db = mongoose.connection;
 
db.on('error', console.error.bind(console, 'connection error:'));
 
 
db.once('open', function () {
    console.log("Connection Successful!");
});
 
//model and schema creation
var UserSchema = mongoose.Schema({
    name: String,
    username: { type: String, unique: true },
    password: String,
    email: { type: String, unique: true },
    mobile: { type: Number, unique: true },
    admin: { type: Boolean, default: false }
});
 
var BookSchema = mongoose.Schema({
    name: String,
    author: String,
    genre: String,
    type: String,
    available: { type: Boolean, default: true }
}, { timestamps: true })
 
var BorrowerRecordSchema = mongoose.Schema({
    username: String,
    bookid: { type: mongoose.ObjectId, unique: true, ref: 'Book' },
    duedate: {
        type: Date,
        default: () => new Date(+new Date() + 15 * 24 * 60 * 60 * 1000),
        required: 'Must Have DueDate'
    }
}, { timestamps: true })
 
var ReturnRecordSchema = mongoose.Schema({
    username: String,
    bookid: { type: mongoose.ObjectId, unique: true, ref: 'Book' },
    duedate: { type: Date, ref: 'BorrowerRecord' },
    fine: Number
}, { timestamps: true })
 
var User = mongoose.model('User', UserSchema, 'user');
var Book = mongoose.model('Book', BookSchema, 'books');
var BorrowerRecord = mongoose.model('BorrowerRecord',
                                     BorrowerRecordSchema, 'borrowers');
var ReturnRecord = mongoose.model('ReturnRecord',
                                   ReturnRecordSchema, 'returnrecords');
 
module.exports = { db, User, Book, BorrowerRecord, ReturnRecord };




//auth.js
 
const jwt = require('jsonwebtoken');
const JWTStrategy = require("passport-jwt").Strategy;
var LocalStrategy = require('passport-local');
var passport = require('passport');
const express = require('express');
var router = express.Router();
var { User } = require('./db');
 
//passport local strategy configuration
passport.use(new LocalStrategy(async function verify(username, password, cb) {
    const query = User.where({ username: username });
    await query.findOne().then(function (user) {
        if (user.password === password) {
            cb(null, user, { status: 200, message: 'Login Successful.' });
        }
        else {
            cb(null, false, { status: 401,
                message: 'Incorrect username or password.'
            })
        }
    }).catch(function (err) {
        cb(null, false, { status: 401, message: 'User Does Not Exist' })
    });
}));
 
//passport jwt strategy configuration
passport.use(new JWTStrategy(
    {
        jwtFromRequest: (req) => req.headers['x-access-token'],
        secretOrKey: 'examplesecret',
    },
    (payload, done) => {
        return done(null, payload);
    }
));
 
passport.serializeUser(function (user, cb) {
    process.nextTick(function () {
        cb(null, { id: user.id, username: user.username });
    });
});
 
passport.deserializeUser(function (user, cb) {
    process.nextTick(function () {
        return cb(null, user);
    });
});
 
//route for registering user and admin
router.post('/register', async (req, res) => {
    //new user creation from request body data
    var user1 = new User(req.body);
 
    await user1.save().then(function (user) {
        if (user) {
            console.log(user.name + " saved to user collection.");
            res.send({ status: 200, message: user.name });
        }
    }, function (err) {
 
        //errors for various primary key
        if (Object.keys(err.keyPattern)[0] == 'mobile') {
            res.send({ status: 500, message: "User with mobile already exist"});
        }
        else if (Object.keys(err.keyPattern)[0] == 'username') {
            res.send({status: 500, message:"User with username already exist"});
        }
        else if (Object.keys(err.keyPattern)[0] == 'email') {
            res.send({ status: 500, message: "User with email already exist" });
        }
        else {
            res.send({ status: 500, message: "Internal Server Error" });
        }
    });
});
 
 
//route for logging user in
router.post('/login', (req, res) => {
    passport.authenticate('local', { session: false }, (err, user, info) => {
        if (err || !user) {
            return res.send({ status: 401, message: info.message });
        }
        req.login(user, { session: false }, (err) => {
            if (err) {
                res.send(err);
            }
            var userobject = {
                username: user.username,
                mobile: user.mobile,
                admin: user.admin
            }
            var token = jwt.sign(userobject, 'examplesecret');
            req.session.jwt = token;
            return res.send({ status: 200, token: token });
        });
    })(req, res);
});
 
 
//route for logging out user
router.post('/logout', (req, res, next) => {
    req.session.destroy(function (err) {
        if (err) { return next(err); }
        res.redirect('/');
    });
})
 
//route for getting session in frontend
router.get('/session', (req, res) => {
    passport.authenticate('jwt', { session: false }, (err, user) => {
        if (err || !user) {
            res.send(false);
        } else {
            res.send(user);
        }
    })(req, res);
});
 
module.exports = router;




//library.js
 
const express = require("express");
var passport = require("passport");
var router = express.Router();
var { User, Book, BorrowerRecord, ReturnRecord } = require("./db");
 
//home endpoint
router.get("/", (req, res) => {
    res.send("Welcome To Library Management System");
});
 
//route for getting all books from database
router.get("/getbooks", async (req, res) => {
    const books = await Book.find({});
    res.send({ status: 200, books: books });
});
 
//route for getting all users from database
router.get("/getusers", async (req, res) => {
    const users = await User.find({});
    res.send({ status: 200, users: users });
});
 
//route for creating a new book
router.post("/createbook", async (req, res) => {
    //new book from request body
    var book = new Book(req.body);
 
    //authentication
    passport.authenticate("jwt", { session: false }, async (err, user) => {
        if (err || !user) {
            res.send({ status: 401, message: "Not Authorized" });
        } else {
            //checking if the user is admin
            if (user.admin) {
                //saving book to db
                await book.save().then(
                    function (saveres) {
                        if (saveres) {
                            res.send({ status: 200, message: saveres });
                        }
                    },
                    function (err) {
                        res.send({
                            status: 500,
                            message: "Internal Server Error",
                        });
                    }
                );
            } else {
                res.send({
                    status: 401,
                    message: "You are not authorized to perform this action",
                });
            }
        }
    })(req, res);
});
 
//route for borrowing a new book
router.post("/borrowbook", async (req, res) => {
    //userid and bookid from request
    var bookid = req.body.bookid;
    var borrowerusername = req.body.username;
 
    //authentication
    passport.authenticate("jwt", { session: false }, async (err, user) => {
        if (err || !user) {
            res.send({ status: 401, message: "Not Authorized" });
        } else {
            if (user.admin) {
                User.findOne({ username: borrowerusername })
                    .then((user) => {
                        console.log(user);
                        if (user) {
                            Book.findOne({ _id: bookid })
                                .then((book) => {
                                    console.log("book");
                                    if (book) {
                                        if (book.available) {
                                            //creating and saving new borrower record in database.
                                            var newBorrowerRecord =
                                                new BorrowerRecord({
                                                    username: user.username,
                                                    bookid: book["_id"],
                                                });
                                            newBorrowerRecord
                                                .save()
                                                .then((saveres) => {
                                                    if (saveres) {
                                                        Book.where({
                                                            _id: book["_id"],
                                                        })
                                                            .updateOne({
                                                                available: false,
                                                            })
                                                            .then((updtres) => {
                                                                res.send({
                                                                    status: 200,
                                                                    message:
                                                                        "book borrowed successfully by " +
                                                                        user.username,
                                                                });
                                                            });
                                                    } else {
                                                        res.send({
                                                            status: 500,
                                                            message:
                                                                "Error Borrowing Book",
                                                        });
                                                    }
                                                })
                                                .catch((err) => {
                                                    res.send({
                                                        status: 500,
                                                        message:
                                                            "Error Borrowing Book",
                                                    });
                                                });
                                        } else {
                                            res.send({
                                                status: 500,
                                                message:
                                                    "Book Is not available",
                                            });
                                        }
                                    } else {
                                        res.send({
                                            status: 500,
                                            message:
                                                "Book with Id Does Not Exist",
                                        });
                                    }
                                })
                                .catch((err) => {
                                    res.send({
                                        status: 500,
                                        message: "Internal Server Error",
                                    });
                                });
                        } else {
                            res.send({
                                status: 500,
                                message: "Borrower Does Not Exist",
                            });
                        }
                    })
                    .catch((err) => {
                        res.send({
                            status: 500,
                            message: "Internal Server Error",
                        });
                    });
            } else {
                res.send({
                    status: 401,
                    message: "You are not authorized to perform this action",
                });
            }
        }
    })(req, res);
});
 
//route for returning a book
router.post("/returnbook", async (req, res, next) => {
    var bookid = req.body.bookid;
    var borrowerusername = req.body.username;
 
    //authentication
    passport.authenticate("jwt", { session: false }, async (err, user) => {
        if (err || !user) {
            res.send({ status: 401, message: "Not Authorized" });
        } else {
            if (user.admin) {
                //checking for existance of borrower record in db
                BorrowerRecord.findOne({
                    bookid: bookid,
                    username: borrowerusername,
                })
                    .then((borrowrec) => {
                        if (borrowrec) {
                            var todaysdate = new Date().toISOString();
 
                            //calculation of fine if delayed in returning
                            const fine = 0;
                            if (todaysdate > borrowrec.submitdate) {
                                const diffTime = Math.abs(
                                    todaysdate - borrowrec.submitdate
                                );
                                const diffDays = Math.ceil(
                                    diffTime / (1000 * 60 * 60 * 24)
                                );
 
                                fine = diffDays * 2;
                            }
 
                            //creating and saving new return record.
                            var returnrec = new ReturnRecord({
                                username: borrowerusername,
                                bookid: bookid,
                                duedate: borrowrec.submitdate,
                                fine: fine,
                            });
 
                            returnrec
                                .save()
                                .then((saveres) => {
                                    if (saveres) {
                                        Book.findOne({ _id: bookid })
                                            .updateOne({ available: true })
                                            .then((updtres) => {
                                                if (updtres) {
                                                    res.send({
                                                        status: 200,
                                                        message:
                                                            "Book Returned Successfully",
                                                    });
                                                } else {
                                                    res.send({
                                                        status: 500,
                                                        message:
                                                            "Error Creating Return Record",
                                                    });
                                                }
                                            });
                                    } else {
                                        res.send({
                                            status: 500,
                                            message:
                                                "Error Creating Return Record",
                                        });
                                    }
                                })
                                .catch((err) => {
                                    res.send({
                                        status: 500,
                                        message: "Internal Server Error",
                                    });
                                });
                        } else {
                            res.send({
                                status: 500,
                                message: "No Record Found",
                            });
                        }
                    })
                    .catch((err) => {
                        res.send({
                            status: 500,
                            message: "Internal Server Error",
                        });
                    });
            } else {
                res.send({
                    status: 401,
                    message: "You are not authorized to perform this action",
                });
            }
        }
    })(req, res);
});
 
//route for paying fine
router.post("/payfine", (req, res) => {
    //return record id from request.
    var returnrecid = req.body.returnrecordid;
 
    //authentication
    passport.authenticate("jwt", { session: false }, async (err, user) => {
        if (err || !user) {
            res.send({ status: 401, message: "Not Authorized" });
        } else {
            if (user.admin) {
                //paying fine by updating return record in database.
                ReturnRecord.findOne({ _id: returnrecid })
                    .updateOne({ fine: 0 })
                    .then((updtres) => {
                        if (updtres) {
                            res.send({
                                status: 200,
                                message: "Fine Paid Successfully",
                            });
                        } else {
                            res.send({
                                status: 500,
                                message: "Error paying Fine",
                            });
                        }
                    })
                    .catch((err) => {
                        res.send({
                            status: 500,
                            message: "Internal Server Error",
                        });
                    });
            } else {
                res.send({
                    status: 401,
                    message: "You are not authorized to perform this action",
                });
            }
        }
    })(req, res);
});
 
module.exports = router;

Steps to run the application : Run the following command in the terminal.

nodemon index.js 

NOTE : For accessing routes which requires LOGIN you need to pass JWT token as ‘x-access-token’ from headers as below .

List of All API links :

Output:


Article Tags :