Today we use Node.js + Express + Docker + mysql + JWT to make a simple version of the user management restful API, which has basic user registration, user login and access to user information functions. Express routing, Express-Validator as form validator, mysql container running with Docker, password encryption, JWT generating user tokens, etc. So let’s do it

The technology used

  • nodejs
  • express
  • mysql
  • jwt
  • docker

Step 1: Create the project directory

mkdir nodejs-auth-mysql-rest-api
cd nodejs-auth-mysql-rest-api
npm init -y
Copy the code

Install dependencies

npm install express express-validator mysql body-parser jsonwebtoken bcryptjs cors --save
Copy the code
  • express
    • Start the basic HTTP service
  • express-validator
    • Used to verify that the form is valid
  • mysql
    • Connect to mysql database, store data, query data
  • body-parser
    • Parse the data in the BODY of the POST request
  • jsonwebtoken
    • Tokens used to generate JWT
  • bcryptjs
    • Encrypts the user registration password
  • cors
    • Allows cross-domain request access

Step 2: Create the database and tables

Here I don’t need to install mysql database on the computer, we use docker way to run a mysql container on the machine, need to be familiar with some basic Docker use.

Create a data folder

mkdir data
Copy the code

Create mysql container

docker run -v "$PWD/data":/var/lib/mysql --name dev-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
Copy the code
  • docker run
    • Run the Docker container
  • -v “$PWD/data”:/var/lib/mysql
    • Map the data storage directory in the container to the directory on the host to avoid data loss caused by container shutdown
  • –name dev-mysql
    • Container name
  • -p 3306:3306
    • Map port 3306 in the container to the host. I do this for convenience. Normally, I don’t do this because it’s dangerous.
  • -e MYSQL_ROOT_PASSWORD=123456
    • Set the root password to 123456
  • -d
    • Run the container in the background
  • Mysql: 5.7
    • Mirror and mirrored versions of the container

View the running container

docker ps
Copy the code
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES B1808287e831 mysql:5.7 "docker-entryPoint.s..." 15 seconds ago Up 12 seconds 0.0.0.0:3306->3306/ TCP, 33060/ TCP dev-mysqlCopy the code

Stop the container

docker stop b1808287e831
Copy the code

View all containers

docker ps -a
Copy the code
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES B1808287e831 mysql:5.7 "docker-entryPoint.s..." 15 minutes ago Exited (0) 10 seconds ago dev-mysqlCopy the code

Start the container

docker start b1808287e831
Copy the code

Create databases and tables

Database.sql is created in the directory and the user creates the data table

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `email` varchar(50) NOT NULL,
  `password` varchar(200) NOT NULL.PRIMARY KEY (id),
  UNIQUE KEY email (email)
 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
Copy the code

Execute the following command to create the database and tables within the container

# the SQL file copy into container docker cp $PWD/database. The SQL b1808287e831: / database SQL # into the container docker exec - it b1808287e831 bin/bash # Mysql -u root -p mysql -u root -p mysql Create database 'node-app'; Use 'node-app'; SQL > alter table source /database.sql; # exit mysql; # exit the container;Copy the code

Step 3: Connect to the database in NodeJS

Create dbConnection. Js

const mysql = require('mysql');

const conn = mysql.createConnection({
  host: '127.0.0.1'.user: 'root'.password: '123456'.database: 'node-app'
}); 
 
conn.connect(function(err) {
  if (err) throw err;
  console.log('Database connection successful');
});

module.exports = conn;
Copy the code

Test whether the connection is successful

node dbConnection.js
The database connection is successful
Copy the code

Step 4: Create the Express service

Create a server. Js

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const indexRouter = require('./router.js');

const app = express();

app.use(express.json());

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({
    extended: true
}));

app.use(cors());

app.use('/api', indexRouter);

// Processing error
app.use((err, req, res, next) = > {
    // console.log(err);
    err.statusCode = err.statusCode || 500;
    err.message = err.message || "Internal Server Error";
    res.status(err.statusCode).json({
      message: err.message,
    });
});

app.listen(3000.() = > console.log('Service started successfully: http://localhost:3000'));
Copy the code

Step 5: Create routes and validators

Create validation.js file

const { check } = require('express-validator');

exports.signupValidation = [
  check('name'.'Please enter a user name').not().isEmpty(),
  check('email'.'Please enter a valid email address').isEmail(),
  check('password'.'Password must be at least six characters.').isLength({ min: 6})]exports.loginValidation = [
  check('email'.'Please enter a valid email address').isEmail(),
  check('password'.'Password must be at least six characters.').isLength({ min: 6})]Copy the code

Create the router.js file

const express = require('express');
const router = express.Router();
const db = require('./dbConnection');
const { signupValidation, loginValidation } = require('./validation');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

const JWT_SECRET = 'my-secret'

router.post('/register', signupValidation, (req, res, next) = > {
  db.query(
    `SELECT * FROM users WHERE LOWER(email) = LOWER(${db.escape(
      req.body.email
    )}); `.(err, result) = > {
      if (result.length) {
        return res.status(409).send({
          msg: 'Mailbox registered'
        });
      } else {
        // If you can register,
        bcrypt.hash(req.body.password, 10.(err, hash) = > {
          if (err) {
            return res.status(500).send({
              msg: err
            });
          } else {
            // The password is encrypted and stored in the database
            db.query(
              `INSERT INTO users (name, email, password) VALUES ('${req.body.name}', ${db.escape(
                req.body.email
              )}.${db.escape(hash)}) `.(err, result) = > {
                if (err) {
                  return res.status(400).send({
                    msg: err
                  });
                }
                return res.status(201).send({
                  msg: 'User registered successfully'}); }); }}); }}); }); router.post('/login', loginValidation, (req, res, next) = > {
  db.query(
    `SELECT * FROM users WHERE email = ${db.escape(req.body.email)}; `.(err, result) = > {
      // The user does not exist
      if (err) {
        // throw err;
        return res.status(400).send({
          msg: err
        });
      }
      if(! result.length) {return res.status(401).send({
          msg: 'Wrong username or password'
        });
      }
      // Check that the password is correct
      bcrypt.compare(
        req.body.password,
        result[0] ['password'].(bErr, bResult) = > {
          // The password is incorrect
          if (bErr) {
            // throw bErr;
            return res.status(401).send({
              msg: 'Wrong username or password'
            });
          }
          if (bResult) {
            const token = jwt.sign({ id: result[0].id }, JWT_SECRET, { expiresIn: '1h' });
            db.query(
              `UPDATE users SET last_login = now() WHERE id = '${result[0].id}'`
            );
            return res.status(200).send({
              msg: 'Successful landing',
              token,
              user: result[0]}); }return res.status(401).send({
            msg: 'Wrong username or password'}); }); }); }); router.post('/get-user', signupValidation, (req, res, next) = > {
  if(! req.headers.authorization || ! req.headers.authorization.startsWith('Bearer') | |! req.headers.authorization.split(' ') [1]) {return res.status(422).json({
      message: "Lack of Token"}); }const theToken = req.headers.authorization.split(' ') [1];
  const decoded = jwt.verify(theToken, JWT_SECRET);
  db.query('SELECT * FROM users where id=? ', decoded.id, function (error, results, fields) {
    if (error) throw error;
    return res.send({ error: false.data: results[0].message: 'Request successful' });
  });
});

module.exports = router;
Copy the code

Step 6: Run the Express service

Install nodemon

npm install nodemon --save-dev
Copy the code

Modify the package. The json

"scripts": {
    "start": "nodemon server.js"
},
Copy the code

Run the project

npm start
Service started successfully: http://localhost:3000
The database connection is successful
Copy the code

Step 7: Use the Postman test

Registered users

POST - http://localhost:3000/api/register
Copy the code

Check whether there is data in the database

landing

POST - http://localhost:3000/api/login
Copy the code

Obtaining User information

POST - http://localhost:3000/api/get-user
Copy the code

The source code

Github:github.com/cmdfas/node…