├── .gitignore ├── .env.example ├── app ├── middlewares │ ├── index.js │ ├── verifySignUp.js │ └── authJwt.js ├── controllers │ ├── user.controller.js │ ├── auth.controller.js │ └── book.controller.js ├── models │ ├── role.model.js │ ├── user.model.js │ ├── book.model.js │ └── index.js ├── config │ └── config.js └── routes │ ├── auth.routes.js │ ├── user.routes.js │ └── book.routes.js ├── package.json ├── server.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | node_modules 4 | .env -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | PORT=8080 3 | 4 | # Database 5 | DB_HOST=your-db-host 6 | DB_USER=your-db-username 7 | DB_PASS=your-db-password 8 | DB_NAME=your-db-name -------------------------------------------------------------------------------- /app/middlewares/index.js: -------------------------------------------------------------------------------- 1 | const authJwt = require("./authJwt"); 2 | const verifySignUp = require("./verifySignUp"); 3 | 4 | module.exports = { 5 | authJwt, 6 | verifySignUp 7 | }; 8 | -------------------------------------------------------------------------------- /app/controllers/user.controller.js: -------------------------------------------------------------------------------- 1 | exports.allAccess = (req, res) => { 2 | res.status(200).send("Public Content."); 3 | }; 4 | 5 | exports.userBoard = (req, res) => { 6 | res.status(200).send("User Content."); 7 | }; 8 | 9 | exports.adminBoard = (req, res) => { 10 | res.status(200).send("Admin Content."); 11 | }; 12 | 13 | exports.moderatorBoard = (req, res) => { 14 | res.status(200).send("Moderator Content."); 15 | }; 16 | -------------------------------------------------------------------------------- /app/models/role.model.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, Sequelize, DataTypes) => { 2 | const Role = sequelize.define( 3 | "role", // Model name 4 | { 5 | // Attributes 6 | id: { 7 | type: DataTypes.INTEGER, 8 | primaryKey: true 9 | }, 10 | name: { 11 | type: DataTypes.STRING 12 | } 13 | }, 14 | { 15 | // Options 16 | timestamps: true, 17 | underscrored: true, 18 | createdAt: "created_at", 19 | updatedAt: "updated_at" 20 | } 21 | ); 22 | 23 | return Role; 24 | }; 25 | -------------------------------------------------------------------------------- /app/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: process.env.NODE_ENV, 3 | PORT: process.env.PORT, 4 | 5 | /** DATABASE */ 6 | db: { 7 | DB_HOST: process.env.DB_HOST, 8 | DB_USER: process.env.DB_USER, 9 | DB_PASS: process.env.DB_PASS, 10 | DB_NAME: process.env.DB_NAME, 11 | dialect: "mysql", 12 | 13 | // pool is optional, it will be used for Sequelize connection pool configuration 14 | pool: { 15 | max: 5, 16 | min: 0, 17 | acquire: 30000, 18 | idle: 10000 19 | } 20 | }, 21 | 22 | /** AUTH KEY */ 23 | auth: { 24 | secret: "our-secret-key" 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /app/routes/auth.routes.js: -------------------------------------------------------------------------------- 1 | const { verifySignUp } = require("../middlewares"); 2 | const controller = require("../controllers/auth.controller"); 3 | 4 | module.exports = function(app) { 5 | app.use(function(req, res, next) { 6 | res.header( 7 | "Access-Control-Allow-Headers", 8 | "x-access-token, Origin, Content-Type, Accept" 9 | ); 10 | 11 | next(); 12 | }); 13 | 14 | app.post( 15 | "/api/auth/signup", 16 | [ 17 | verifySignUp.checkDuplicateUsernameOrEmail, 18 | verifySignUp.checkRolesExisted 19 | ], 20 | controller.signup 21 | ); 22 | 23 | app.post("/api/auth/signin", controller.signin); 24 | }; 25 | -------------------------------------------------------------------------------- /app/models/user.model.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, Sequelize, DataTypes) => { 2 | const User = sequelize.define( 3 | "user", // Model name 4 | { 5 | // Attributes 6 | id: { 7 | type: DataTypes.UUID, 8 | defaultValue: Sequelize.UUIDV4, 9 | primaryKey: true 10 | }, 11 | username: { 12 | type: DataTypes.STRING, 13 | unique: true 14 | }, 15 | email: { 16 | type: DataTypes.STRING 17 | }, 18 | password: { 19 | type: DataTypes.STRING 20 | } 21 | }, 22 | { 23 | // Options 24 | timestamps: true, 25 | underscrored: true, 26 | createdAt: "created_at", 27 | updatedAt: "updated_at" 28 | } 29 | ); 30 | 31 | return User; 32 | }; 33 | -------------------------------------------------------------------------------- /app/routes/user.routes.js: -------------------------------------------------------------------------------- 1 | const { authJwt } = require("../middlewares"); 2 | const controller = require("../controllers/user.controller"); 3 | 4 | module.exports = function(app) { 5 | app.use(function(req, res, next) { 6 | res.header( 7 | "Access-Control-Allow-Headers", 8 | "x-access-token, Origin, Content-Type, Accept" 9 | ); 10 | 11 | next(); 12 | }); 13 | 14 | app.get("/api/test/all", controller.allAccess); 15 | 16 | app.get("/api/test/user", [authJwt.verifyToken], controller.userBoard); 17 | 18 | app.get( 19 | "/api/test/mod", 20 | [authJwt.verifyToken, authJwt.isModerator], 21 | controller.moderatorBoard 22 | ); 23 | 24 | app.get( 25 | "/api/test/admin", 26 | [authJwt.verifyToken, authJwt.isAdmin], 27 | controller.adminBoard 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /app/routes/book.routes.js: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const bookController = require("../controllers/book.controller.js"); 3 | 4 | const router = require("express").Router(); 5 | 6 | // Create a new Book 7 | router.post("/", bookController.create); 8 | 9 | // Retrieve all Books 10 | router.get("/", bookController.findAll); 11 | 12 | // Retrieve all published Books 13 | router.get("/published", bookController.findAllPublished); 14 | 15 | // Retrieve a single Book with id 16 | router.get("/:id", bookController.findOne); 17 | 18 | // Update a Book with id 19 | router.put("/:id", bookController.update); 20 | 21 | // Delete a Book with id 22 | router.delete("/:id", bookController.delete); 23 | 24 | // Delete all Books 25 | router.delete("/", bookController.deleteAll); 26 | 27 | app.use("/api/books", router); 28 | }; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-sequelize-mysql", 3 | "version": "1.0.0", 4 | "description": "Learn REST API using Node.js, Express, Sequelize and MySQL", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "nodemon -r dotenv/config server.js" 9 | }, 10 | "keywords": [ 11 | "rest", 12 | "api", 13 | "nodejs", 14 | "express", 15 | "sequelize", 16 | "mysql", 17 | "jwt" 18 | ], 19 | "author": "Indra Arianggi", 20 | "license": "ISC", 21 | "dependencies": { 22 | "bcryptjs": "^2.4.3", 23 | "body-parser": "^1.19.0", 24 | "cors": "^2.8.5", 25 | "express": "^4.17.1", 26 | "jsonwebtoken": "^8.5.1", 27 | "mysql2": "^2.1.0", 28 | "sequelize": "^5.21.3" 29 | }, 30 | "devDependencies": { 31 | "dotenv": "^8.2.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/models/book.model.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, Sequelize, DataTypes) => { 2 | const Book = sequelize.define( 3 | "book", // Model name 4 | { 5 | // Model attributes 6 | id: { 7 | type: DataTypes.INTEGER, 8 | allowNull: false, 9 | autoIncrement: true, 10 | primaryKey: true 11 | }, 12 | title: { 13 | type: DataTypes.STRING 14 | }, 15 | author: { 16 | type: DataTypes.STRING 17 | }, 18 | published: { 19 | type: DataTypes.BOOLEAN 20 | }, 21 | created_at: { 22 | allowNull: false, 23 | type: DataTypes.DATE 24 | }, 25 | updated_at: { 26 | allowNull: false, 27 | type: DataTypes.DATE 28 | } 29 | }, 30 | { 31 | // Options 32 | timestamps: true, 33 | underscrored: true, 34 | createdAt: "created_at", 35 | updatedAt: "updated_at" 36 | } 37 | ); 38 | 39 | return Book; 40 | }; 41 | -------------------------------------------------------------------------------- /app/models/index.js: -------------------------------------------------------------------------------- 1 | const config = require("../config/config.js"); 2 | const { Sequelize, DataTypes, Op } = require("sequelize"); 3 | 4 | const sequelize = new Sequelize( 5 | config.db.DB_NAME, 6 | config.db.DB_USER, 7 | config.db.DB_PASS, 8 | { 9 | host: config.db.DB_HOST, 10 | dialect: config.db.dialect, 11 | operatorsAliases: false, 12 | 13 | poll: { 14 | max: config.db.pool.max, 15 | min: config.db.pool.min, 16 | acquire: config.db.pool.acquire, 17 | idle: config.db.pool.idle 18 | } 19 | } 20 | ); 21 | 22 | const db = {}; 23 | 24 | db.Sequelize = Sequelize; 25 | db.Op = Op; 26 | db.sequelize = sequelize; 27 | 28 | db.books = require("./book.model.js")(sequelize, Sequelize, DataTypes); 29 | db.user = require("./user.model.js")(sequelize, Sequelize, DataTypes); 30 | db.role = require("./role.model.js")(sequelize, Sequelize, DataTypes); 31 | 32 | db.role.belongsToMany(db.user, { 33 | through: "user_roles", 34 | foreignKey: "role_id", 35 | otherKey: "user_id" 36 | }); 37 | db.user.belongsToMany(db.role, { 38 | through: "user_roles", 39 | foreignKey: "user_id", 40 | otherKey: "role_id" 41 | }); 42 | 43 | db.ROLES = ["user", "admin", "moderator"]; 44 | 45 | module.exports = db; 46 | -------------------------------------------------------------------------------- /app/middlewares/verifySignUp.js: -------------------------------------------------------------------------------- 1 | const db = require("../models"); 2 | const ROLES = db.ROLES; 3 | const User = db.user; 4 | 5 | checkDuplicateUsernameOrEmail = (req, res, next) => { 6 | // Username 7 | User.findOne({ 8 | where: { 9 | username: req.body.username 10 | } 11 | }).then(user => { 12 | if (user) { 13 | res.status(400).send({ 14 | message: "Failed! Username is already in use!" 15 | }); 16 | return; 17 | } 18 | 19 | // Email 20 | User.findOne({ 21 | where: { 22 | email: req.body.email 23 | } 24 | }).then(user => { 25 | if (user) { 26 | res.status(400).send({ 27 | message: "Failed! Email is already in use!" 28 | }); 29 | return; 30 | } 31 | 32 | next(); 33 | }); 34 | }); 35 | }; 36 | 37 | checkRolesExisted = (req, res, next) => { 38 | if (req.body.roles) { 39 | for (let i = 0; i < req.body.roles.length; i++) { 40 | if (!ROLES.includes(req.body.roles[i])) { 41 | res.status(400).send({ 42 | message: "Failed! Role does not exist = " + req.body.roles[i] 43 | }); 44 | return; 45 | } 46 | } 47 | } 48 | 49 | next(); 50 | }; 51 | 52 | const verifySignUp = { 53 | checkDuplicateUsernameOrEmail: checkDuplicateUsernameOrEmail, 54 | checkRolesExisted: checkRolesExisted 55 | }; 56 | 57 | module.exports = verifySignUp; 58 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const bodyParser = require("body-parser"); 3 | const cors = require("cors"); 4 | const config = require("./app/config/config.js"); 5 | 6 | const app = express(); 7 | 8 | const corsOptions = { 9 | origin: "http://localhost:8081" 10 | }; 11 | 12 | app.use(cors(corsOptions)); 13 | 14 | // parse requests of content-type - application/json 15 | app.use(bodyParser.json()); 16 | 17 | // parse requests of content-type - application/x-www-form-urlencoded 18 | app.use(bodyParser.urlencoded({ extended: true })); 19 | 20 | // database 21 | const db = require("./app/models"); 22 | const Role = db.role; 23 | db.sequelize.sync().then(() => { 24 | initial(); // Just use it in development, at the first time execution!. Delete it in production 25 | }); 26 | 27 | // simple route 28 | app.get("/", (req, res) => { 29 | res.json({ message: "Hi there, welcome to this tutorial." }); 30 | }); 31 | 32 | // api routes 33 | require("./app/routes/book.routes")(app); 34 | require("./app/routes/auth.routes")(app); 35 | require("./app/routes/user.routes")(app); 36 | 37 | // set port, listen for requests 38 | const PORT = config.PORT; 39 | app.listen(PORT, () => { 40 | console.log(`Server is running on port ${PORT}`); 41 | }); 42 | 43 | // Just use it in development, at the first time execution!. Delete it in production 44 | function initial() { 45 | Role.create({ 46 | id: 1, 47 | name: "user" 48 | }); 49 | 50 | Role.create({ 51 | id: 2, 52 | name: "moderator" 53 | }); 54 | 55 | Role.create({ 56 | id: 3, 57 | name: "admin" 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # REST API using Node.js, Express, Sequelize and MySQL + JWT Authentication and Authorization 2 | 3 | ## Getting Started 4 | 5 | 1. Clone this repository 6 | 7 | ```bash 8 | git clone https://github.com/indraarianggi/nodejs-sequelize-mysql-api.git 9 | cd nodejs-sequelize-mysql-api 10 | ``` 11 | 12 | 2. Install the npm packages 13 | 14 | ```bash 15 | npm install 16 | ``` 17 | 18 | Also install `nodemon` globally, if you don't have it yet. 19 | 20 | ```bash 21 | npm install -g nodemon 22 | ``` 23 | 24 | 3. Congfigure environment settings 25 | 26 | Create a file with the following name and location `.env` and copy the contents from `.env.example` into it. Replace the values with your specific configuration. Don't worry, this file is in the `.gitignore` so it won't get pushed to github. 27 | 28 | ```javasscript 29 | NODE_ENV=development 30 | PORT=8080 31 | 32 | # Database 33 | DB_HOST=your-db-host 34 | DB_USER=your-db-username 35 | DB_PASS=your-db-password 36 | DB_NAME=your-db-name 37 | ``` 38 | 39 | 4. Running the app locally 40 | 41 | Run this command, which is located in npm script in `package.json` file. 42 | 43 | ```bash 44 | npm run dev 45 | ``` 46 | 47 | ## Resources 48 | 49 | 1. [Node.js Rest APIs example with Express, Sequelize & MySQL](https://bezkoder.com/node-js-express-sequelize-mysql/) 50 | 51 | 2. [Node.js – JWT Authentication & Authorization with JSONWebToken example](https://bezkoder.com/node-js-jwt-authentication-mysql/) 52 | 53 | 3. [In-depth Introduction to JWT-JSON Web Token](https://bezkoder.com/jwt-json-web-token/) 54 | 55 | 4. [Sequelize Documentation](https://sequelize.org/master/) 56 | 57 | 5. [Getting Started with Node, Express and Mysql Using Sequelize](https://medium.com/@prajramesh93/getting-started-with-node-express-and-mysql-using-sequelize-ed1225afc3e0) 58 | 59 | 6. [Hidup Mudah dengan Sequelize: ORM Untuk Aplikasi NodeJS](https://refactory.id/post/91-hidup-mudah-dengan-sequelize-orm-untuk-aplikasi-nodejs) 60 | 61 | 7. [Node.js Everywhere with Environment Variables!](https://medium.com/the-node-js-collection/making-your-node-js-work-everywhere-with-environment-variables-2da8cdf6e786) 62 | -------------------------------------------------------------------------------- /app/middlewares/authJwt.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const config = require("../config/config.js"); 3 | const db = require("../models"); 4 | const User = db.user; 5 | 6 | verifyToken = (req, res, next) => { 7 | let token = req.headers["x-access-token"]; 8 | 9 | if (!token) { 10 | return res.status(403).send({ 11 | message: "No token provided!" 12 | }); 13 | } 14 | 15 | jwt.verify(token, config.auth.secret, (err, decoded) => { 16 | if (err) { 17 | return res.status(401).send({ 18 | message: "Unauthorized!" 19 | }); 20 | } 21 | 22 | req.userId = decoded.id; 23 | 24 | next(); 25 | }); 26 | }; 27 | 28 | isAdmin = (req, res, next) => { 29 | User.findByPk(req.userId).then(user => { 30 | user.getRoles().then(roles => { 31 | for (let i = 0; i < roles.lenth; i++) { 32 | if (roles[i].name === "admin") { 33 | next(); 34 | return; 35 | } 36 | } 37 | 38 | res.status(403).send({ 39 | message: "Require Admin Role!" 40 | }); 41 | return; 42 | }); 43 | }); 44 | }; 45 | 46 | isModerator = (req, res, next) => { 47 | User.findByPk(req.userId).then(user => { 48 | user.getRoles().then(roles => { 49 | for (let i = 0; i < roles.length; i++) { 50 | if (roles[i].name === "moderator") { 51 | next(); 52 | return; 53 | } 54 | } 55 | 56 | res.status(403).send({ 57 | message: "Require Moderator Role!" 58 | }); 59 | }); 60 | }); 61 | }; 62 | 63 | isModeratorOrAdmin = (req, res, next) => { 64 | User.findByPk(req.userId).then(user => { 65 | user.getRoles().then(roles => { 66 | for (let i = 0; i < roles.length; i++) { 67 | if (roles[i].name === "moderator") { 68 | next(); 69 | return; 70 | } 71 | 72 | if (roles[i].name === "admin") { 73 | next(); 74 | return; 75 | } 76 | } 77 | 78 | res.status(403).send({ 79 | message: "Require Moderator or Admin Role!" 80 | }); 81 | }); 82 | }); 83 | }; 84 | 85 | const authJwt = { 86 | verifyToken: verifyToken, 87 | isAdmin: isAdmin, 88 | isModerator: isModerator, 89 | isModeratorOrAdmin: isModeratorOrAdmin 90 | }; 91 | 92 | module.exports = authJwt; 93 | -------------------------------------------------------------------------------- /app/controllers/auth.controller.js: -------------------------------------------------------------------------------- 1 | const config = require("../config/config"); 2 | const jwt = require("jsonwebtoken"); 3 | const bcrypt = require("bcryptjs"); 4 | const db = require("../models"); 5 | const User = db.user; 6 | const Role = db.role; 7 | const Op = db.Op; 8 | 9 | exports.signup = (req, res) => { 10 | // Save user to database 11 | User.create({ 12 | username: req.body.username, 13 | email: req.body.email, 14 | password: bcrypt.hashSync(req.body.password, 8) 15 | }) 16 | .then(user => { 17 | if (req.body.roles) { 18 | Role.findAll({ 19 | where: { 20 | name: { 21 | [Op.or]: req.body.roles 22 | } 23 | } 24 | }).then(roles => { 25 | user.setRoles(roles).then(() => { 26 | res.send({ message: "User was registered successfully!" }); 27 | }); 28 | }); 29 | } else { 30 | // User role 1 31 | user.setRoles([1]).then(() => { 32 | res.send({ message: "User was registered successfully!" }); 33 | }); 34 | } 35 | }) 36 | .catch(err => { 37 | res.status(500).send({ message: err.message }); 38 | }); 39 | }; 40 | 41 | exports.signin = (req, res) => { 42 | User.findOne({ 43 | where: { 44 | username: req.body.username 45 | } 46 | }) 47 | .then(user => { 48 | if (!user) { 49 | return res.status(404).send({ message: "User Not found." }); 50 | } 51 | 52 | let passwordIsValid = bcrypt.compareSync( 53 | req.body.password, 54 | user.password 55 | ); 56 | 57 | if (!passwordIsValid) { 58 | return res.status(401).send({ 59 | accessToken: null, 60 | message: "Invalid Password!" 61 | }); 62 | } 63 | 64 | let token = jwt.sign({ id: user.id }, config.auth.secret, { 65 | expiresIn: 86400 // 24 hours 66 | }); 67 | 68 | let authorities = []; 69 | user.getRoles().then(roles => { 70 | for (let i = 0; i < roles.length; i++) { 71 | authorities.push("ROLE_" + roles[i].name.toUpperCase()); 72 | } 73 | 74 | res.status(200).send({ 75 | id: user.id, 76 | username: user.username, 77 | email: user.email, 78 | roles: authorities, 79 | accessToken: token 80 | }); 81 | }); 82 | }) 83 | .catch(err => { 84 | res.status(500).send({ message: err.message }); 85 | }); 86 | }; 87 | -------------------------------------------------------------------------------- /app/controllers/book.controller.js: -------------------------------------------------------------------------------- 1 | const db = require("../models"); 2 | const Book = db.books; 3 | const Op = db.Op; 4 | 5 | // Create and Save a new Book 6 | exports.create = (req, res) => { 7 | // Validate request 8 | if (!req.body.title) { 9 | res.status(400).send({ 10 | message: "Content can not be empty!" 11 | }); 12 | return; 13 | } 14 | 15 | // Create a Book 16 | const book = { 17 | title: req.body.title, 18 | author: req.body.author, 19 | published: req.body.published ? req.body.published : false 20 | }; 21 | 22 | // Save Book in database 23 | Book.create(book) 24 | .then(data => { 25 | res.send(data); 26 | }) 27 | .catch(err => { 28 | res.status(500).send({ 29 | message: err.message || "Some error occurred while creating the Book." 30 | }); 31 | }); 32 | }; 33 | 34 | // Retrieve all Books from the database. 35 | exports.findAll = (req, res) => { 36 | const title = req.query.title; 37 | var condition = title ? { title: { [Op.like]: `%${title}%` } } : null; 38 | 39 | Book.findAll({ where: condition }) 40 | .then(data => { 41 | res.send(data); 42 | }) 43 | .catch(err => { 44 | res.send(500).send({ 45 | message: err.message || "Some error accurred while retrieving books." 46 | }); 47 | }); 48 | }; 49 | 50 | // Find a single Book with an id 51 | exports.findOne = (req, res) => { 52 | const id = req.params.id; 53 | 54 | Book.findByPk(id) 55 | .then(data => { 56 | res.send(data); 57 | }) 58 | .catch(err => { 59 | res.status(500).send({ 60 | message: `Error retrieving Book with id = ${id}` 61 | }); 62 | }); 63 | }; 64 | 65 | // Update a Book by the id in the request 66 | exports.update = (req, res) => { 67 | const id = req.params.id; 68 | 69 | Book.update(req.body, { 70 | where: { id: id } 71 | }) 72 | .then(num => { 73 | if (num == 1) { 74 | res.send({ 75 | message: "Book was updated successfully." 76 | }); 77 | } else { 78 | res.send({ 79 | message: `Cannot update Book with id=${id}. Maybe Book was not found or req.body is empty!` 80 | }); 81 | } 82 | }) 83 | .catch(err => { 84 | res.status(500).send({ 85 | message: "Error updating Book with id=" + id 86 | }); 87 | }); 88 | }; 89 | 90 | // Delete a Book with the specified id in the request 91 | exports.delete = (req, res) => { 92 | const id = req.params.id; 93 | 94 | Book.destroy({ 95 | where: { id: id } 96 | }) 97 | .then(num => { 98 | if (num == 1) { 99 | res.send({ 100 | message: "Book was deleted successfully!" 101 | }); 102 | } else { 103 | res.send({ 104 | message: `Cannot delete Book with id=${id}. Maybe Book was not found!` 105 | }); 106 | } 107 | }) 108 | .catch(err => { 109 | res.status(500).send({ 110 | message: "Could not delete Book with id=" + id 111 | }); 112 | }); 113 | }; 114 | 115 | // Delete all Books from the database. 116 | exports.deleteAll = (req, res) => { 117 | Book.destroy({ 118 | where: {}, 119 | truncate: false 120 | }) 121 | .then(nums => { 122 | res.send({ message: `${nums} Books were deleted successfully!` }); 123 | }) 124 | .catch(err => { 125 | res.status(500).send({ 126 | message: err.message || "Some error occurred while removing all books." 127 | }); 128 | }); 129 | }; 130 | 131 | // Find all published Books 132 | exports.findAllPublished = (req, res) => { 133 | Book.findAll({ where: { published: true } }) 134 | .then(data => { 135 | res.send(data); 136 | }) 137 | .catch(err => { 138 | res.status(500).send({ 139 | message: err.message || "Some error occurred while retrieving books." 140 | }); 141 | }); 142 | }; 143 | --------------------------------------------------------------------------------