Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a99d5e5

Browse files
Added Book Add/Update/List/Detail
1 parent b4a2757 commit a99d5e5

File tree

11 files changed

+225
-22
lines changed

11 files changed

+225
-22
lines changed

‎.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
MONGODB_URL=YourConnectionString
22
JWT_SECRET=YourSecret
3-
JWT_TIMEOUT_DURATION=2
3+
JWT_TIMEOUT_DURATION="2 hours"

‎.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@ typings/
5959

6060
# next.js build output
6161
.next
62+
63+
#vs code configurations
64+
.vscode/

‎app.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,10 @@ app.all("*", function(req, res) {
3838
return apiResponse.notFoundResponse(res, 'Page not found');
3939
});
4040

41+
app.use((err, req, res, next) => {
42+
if(err.name == "UnauthorizedError"){
43+
return apiResponse.unauthorizedResponse(res, err.message);
44+
}
45+
});
46+
4147
module.exports = app;

‎controllers/BookController.js

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
const Book = require("../models/BookModel");
2+
const { body,validationResult } = require('express-validator');
3+
const { sanitizeBody } = require('express-validator');
4+
const apiResponse = require('../helpers/apiResponse');
5+
const auth = require('../middlewares/jwt');
6+
var moment = require('moment');
7+
var mongoose = require('mongoose');
8+
9+
function BookData(data) {
10+
this.title= data.title;
11+
this.description = data.description;
12+
this.isbn = data.isbn;
13+
this.createdAt = data.createdAt;
14+
}
15+
16+
/**
17+
* Book List.
18+
*
19+
* @returns {Object}
20+
*/
21+
exports.bookList = [
22+
auth,
23+
function (req, res) {
24+
try {
25+
Book.find({user: req.user._id},'title description isbn createdAt').then((books)=>{
26+
if(books.length > 0){
27+
return apiResponse.successResponseWithData(res, 'Operation success', books);
28+
}else{
29+
return apiResponse.successResponseWithData(res, "Operation success", {});
30+
}
31+
});
32+
} catch (err) {
33+
//throw error in json response with status 500.
34+
return apiResponse.ErrorResponse(res, err);
35+
}
36+
}
37+
];
38+
39+
/**
40+
* Book Detail.
41+
*
42+
* @returns {Object}
43+
*/
44+
exports.bookDetail = [
45+
auth,
46+
function (req, res) {
47+
if(!mongoose.Types.ObjectId.isValid(req.params.id)){
48+
return apiResponse.successResponseWithData(res, "Operation success", {});
49+
}
50+
try {
51+
Book.findOne({_id: req.params.id,user: req.user._id},'title description isbn createdAt').then((book)=>{
52+
if(book !== null){
53+
let bookData = new BookData(book);
54+
return apiResponse.successResponseWithData(res, 'Operation success', bookData);
55+
}else{
56+
return apiResponse.successResponseWithData(res, "Operation success", {});
57+
}
58+
});
59+
} catch (err) {
60+
//throw error in json response with status 500.
61+
return apiResponse.ErrorResponse(res, err);
62+
}
63+
}
64+
];
65+
66+
/**
67+
* Store book.
68+
*
69+
* @param {string} title
70+
* @param {string} description
71+
* @param {string} isbn
72+
*
73+
* @returns {Object}
74+
*/
75+
exports.bookStore = [
76+
auth,
77+
body('title', 'Title must not be empty.').isLength({ min: 1 }).trim(),
78+
body('description', 'Description must not be empty.').isLength({ min: 1 }).trim(),
79+
body('isbn', 'ISBN must not be empty').isLength({ min: 1 }).trim().custom(value => {
80+
return Book.findOne({isbn : value,user: req.user._id}).then(book => {
81+
if (book) {
82+
return Promise.reject('Book already exist with this ISBN no.');
83+
}
84+
});
85+
}),
86+
sanitizeBody('*').escape(),
87+
(req, res, next) => {
88+
try {
89+
const errors = validationResult(req);
90+
var book = new Book(
91+
{ title: req.body.title,
92+
user: req.user,
93+
description: req.body.description,
94+
isbn: req.body.isbn
95+
});
96+
97+
if (!errors.isEmpty()) {
98+
return apiResponse.validationErrorWithData(res, 'Validation Error.', errors.array());
99+
}
100+
else {
101+
//Save book.
102+
book.save(function (err) {
103+
if (err) { return apiResponse.ErrorResponse(res, err); }
104+
let bookData = new BookData(book);
105+
return apiResponse.successResponseWithData(res,'Book add Success.', bookData);
106+
});
107+
}
108+
} catch (err) {
109+
//throw error in json response with status 500.
110+
return apiResponse.ErrorResponse(res, err);
111+
}
112+
}
113+
];
114+
115+
/**
116+
* Store book.
117+
*
118+
* @param {string} title
119+
* @param {string} description
120+
* @param {string} isbn
121+
*
122+
* @returns {Object}
123+
*/
124+
exports.bookUpdate = [
125+
auth,
126+
body('title', 'Title must not be empty.').isLength({ min: 1 }).trim(),
127+
body('description', 'Description must not be empty.').isLength({ min: 1 }).trim(),
128+
body('isbn', 'ISBN must not be empty').isLength({ min: 1 }).trim(),
129+
sanitizeBody('*').escape(),
130+
(req, res, next) => {
131+
try {
132+
const errors = validationResult(req);
133+
var book = new Book(
134+
{ title: req.body.title,
135+
description: req.body.description,
136+
isbn: req.body.isbn,
137+
_id:req.params.id
138+
});
139+
140+
if (!errors.isEmpty()) {
141+
return apiResponse.validationErrorWithData(res, 'Validation Error.', errors.array());
142+
}
143+
else {
144+
if(!mongoose.Types.ObjectId.isValid(req.params.id)){
145+
return apiResponse.validationErrorWithData(res, 'Invalid Error.', "Invalid ID");
146+
}
147+
Book.findOne({isbn : req.body.isbn,user: req.user._id, _id: { "$ne": req.params.id }}).then(book => {
148+
if (book) {
149+
return apiResponse.validationErrorWithData(res, 'Validation Error.', "Book already exist with this ISBN no.");
150+
}
151+
});
152+
//Check authorized user
153+
Book.findById(req.params.id, function (err, book) {
154+
if(book.user.toString() !== req.user._id){
155+
return apiResponse.unauthorizedResponse(res, 'You are not authorized to do this operation.');
156+
}
157+
});
158+
//Save book.
159+
Book.findByIdAndUpdate(req.params.id, book, {},function (err) {
160+
if (err) { return apiResponse.ErrorResponse(res, err); }
161+
let bookData = new BookData(book);
162+
return apiResponse.successResponseWithData(res,'Book update Success.', bookData);
163+
});
164+
}
165+
} catch (err) {
166+
//throw error in json response with status 500.
167+
return apiResponse.ErrorResponse(res, err);
168+
}
169+
}
170+
];

‎middlewares/jwt.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const jwt = require('express-jwt');
2+
const secret = process.env.JWT_SECRET;
3+
4+
const authenticate = jwt({
5+
secret: secret
6+
});
7+
8+
module.exports = authenticate;

‎models/BookModel.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var mongoose = require('mongoose');
2+
var moment = require('moment');
3+
4+
var Schema = mongoose.Schema;
5+
6+
var BookSchema = new Schema({
7+
title: {type: String, required: true},
8+
description: {type: String, required: true},
9+
isbn: {type: String, required: true},
10+
user: { type: Schema.ObjectId, ref: 'User', required: true },
11+
}, {timestamps: true});
12+
13+
module.exports = mongoose.model('Book', BookSchema);

‎models/UserModel.js

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
11
var mongoose = require('mongoose');
22

33
var UserSchema = new mongoose.Schema({
4-
firstName: {
5-
type: String,
6-
required: true
7-
},
8-
lastName: {
9-
type: String,
10-
required: true
11-
},
12-
email: {
13-
type: String,
14-
required: true
15-
},
16-
password: {
17-
type: String,
18-
required: true
19-
},
20-
status: {
21-
type: Boolean,
22-
required: true,
23-
default: 1,
24-
}
4+
firstName: {type: String, required: true},
5+
lastName: {type: String, required: true},
6+
email: {type: String, required: true},
7+
password: {type: String, required: true},
8+
status: {type: Boolean, required: true, default: 1}
259
}, {timestamps: true});
2610

2711
// Virtual for user's full name

‎package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"express-jwt": "^5.3.1",
1616
"express-validator": "^6.1.1",
1717
"jsonwebtoken": "^8.5.1",
18+
"moment": "^2.24.0",
1819
"mongoose": "^5.6.6",
1920
"morgan": "~1.9.0"
2021
},

‎routes/api.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
var express = require('express');
22
var usersRouter = require('./users');
33
var authRouter = require('./auth');
4+
var bookRouter = require('./book');
45

56
var app = express();
67

78
app.use('/users/', usersRouter);
89
app.use('/auth/', authRouter);
10+
app.use('/book/', bookRouter);
911

1012
module.exports = app;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /