Create web interface for NTP server – index.js & index.html (Part 3)

Posted by:

|

On:

|

In a typical Express application, the index.js file under the route ‘/' serves as the primary router for handling requests directed at the root URL (/).

Usage and Functions of index.js

  1. Route Definition:
    • The primary purpose of index.js is to define the routes that the application will respond to for the root URL (/) and any sub-paths. This includes specifying HTTP methods (GET, POST, etc.) and defining what actions to take when those routes are accessed. A new router instance is created using express.Router(), allowing you to define multiple routes.
  2. Route Handlers:
    • Each route handler (e.g., for /login and /logout) defines what happens when a request is made to that path.
    • Each route handler contains a callback function that processes any necessary logic (like querying a database), rendering a view, performing other actions and sends a response back to the client.
  3. Modular Structure:
    • By placing route definitions in a separate file, index.js helps maintain a modular structure. This separation makes the codebase easier to manage, especially as the application grows and more routes are added.
  4. Middleware Inclusion:
    • The file can include middleware functions that are specific to the routes it defines. Middleware can be used for tasks like authentication, logging, or data validation before the main route handler is executed.
  5. Exporting the Router:
    • At the end of the file, the router instance is exported making it available for use in other parts of the application.

In my index.js, I will add the some route handlers.

(A) Module Imports:

var express = require('express');  // Import the Express module
var router = express.Router();     // Create a new router instance
var database = require('../database'); // Import database module database.js under directory apps
var path = require('path');        // Import the built-in path module

(B) When a HTTP GET request is made to path /login, /config, /account, /dashboard, the matched route outputs the full path to the express console for debugging purposes [console.log] and sends the specified HTML file as the response [response.sendFile]. All html files are placed in the directory ‘public’.

router.get('/login', function(request, response, next) {
    console.log(path.join(__dirname, '../public', 'index.html'));  //
    response.sendFile(path.join(__dirname, '../public', 'index.html'));
});

router.get('/config', function(request, response, next) {
    console.log(path.join(__dirname, '../public', 'config.html'));
    response.sendFile(path.join(__dirname, '../public', 'config.html'));
});

router.get('/account', function(request, response, next) {
    console.log(path.join(__dirname, '../public', 'account.html'));
    response.sendFile(path.join(__dirname, '../public', 'account.html'));	
});	

(C) When a HTTP GET request is made to path /logout, this route will be executed. The request in the function contains details about the request, including session data. The line “”request.session.destroy()” removes the session data associated with the user. It also effectively logs the user out by clearing any stored information in the session, such as user credentials or preferences and delete the session cookie from the client. After destroying the session, “response.redirect(“/login”)” sends a redirect response to the client, instructing the browser to navigate to the /login page and allows users to return to the login page for re-authentication.

router.get('/logout', function(request, response, next) {
    request.session.destroy();
    response.redirect("/login");
});

(D) When a HTTP POST request is made to path /login, this route will be executed to show the login page. The coding is not difficult to understand. Please note that I add many console.log for debugging. There is inline html codes and MySQL query as well.

router.post('/login', function(request, response, next) {
    var user_username = request.body.user_username;
    var user_password = request.body.user_password;

    // Helper function to render error messages
    function renderError(message) {
        response.send(`
        <!DOCTYPE html>
        <html lang="en">
          <head>
            <title>Login Form</title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <link rel="stylesheet" href="../public/css/bootstrap.min.css"> 
          </head>
          <body>
            <div class="container">
                <center>
                    <h3 class="text-danger">${message}</h3>
                    <a href="/login">Try again</a>
                </center>
            </div>
          </body>
        </html>
        `);
    }

    var query = `
    SELECT * FROM ACCOUNTS
    WHERE username = "${user_username}"
    `;

    database.query(query, function(error, data) {
        console.log(`log001: `, data); // Prepend "log101:" before logging data
	    console.log(`log002: `, user_password);
		console.log(`log003: `, data.length);
        if (data.length > 0) {
            for (var count = 0; count < data.length; count++) {
	     		console.log(`log004: `, data[count].password);
                if (data[count].password === user_password) {
                    request.session.user_id = data[count].user_id; // Set the session user_id
                    console.log("match");
                    return response.redirect('/dashboard'); // Redirect to dash board
                } else {
                    console.log("Incorrect Password");
                    return renderError("Incorrect Password!"); // Use the helper function
                 }
            }
        } else {
            console.log("Incorrect User Name");
            return renderError("Incorrect User Name!"); // Use the helper function
        }
    });
});

Create following index.html and placed under the directory “public”

<!doctype html>
<html lang="en">
    <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- CSS -->
	<link rel="stylesheet" href="css/bootstrap.min.css"> 
	<link rel="stylesheet" href="css/all.min.css"> 
	<link rel="stylesheet" href="css/material.min.css">  
	<link rel="stylesheet" href="css/style.css">		
		
        <title>Login</title>
    </head>
    <body>
	
	 <div class="container"> <!-- class is part of boolstrap class -->
            <h3 class="mt-5 mb-5 text-center text-primary"><b></b></h3>
            <div class="row mt-5">
                <div class="col-md-3">&nbsp;</div>
                <div class="col-md-6">

                  <div class="card">
		     <div class="mdl-card__title custom-color-background mdl-color-text--white relative">
                        <h2 class="mdl-card__title-text">Login Here</h2>
                        </div>
                        <div class="card-body">
			<form id="loginForm" method="POST" action="/login">
                          <div class="mb-3">
                             <label>User Name</label>
                             <input type="email" required placeholder="Email" id="user_username" name="user_username" class="form-control" />
                          </div>
                          <div class="mb-3">
                             <label>Password</label>
                             <input type="password" required placeholder="Password" id="user_password" name="user_password" class="form-control" />
                          </div>
                          <div class="mb-3">
				<button type="submit" id="login-button" class="mdl-button mdl-js-button mdl-button--raised custom-color-button mdl-color-text--white">Submit</button>
                            </div>							
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div> 
    </body>
</html>

Create directory “css” under “public” and place following css files downloaded from internet.

bootstrap.min.css,
all.min.css,
material.min.css,
style.css

Create the database and table for login:

Check if database “ntpserver” exists. Create one if this does not exist.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| ntpserver          |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.05 sec)

Use database “ntpserver” :

mysql> use ntpserver;

Create table “accounts” with following fields:

ACCOUNTS {
    int id PK
    varchar username
    varchar password
    int role   //0:normal user, 1:supervisor
}
CREATE TABLE ACCOUNTS (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL,
role INT NOT NULL
);

Show table structure:

mysql> DESCRIBE ACCOUNTS;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int         | NO   | PRI | NULL    | auto_increment |
| username | varchar(20) | NO   |     | NULL    |                |
| password | varchar(20) | NO   |     | NULL    |                |
| role     | int         | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+

Insert two records:

mysql> INSERT INTO ACCOUNTS (username, password, role) VALUES ('FelixTang', '888888', 1), ('StanLee', '123456', 0);

Show table data:

mysql> select * from ACCOUNTS;
+----+-----------+----------+------+
| id | username  | password | role |
+----+-----------+----------+------+
|  1 | FelixTang | 888888   |    1 |
|  2 | StanLee   | 123456   |    0 |
+----+-----------+----------+------+
2 rows in set (0.00 sec)

Now, everything is ready for a login webpage. Open the terminal and run the app by “npm start”. You can get the following message and enter the debug window of node.

> apps@0.0.0 start
> node ./bin/www

MySQL Database is connected Successfully as id 43

Open a web browser. Type http://192.168.2.180:3000 and you will see the responsive login page.

Up to now, there are still three HTTP get routes left for development. In next blog, I will make a dashboard page to show the system clock, GPS data, NTP status and time sync to my device. I also want to study and learn how to make a Hypertext transfer protocol secure (HTTPS) , which is the primary protocol used to send data between a web browser and a website. HTTPS is the secure version of HTTP and is encrypted in order to increase security of data transfer.

Posted by

in