In the root folder, let’s create a new server.js file:
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(bodyParser.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// simple route
app.get("/", (req, res) => {
res.json({ message: "Welcome to bezkoder application." });
});
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
What we’be just done in the code above:
– import express, body-parser and cors modules:
Express is for building the Rest apis
– create an Express app, then add body-parser and cors middlewares using app.use() method. Notice that we set origin: http://localhost:8081.
– define a GET route which is simple for test.
– listen on port 8080 for incoming requests.
Configure MongoDB database
In the app folder, create config folder for configuration.
Then create a new db.config.js file that contains parameters for setting up MongoDB later:
These Mongoose Models represents users & roles collections in MongoDB database.
User object will have a roles array that contains ids in roles collection as reference.
After initializing Mongoose, we don’t need to write CRUD functions because Mongoose supports all of them:
find User by username: User.findOne({ username: … })
These functions will be used in our Controllers and Middlewares.
Initialize Mongoose
Now create app/models/index.js with content like this:
To verify a Signup action, we need 2 functions:
– check duplications for username and email
– check if roles in the request is legal or not
middlewares/verifySignUp.js
const db = require("../models");
const ROLES = db.ROLES;
const User = db.user;
checkDuplicateUsernameOrEmail = (req, res, next) => {
// Username
User.findOne({
username: req.body.username
}).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (user) {
res.status(400).send({ message: "Failed! Username is already in use!" });
return;
}
// Email
User.findOne({
email: req.body.email
}).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (user) {
res.status(400).send({ message: "Failed! Email is already in use!" });
return;
}
next();
});
});
};
checkRolesExisted = (req, res, next) => {
if (req.body.roles) {
for (let i = 0; i < req.body.roles.length; i++) {
if (!ROLES.includes(req.body.roles[i])) {
res.status(400).send({
message: `Failed! Role ${req.body.roles[i]} does not exist!`
});
return;
}
}
}
next();
};
const verifySignUp = {
checkDuplicateUsernameOrEmail,
checkRolesExisted
};
module.exports = verifySignUp;
To process Authentication & Authorization, we create following functions:
- check if token is provided, legal or not. We get token from x-access-token of HTTP headers, then use jsonwebtoken's verify() function
- check if roles of the user contains required role or not
There are 4 functions:
– /api/test/all for public access
– /api/test/user for loggedin users (any role)
– /api/test/mod for moderator users
– /api/test/admin for admin users
Let's combine middlewares with controller functions in the next section.
Define Routes
When a client sends request for an endpoint using HTTP request (GET, POST, PUT, DELETE), we need to determine how the server will response by setting up the routes.
We can separate our routes into 2 part: for Authentication and for Authorization (accessing protected resources).
...
// routes
require('./app/routes/auth.routes')(app);
require('./app/routes/user.routes')(app);
// set port, listen for requests
...
Run & Test with Results
Run Node.js application with command: node server.js.
The console shows:
Server is running on port 8080.
Successfully connect to MongoDB.
added 'user' to roles collection
added 'admin' to roles collection
added 'moderator' to roles collection
Let's check roles collection in MongoDB database:
Register some users with /signup API:
admin with admin role
modera with moderator and user roles
bezkoder with user role
users collection after signup could look like this.
Access public resource: GET /api/test/all
Access protected resource: GET /api/test/user
Login an account (with wrong password): POST /api/auth/signin