ESP32 Keypad Database Security System - REST - Logo

Posted on

by

in

Build REST API Using Node.js, Express and MongoDB

Introduction

In this post, we are going to build a REST API using Node.js, Express, and MongoDB. These APIs will be called by our Internet of Things(IOT) projects.

REST (Representation State Transfer) or RESTful API architectural style uses HTTP requests to manipulate any server resources. In this tutorial, we are building our own RESTful application that will allow us to initiate a CRUD (Create/Read/Update/Delete) operation with our database. We are using Node.js, Express, and MongoDB Atlas in creating our REST API server.

We are building an application to manipulate keycodes in our MongoDB Atlas database. These keycodes are entered thru our Keypad electronic components that are being read by our Microcontroller(MCU) unit. As an IOT developer, knowledge about how to create or interface with RESTful API web service will help expand your experience in creating more creative projects.

This post is part of the following tutorial series that uses it as part of the IOT project.

Let’s get on with it!

Video

The following video shows how I did the setup and testing if you want to see it in actuality.

Special Notes Before You Proceed

The following sections will discuss how to set up your own REST API Server using Node.js, Express, and MongoDB Atlas step by step. It involves lots of javascript programming and if you are not comfortable working with these technologies then you can skip this part.

You can just set up your MongoDB cluster by following this post as we need this to store our keycodes. But I highly suggest that you work your way into these steps so that you would learn how to set up your own REST API Server. This skill will widen your knowledge as an IOT developer.

Proceed to the next part of your series which it will discuss how to run the applications

Prerequisites

I am using a Windows workstation and have installed git bash shell as well. In addition, you need to have a working knowledge of Javascript and Node.js.

Design

Let’s discuss first a brief overview of our REST API Server before we go a deep dive into how we start coding it.

REST API Server in Node.js Design
  • HTTP requests come in from different clients. It could be coming from our browsers, command line calls (e.g curl), or even from our Internet of Things Devices (e.g. Arduino, ESP32, Raspberry Pi).
  • HTTP requests usually come with two important components that we care about. One is the HTTP Methods (e.g. GET, POST, PUT, DELETE, etc.) and the other is the path (e.g. ‘/api/keycodes/:code’). For our diagram above the HTTP, Method is GET and the path is “/api/keycodes/:code”.
  • All these HTTP requests are being handled by our Node.js server and assigned specific routes. Each route uses a controller object to handle the request.
  • Controllers communicate with our backend database using Models or what they call an Object Modelling tool (e.g. Mongoose) that communicates with our database which is MongoDB in this case.
  • Data that is being retrieved from our backend database is then processed by the controllers and then send it back to our calling client usually in JSON format.
  • The Routes, Controllers, and Models are coded using the Javascript programming language.

And that is all for a high-level overview of what we are trying to do. The next sections will discuss each of the components we have discussed above. We will be diving deeper into how to create our REST API server using Node.js, Express, and MongoDB Atlas.

Steps

Create our Express Applications

Create a directory in your workstation and name it accordingly as ‘keypads-iot-rest-applications

mkdir keypads-iot-rest-applications

Then, cd into that directory

cd keypads-iot-rest-applications

Then, run the following commands to initiate our Node.js application

$ npm init -y
Wrote to C:\git\nodejs-projects\keypads-iot-rest-applications\package.json:

{
  "name": "keypads-iot-rest-applications",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Install Dependencies

Now we can begin installing the required npm package dependencies for our application. Let’s begin by installing the following node.js libraries.

  • express – will serve as our framework for our backend
  • body-parser – is a middleware function to allow us to read the body of our incoming JSON request
npm install --save express body-parser

Then install the dependencies that are to be useful only during the development process.

  • nodemon – will assist us during development as we won’t be needing to restart our server whenever we do changes.
npm install --save-dev nodemon

We will be adding more dependencies as we go along with the post.

Configure our scripts

To run our application then we need to configure several scripts in our package.json file. During development, we are gonna be doing several code changes at the same time and that is where nodemon package will help us. But during the production run then it is required that we run the normal node runtime script. To do that open your package.json file and add the following entries.

The “dev” script will run our code using nodemon

The “start” script will run our code using the normal node.js runtime

  "scripts": {
    "dev": "nodemon index.js",
    "start": "node index.js"
  }

Afterwhich, your package.json should look like the following.

{
  "name": "keypads-iot-rest-applications",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index.js",
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.20.0",
    "express": "^4.18.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.18"
  }
}

Once you are done, then you could open Visual Studio Code by dragging the folder into it or you could execute the below command to open it as well.

code .

Add .gitignore to our project

Before we start coding our server let us first create a .gitignore file so that we will skip files or directories not meant to be committed to our git repository. Examples of these are configuration files, database credentials, or log files generated by our application.

In Visual Studio code, add a new file called .gitignore then copy the content coming from this gitignore link.

Visual Studio Code gitignore setup

Coding our REST API Server

Next, open the index.js file and paste the following code.

const express = require("express")

const PORT = process.env.PORT || 3000

const app = express()

app.listen(PORT, function () {
  console.log(`Server app listening on port ${PORT}`)
})

The code above will import the required express dependency, open a TCP port and listen for the connection and then log the welcome message.

To run our server application then you can open a terminal inside visual studio code or open it in an external command or git-shell. If everything goes well then you should see the following message logged at your console “Server app listening on port 3000”

$ npm run dev

> keypads-iot-rest-applications@1.0.0 dev C:\git\nodejs-projects\keypads-iot-rest-applications
> nodemon index.js

[nodemon] 2.0.18
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Server app listening on port 3000

Add JSON Parsing Support (body-parser)

We will be adding additional middleware to handle the parsing of the request body into JSON format. We will use the body-parser npm package to do this.

const bodyParser = require("body-parser")

//middleware functions
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

The first function will handle the incoming request and convert it to JSON. The second one will take care of any URL encoded request for us. Our index.js will now look like this.

const express = require("express")
const bodyParser = require("body-parser")

const PORT = process.env.PORT || 3000

const app = express()

//middleware functions
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

app.listen(PORT, function () {
  console.log(`Server app listening on port ${PORT}`)
})
Keypads IOT Rest in Visual Studio Code

Now that we have a working server then we can begin connecting to our cloud database cluster using Mongo Atlas.

Connecting to our MongoDB Atlas Cluster

In our previous post, we set up our own MongoDB Atlas cluster and connected to it using MongoDB Compass. If you have not set up your own MongoDB Atlas cluster then now is the best time to do that.

We will be needing as well the connection string to our MongoDB Atlas cluster in the following format:

Format
mongodb+srv://<USER_NAME>:<YOUR_PASSWORD>@<CLUSTER_NAME>.attzkit.mongodb.net/<DATABASE>
e.g.
mongodb+srv://<USER_NAME>:<YOUR_PASSWORD>@cluster0.attzkit.mongodb.net/keypadsdb

cluster0 – is the name of the cluster that I created

keypadsdb – is the name of the database where our data will be placed

In order for our REST API Application to connect to the cluster that we have created in our MongoDB Atlas then we will be using the Mongoose npm package. Mongoose is an object modeling tool that will make it easy for us to interact with our MongoDB database.

npm install --save mongoose

To use the mongoose package then we will just need to add the following entry to our index.js file.

const mongoose = require("mongoose")

//setup mongoose
const mongodbConnString = "YOUR_CONNECTION_STRING"

mongoose.connect(mongodbConnString)

mongoose.connection.on("error", function(error) {
  console.log(error)
})

mongoose.connection.on("open", function() {
  console.log("Successfully connected to MongoDB Atlas database.")
})

Your index.js should now look like this

const express = require("express")
const bodyParser = require("body-parser")
const mongoose = require("mongoose")

const PORT = process.env.PORT || 3000

const app = express()

//middleware functions
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

//setup mongoose
const mongodbConnString = "<YOUR_CONN_STRING>"

mongoose.connect(mongodbConnString)

mongoose.connection.on("error", function(error) {
  console.log(error)
})

mongoose.connection.on("open", function() {
  console.log("Successfully connected to MongoDB Atlas database.")
})

app.listen(PORT, function () {
  console.log(`Server app listening on port ${PORT}`)
})

We set the values of our connection string in our mongodbConnString variable then we pass it to our mongoose object during the call to the connect function. We added two listeners on the mongoose object during “error” and “open”

If things go well then you should be able to see the following messages being displayed in your terminal.

[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
Server app listening on port 3000
Successfully connected to MongoDB Atlas database.

Save credential in .env config files

As you can see from the index.js above, we have hardcoded our username, password, cluster name, and database into our connection string variable. When we commit our code into our GitHub repository then everybody will know this sensitive information.

To fix this issue we can use a package called dotenv that will read our configuration file named .env and put it in the process.env runtime variable. Note that this .env file is not committed to our repository as it is part of the files in our .gitignore that we created earlier.

First, we install the dotenv npm package by executing this in a terminal.

npm install --save dotenv

Then, we populate our .env file with the following entry

USER_NAME=testuser
PASSWORD=TestPassword!
CLUSTER_NAME=cluster0
DB_NAME=keypadsdb

Afterwhich, we add the following in our index.js file. Using template literals, we resolved the connection string and replace the values coming from our .env file by using the process.env.<VARIABLE_NAME>.

const dotenv = require("dotenv")
//setup dotenv
dotenv.config()

//setup mongoose
const mongodbConnString = `mongodb+srv://${process.env.USER_NAME}:${process.env.PASSWORD}@${process.env.CLUSTER_NAME}.attzkit.mongodb.net/${process.env.DB_NAME}`

If no error is encountered then we should be able to see the message “Successfully connected to MongoDB Atlas database.” to be displayed in our console log.

The following is our index.js at this point.

const express = require("express")
const bodyParser = require("body-parser")
const mongoose = require("mongoose")
const dotenv = require("dotenv")

const PORT = process.env.PORT || 3000

const app = express()

//setup dotenv
dotenv.config()

//middleware functions
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

//setup mongoose
const mongodbConnString = `mongodb+srv://${process.env.USER_NAME}:${process.env.PASSWORD}@${process.env.CLUSTER_NAME}.attzkit.mongodb.net/${process.env.DB_NAME}`


mongoose.connect(mongodbConnString)

mongoose.connection.on("error", function(error) {
  console.log(error)
})

mongoose.connection.on("open", function() {
  console.log("Successfully connected to MongoDB Atlas database.")
})

app.listen(PORT, function () {
  console.log(`Server app listening on port ${PORT}`)
})

Create Mongoose Database Model

We need to create a model to represent our record in our MongoDB Atlas database. To do this let’s create a directory to hold our model object.

From Visual Studio Code, we can create a new directory and name it “models

Visual Studio Code Models Directory

Inside our models folder, let’s create a file called keycode.js

const mongoose = require("mongoose")

const KeyCodeSchema = new mongoose.Schema({
  keyCode: {
    type: String,
    unique: true,
    required: true
  },
  active: {
    type: Boolean
  },
  description: {
    type: String
  }
}, { timestamps: true })

KeyCodeSchema.index({keyCode: 1}, {unique: true})

module.exports = mongoose.model("KeyCode", KeyCodeSchema)

We create a mongoose.schema and initialize it with several properties namely:

  • keyCode – will represent the keycode that is going to be saved in our database. The type is a string and has a unique property.
  • active – will represent if this variable is still active or not. Type is a boolean variable.
  • description – will represent the description for this keycode or whoever owns this keycode. The type is a string and does not need to be required.

We are creating a mongoose.model from this schema and exporting it. An instance of a model is called a document and it is responsible for creating and reading documents from the underlying MongoDB database.

Creating REST API routes

Now we will begin creating specific routes for our application and how we are going to respond to those requests.

These are the routes that we are going to build:

HTTP METHODPATHDESCRIPTION
GET/api/keycodes/:keycodeGet specific Key Code record in the database
GET/api/keycodesGet all key codes records in the database
POST/api/keycodesAdd new key code record
PUT/api/keycodes/:keycodeUpdate key code record
DELETE/api/keycodes/:keycodeDelete specific key code record

The syntax for routes follows the following format below. The callback functions can be separated into different entities that we can call our Controller object.

// Syntax
router.method('<path>', callbackFunction)

// Example
router.get("/", function (req, res) {
  res.json({message: "Hello world!"});
});

To do this, let us create a directory called “routes” in Visual Studio Code. For better practice, we are going to create another subdirectory called “keycodes” inside it. Our app is only serving keycodes information for now but in the future will have others so it’s a good idea to separate it by functionality.

Create a file called keycode.js inside the router/keycodes folder and paste the following code. We have added all routes from our table above but it is not doing anything yet.


const express = require("express")

const router = express.Router()

/* Router functions here */
router.get('/api', (req, res) => {
    res.send('hello REST API')
})

//Get specific Key Code record in the database
router.get('/api/keycodes/:keycode',(req, res) => {

})

//Get all key codes records in the database
router.get('/api/keycodes',(req, res) => {

})

//New Key Code Route
router.post('/api/keycodes/newKeyCode',(req, res) => {

})

//Update key code record
router.put('/api/keycodes/:keycode',(req, res) => {

})

//Delete specific key code record
router.delete('/api/keycodes/:keycode',(req, res) => {

})

module.exports = router

To explain the code above, let’s take one route and explain it a little bit.

const express = require("express")

const router = express.Router()

/* Router functions here */
router.get('/api', (req, res) => {
    res.send('hello REST API')
})
  • We import the express object and then create an instance of express.Router()
  • We create a “route” to an HTTP method with GET and have a path of ‘/api’. A callback function with a request and response object is passed in to handle the HTTP request and HTTP response processing.
  • We then write a plain text with a message ‘hello REST API’
  • We finished by exporting this router object

In order to use this router object then we need to tell our Express Server to use this. To do that we should edit our index.js and add the following line of code. This tells our express server to use the middleware functions and add the routing functionality that we have added.

//middleware function
app.use(require("./routes/keycodes/keycode"))

Our index.js should now look like this:

const express = require("express")
const bodyParser = require("body-parser")
const mongoose = require("mongoose")
const dotenv = require("dotenv")

const PORT = process.env.PORT || 3000

const app = express()

//setup dotenv
dotenv.config()

//middleware functions
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

//setup mongoose
const mongodbConnString = `mongodb+srv://${process.env.USER_NAME}:${process.env.PASSWORD}@${process.env.CLUSTER_NAME}.attzkit.mongodb.net/${process.env.DB_NAME}`


mongoose.connect(mongodbConnString)

mongoose.connection.on("error", function(error) {
  console.log(error)
})

mongoose.connection.on("open", function() {
  console.log("Successfully connected to MongoDB Atlas database.")
})

//middleware function
app.use(require("./routes/keycodes/keycode"))

app.listen(PORT, function () {
  console.log(`Server app listening on port ${PORT}`)
})

Now we are all set, to test our routes, open a browser and input the following url http://localhost:3000/api. You should be able to see the following message printed.

Node.js REST API Hello World

Create Controller Objects

Controllers are basically callback functions that mostly handle the interface to our database using the Model objects that we created (e.g Schema) and the business logic related to it also like additional validation. As we add more routes to our application then it becomes important that we separate the logic into a separate module rather than putting everything in our routes object.

Let’s create the controller for our application, in Visual Studio Code create a directory called “controllers” in our root project and add a new file called “keycode.js“. This will serve as the controller of our keypads/keycode application.

// Import our keyCode schema
const KeyCodeModel = require("../models/keycode");

module.exports = {
  //call back function to create our new key code
  createNewKeyCode: function (keyCode, active, description, callback) {
    // More code to follow here
  },

  // Get specific Key Code record
  getKeyCode: function (keyCode, callback) {
    // More code to follow here
  },

  // Get all key codes records
  getAllKeyCodes: function (callback) {
    // More code to follow here
  },

  //Update key code record
  updateKeyCodeRecord: function (keyCode, active, description, callback) {
    // More code to follow here
  },

  //Delete key code record
  deleteKeyCodeRecord: function (keyCode, callback) {
    // More code to follow here
  },
};
  • We import our schema object
  • We export several functions that will handle the business logic of our interaction with our MongoDB Atlas database.

We will continue to build on this controller object in the next section.

Perform CRUD(Create, Retrieve, Update, Delete) Operation

Add Key Code Record

We start by adding key code records to our database. To do that open your controller\keycode.js file and add the following lines of code in the createNewKeyCode function.

// Import our keyCode schema
const KeyCodeModel = require("../models/keycode");

module.exports = {
  //call back function to create our new key code
  createNewKeyCode: function (keyCode, active, description, callback) {
    const newKeyCode = new KeyCodeModel({
      keyCode: keyCode,
      active: active,
      description: description,
    });
    newKeyCode.save(function (error, newKeyCode) {
      if (error) {
        callback({ success: false, message: "Unable to create new key code!" });
      } else {
        console.log(newKeyCode);
        callback({
          success: true,
          message: "Successfully created new key code records",
        });
      }
    });
  },
};
  • We import our schema from the models directory
  • We export a function called createNewKeyCode. This function is expecting the following parameters keyCode, active, description, callback. They are to be supplied by the calling client.
  • We create a sample KeyCodeModel from our schema and populate it with the values that we passed in and then call the save function.
  • If an error is encountered then the callback is called and passing success=false else if it was successful then success=true.

In our /routes/keycode.js then we need to add the following lines of code.

const keyCodeController = require("../../controllers/keycode");

//New Key Code Route
router.post("/api/keycodes/newKeyCode", (req, res) => {
  if (!req.body.keyCode || !req.body.active || !req.body.description) {
    res.json({ error: true });
  } else {
    keyCodeController.createNewKeyCode(
      req.body.keyCode,
      req.body.active,
      req.body.description,
      function (result) {
        res.json(result);
      }
    );
  }
});
  • We validate if the required parameters are passed in by the client, if not then we return a JSON message with error=true.
  • We call the controller function createNewKeyCode and passed in the required parameters.

To test this API, open Postman and send in the following parameters. Verify the response message as well.

REST API Server in Node.js - Add New Key Code

Verify also that it is saved in our MongoDB Atlas database. To do that open Compass and find the keycode that we passed in.

MongoDB Compass Validate Record

If it is there then hooray! We were able to create our first API.

Get a specific Key Code record

To get a specific key code record then we need to a new function to our controllers\keycode.js. Add the following code to that file.

  // Get specific Key Code record
  getKeyCode: function (keyCode, callback) {
    KeyCodeModel.findOne({ keyCode: keyCode }, (err, record) => {
      if (err || !record) {
        callback({ success: false, message: "Unable find keycode record!" });
      } else {
        //console.log(record); -- show record on log
        callback({
          success: true,
          message: "Successfully retrieved keycode record",
        });
      }
    });
  },

Then in our routes\keycode.js, we call the function above.

//Get specific Key Code record in the database
router.get("/api/keycodes/:keyCode", (req, res) => {
  let keyCode = req.params.keyCode;
  keyCodeController.getKeyCode(keyCode, function (result) {
    res.json(result);
  });
});

We extract the keycode parameter and then call our controller object. Supply the following information in Postman to test this API.

Postman Get Key Code

Get All Key Codes Record

To get all keycodes stored in the database then we can add the following function in our keycode controller controller\keycode.js file.

    // Get all key codes records 
    getAllKeyCodes: function (callback) {
      KeyCodeModel.find({}, (err, keyCodes) => {
        if (err) {
          callback({ success: false, message: "Unable find keycode records!" });
        } else {
          callback({
            success: true,
            message: "Successfully retrieved keycode record",
            keyCodes: keyCodes
          });
        }
      });
    },

Then call this function in our routes\keycode.js.

//Get all key codes records in the database
router.get("/api/keyCodes", (req, res) => {
  keyCodeController.getAllKeyCodes(function (result) {
    res.json(result);
  });
});ode.js

To test this in Postman just follow the below steps:

Postman Get All KeyCodes

Delete Key Code Record

Let us start developing logic on how to delete Key Code records in our MongoDB Atlas database.

Edit your controller\keycode.js and put the following code.

  //Delete key code record
  deleteKeyCodeRecord: function (keyCode, callback) {
    KeyCodeModel.findOne({ keyCode: keyCode }, (err, record) => {
      if (err || !record) {
        callback({
          success: false,
          message: "Unexpected error encountered or keycode record not found while deleting keycode!",
        });
      } else {
        record.remove(function (error) {
          if (error) {
            callback({
              success: false,
              message: "Failed to delete keycode record!",
            });
          } else {
            callback({
              success: true,
              message: "Successfully deleted keycode record!",
            });
          }
        });
      }
    });
  }
  • The controller will query our MongoDB Atlas database and find a key code that is matching our pass parameter.
  • If nothing is found then it just returns a message that “Unexpected error encountered or keycode record not found while deleting keycode!”
  • If a record is found then we execute a delete of the record by calling remove on our model.
  • If something goes wrong during deletion then an error message is sent back to the calling client else the success message is called.

Let us now edit our routes\keycode.js to use our new controller logic. Update your file and put the following entry.

//Delete specific key code record
router.delete("/api/keycodes", (req, res) => {
  if (!req.body.keyCode) {
    res.json({ error: true });
  } else {
    keyCodeController.deleteKeyCodeRecord(
      req.body.keyCode,
      function (result) {
        res.json(result);
      }
    );
  }
});

First, we extract the key code from the request body and then call the deleteKeyCodeRecord from our keyCodeController.

Postman Delete Key Code

Verify that it is deleted in our MongoDB using Compass.

MongoDB Verify Successful Delete

Final Code

This is the final code for each of our modules.

controller\keycode.js:

// Import our keyCode schema
const KeyCodeModel = require("../models/keycode");

module.exports = {
  //call back function to create our new key code
  createNewKeyCode: function (keyCode, active, description, callback) {
    KeyCodeModel.findOne({ keyCode: keyCode }, (err, record) => {
      // Key code is not in the database
      if (!record) {
        const newKeyCode = new KeyCodeModel({
          keyCode: keyCode,
          active: active,
          description: description,
        });
        newKeyCode.save(function (error, newKeyCode) {
          if (error) {
            callback({
              success: false,
              message: "Unable to create new key code!",
            });
          } else {
            console.log(newKeyCode);
            callback({
              success: true,
              message: "Successfully created new key code records",
            });
          }
        });
      } else {
        if (err) {
          callback({
            success: false,
            message: "Unexpected error when querying for new key code!",
          });
        }
        callback({
          success: false,
          message: `${keyCode} already exists in database`,
        });
      }
    });
  },

  // Get specific Key Code record
  getKeyCode: function (keyCode, callback) {
    KeyCodeModel.findOne({ keyCode: keyCode }, (err, record) => {
      if (err || !record) {
        callback({ success: false, message: "Unable find keycode record!" });
      } else {
        //console.log(record); -- show record on log
        callback({
          success: true,
          message: "Successfully retrieved keycode record",
        });
      }
    });
  },

  // Get all key codes records
  getAllKeyCodes: function (callback) {
    KeyCodeModel.find({}, (err, keyCodes) => {
      if (err) {
        callback({ success: false, message: "Unable find keycode records!" });
      } else {
        callback({
          success: true,
          message: "Successfully retrieved keycode records",
          keyCodes: keyCodes,
        });
      }
    });
  },

  //Update key code record
  updateKeyCodeRecord: function (keyCode, active, description, callback) {
    KeyCodeModel.findOne({ keyCode: keyCode }, (err, record) => {
      if (err || !record) {
        callback({
          success: false,
          message:
            "Unexpected error encountered or keycode record not found while updating keycode record!",
        });
      } else {
        record.active = active;
        record.description = description;

        record.save(function (error) {
          if (error) {
            callback({
              success: false,
              message: "Failed to update keycode record!",
            });
          } else {
            callback({
              success: true,
              message: "Successfully updated record!",
            });
          }
        });
      }
    });
  },

  //Delete key code record
  deleteKeyCodeRecord: function (keyCode, callback) {
    KeyCodeModel.findOne({ keyCode: keyCode }, (err, record) => {
      if (err || !record) {
        callback({
          success: false,
          message:
            "Unexpected error encountered or keycode record not found while deleting keycode!",
        });
      } else {
        record.remove(function (error) {
          if (error) {
            callback({
              success: false,
              message: "Failed to delete keycode record!",
            });
          } else {
            callback({
              success: true,
              message: "Successfully deleted keycode record!",
            });
          }
        });
      }
    });
  },
};

routes\keycode.js:

const express = require("express");

const router = express.Router();

const keyCodeController = require("../../controllers/keycode");

/* Router functions here */
router.get("/api", (req, res) => {
  res.send("hello REST API");
});

//Get specific Key Code record in the database
router.get("/api/keycodes/:keyCode", (req, res) => {
  let keyCode = req.params.keyCode;
  keyCodeController.getKeyCode(keyCode, function (result) {
    res.json(result);
  });
});

//Get all key codes records in the database
router.get("/api/keyCodes", (req, res) => {
  keyCodeController.getAllKeyCodes(function (result) {
    res.json(result);
  });
});

//New Key Code Route
router.post("/api/keycodes/newKeyCode", (req, res) => {
  if (!req.body.keyCode || !req.body.active || !req.body.description) {
    res.json({ error: true });
  } else {
    keyCodeController.createNewKeyCode(
      req.body.keyCode,
      req.body.active,
      req.body.description,
      function (result) {
        res.json(result);
      }
    );
  }
});

//Update key code record
router.put("/api/keycodes/", (req, res) => {
  console.log(req.body);
  if (!req.body.keyCode || !req.body.active || !req.body.description) {
    res.json({ error: true });
  } else {
    keyCodeController.updateKeyCodeRecord(
      req.body.keyCode,
      req.body.active,
      req.body.description,
      function (result) {
        res.json(result);
      }
    );
  }
});

//Delete specific key code record
router.delete("/api/keycodes", (req, res) => {
  if (!req.body.keyCode) {
    res.json({ error: true });
  } else {
    keyCodeController.deleteKeyCodeRecord(
      req.body.keyCode,
      function (result) {
        res.json(result);
      }
    );
  }
});

module.exports = router;

models\keycode.js:

const mongoose = require("mongoose")

const KeyCodeSchema = new mongoose.Schema({
  keyCode: {
    type: String,
    unique: true,
    required: true
  },
  active: {
    type: Boolean
  },
  description: {
    type: String,
    required: true
  }
}, { timestamps: true })

KeyCodeSchema.index({keyCode: 1}, {unique: true})

module.exports = mongoose.model("KeyCode", KeyCodeSchema)

index.js:

const express = require("express")
const bodyParser = require("body-parser")
const mongoose = require("mongoose")
const dotenv = require("dotenv")

const PORT = process.env.PORT || 3000

const app = express()

//setup dotenv
dotenv.config()

//middleware functions
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

//setup mongoose
const mongodbConnString = `mongodb+srv://${process.env.USER_NAME}:${process.env.PASSWORD}@${process.env.CLUSTER_NAME}.attzkit.mongodb.net/${process.env.DB_NAME}`


mongoose.connect(mongodbConnString)

mongoose.connection.on("error", function(error) {
  console.log(error)
})

mongoose.connection.on("open", function() {
  console.log("Successfully connected to MongoDB Atlas database.")
})

//middleware function
app.use(require("./routes/keycodes/keycode"))

app.listen(PORT, function () {
  console.log(`Server app listening on port ${PORT}`)
})

Wrap Up

We have discussed how to create our own REST API Server using Node.js, Express, and MongoDB Atlas in this post.

We will be using the same application in the future Internet of Things (IOT) projects.

Happy Exploring!

If you like my post then please consider sharing this. Thanks!

4 responses to “Build REST API Using Node.js, Express and MongoDB”

  1. ESP32 Keypad Database Security System – Design – donskytech.com

    […] Part 2 – ESP32 Keypad Database Security System – Build REST API Using Node.js, Express a… […]

  2. ESP32 Keypad Database Security System Code – donskytech.com

    […] Part 2 – ESP32 Keypad Database Security System – Build REST API Using Node.js, Express and Mongo… […]

  3. Keypad with a Database Security System using Raspberry Pi

    […] you would like to follow along on how I did this project from scratch then you can see this in my how to build rest API using node.js, express and MongoDB […]

  4. How to serve static files in Node.js and Express server?

    […] Content: Build REST API Using Node.js, Express, and MongoDBUsing Node.js and React to display a chart of real-time sensor […]

Leave a Reply

Your email address will not be published. Required fields are marked *