mirror of https://github.com/Aelita4/sshmon.git
				
				
				
			Create login/register form
This commit is contained in:
		
							parent
							
								
									78b6c6b687
								
							
						
					
					
						commit
						0c63934a8a
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -10,14 +10,22 @@
 | 
			
		|||
  "author": "",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "bcrypt": "^5.0.1",
 | 
			
		||||
    "cookie-parser": "^1.4.6",
 | 
			
		||||
    "ejs": "^3.1.8",
 | 
			
		||||
    "eslint": "^8.22.0",
 | 
			
		||||
    "express": "^4.18.1",
 | 
			
		||||
    "express-session": "^1.17.3",
 | 
			
		||||
    "mysql": "^2.18.1",
 | 
			
		||||
    "ping": "^0.4.2",
 | 
			
		||||
    "typescript": "^4.7.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/bcrypt": "^5.0.0",
 | 
			
		||||
    "@types/cookie-parser": "^1.4.3",
 | 
			
		||||
    "@types/express": "^4.17.13",
 | 
			
		||||
    "@types/express-session": "^1.17.5",
 | 
			
		||||
    "@types/mysql": "^2.15.21",
 | 
			
		||||
    "@types/node": "^18.7.6",
 | 
			
		||||
    "@types/ping": "^0.4.1"
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								src/index.ts
								
								
								
								
							
							
						
						
									
										42
									
								
								src/index.ts
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,10 @@
 | 
			
		|||
import express, { Request, Response } from 'express';
 | 
			
		||||
import * as Ping from 'ping';
 | 
			
		||||
import { existsSync, readdirSync, writeFileSync, readFileSync } from 'fs';
 | 
			
		||||
import sessions from "express-session"
 | 
			
		||||
import cookieParser from "cookie-parser"
 | 
			
		||||
import mysql from 'mysql'
 | 
			
		||||
import bcrypt from 'bcrypt'
 | 
			
		||||
 | 
			
		||||
const ping = async (host: string) => {
 | 
			
		||||
    const result = await Ping.promise.probe(host, {
 | 
			
		||||
| 
						 | 
				
			
			@ -10,8 +14,28 @@ const ping = async (host: string) => {
 | 
			
		|||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const connection = mysql.createConnection({
 | 
			
		||||
    host: "localhost",
 | 
			
		||||
    user: "root",
 | 
			
		||||
    password: "root",
 | 
			
		||||
    database: "sshmon"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
connection.connect();
 | 
			
		||||
 | 
			
		||||
const app = express();
 | 
			
		||||
 | 
			
		||||
app.set('views', __dirname + '/../views');
 | 
			
		||||
app.set('view engine', 'ejs');
 | 
			
		||||
app.use(sessions({
 | 
			
		||||
    secret: "jkthaljkerhwejhflsbglsrbhsbfgdnbsdktiu34y5i4",
 | 
			
		||||
    saveUninitialized:true,
 | 
			
		||||
    cookie: { maxAge: 1000 * 60 * 60 * 24 },
 | 
			
		||||
    resave: false 
 | 
			
		||||
}));
 | 
			
		||||
app.use(cookieParser());
 | 
			
		||||
app.use(express.urlencoded());
 | 
			
		||||
 | 
			
		||||
const pings = new Map();
 | 
			
		||||
 | 
			
		||||
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
 | 
			
		||||
| 
						 | 
				
			
			@ -22,16 +46,24 @@ const timeoutDelay = 60000;
 | 
			
		|||
const routes = readdirSync("./routes");
 | 
			
		||||
routes.forEach(route => {
 | 
			
		||||
    const file = require(`./routes/${route}`);
 | 
			
		||||
    app.get(file.url, file.callback.bind(null, { addresses, ping, pings, timeoutDelay }))
 | 
			
		||||
    console.log(`[${file.method}] ${file.url}`);
 | 
			
		||||
    switch(file.method) {
 | 
			
		||||
        case "GET": app.get(file.url, file.callback.bind(null, { addresses, ping, pings, timeoutDelay })); break;
 | 
			
		||||
        case "POST": app.post(file.url, file.callback.bind(null, { addresses, ping, pings, timeoutDelay })); break;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.set('views', __dirname + '/../views');
 | 
			
		||||
app.set('view engine', 'ejs');
 | 
			
		||||
app.listen(8080, () => console.log('rdy'));
 | 
			
		||||
 | 
			
		||||
export interface Data {
 | 
			
		||||
interface Data {
 | 
			
		||||
    ping: Function,
 | 
			
		||||
    pings: Map<string, number>,
 | 
			
		||||
    addresses: Array<string>,
 | 
			
		||||
    timeoutDelay: number
 | 
			
		||||
};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
interface User {
 | 
			
		||||
    username: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export { connection, bcrypt, User, Data };
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import { Request, Response } from 'express';
 | 
			
		|||
import { existsSync, writeFileSync, readFileSync } from 'fs'
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/addIP/:ip",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
import { Request, Response } from 'express';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/downtime/:ip",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        const ip = req.params.ip;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
import { Request, Response } from 'express';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/login",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        res.render("pages/login.ejs", { invalid: "" });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
import { Request, Response } from 'express';
 | 
			
		||||
import { connection, bcrypt } from '../index'
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "POST",
 | 
			
		||||
    url: "/loginUser",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        
 | 
			
		||||
        connection.query("SELECT * FROM users WHERE username = ?", req.body.username, async (err, results, fields) => {
 | 
			
		||||
            if(err) throw err;
 | 
			
		||||
            if(results.length === 0) res.render("pages/login.ejs", { invalid: "baduserorpass" });
 | 
			
		||||
            else {
 | 
			
		||||
                const compare = await bcrypt.compare(req.body.password, results[0].password);
 | 
			
		||||
                if(compare) {
 | 
			
		||||
                    const session = req.session;
 | 
			
		||||
                    //@ts-ignore
 | 
			
		||||
                    session.user = {}
 | 
			
		||||
                    //@ts-ignore
 | 
			
		||||
                    session.user.username = req.body.username;
 | 
			
		||||
        
 | 
			
		||||
                    res.redirect("/");
 | 
			
		||||
                } else res.render("pages/login.ejs", { invalid: "baduserorpass" });
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
import { Request, Response } from 'express';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/logout",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        req.session.destroy(err => {
 | 
			
		||||
            res.redirect('/login');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
import { Request, Response } from 'express';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/ping/:ip",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        const ip = req.params.ip;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
import { Request, Response } from 'express';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/register",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        res.render("pages/register.ejs", { invalid: "" });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
import e, { Request, Response } from 'express';
 | 
			
		||||
import { connection, bcrypt } from '../index'
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "POST",
 | 
			
		||||
    url: "/registerUser",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        if(!req.body.username || !req.body.password) {
 | 
			
		||||
            res.render("pages/register.ejs", { invalid: "noinput" });
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(req.body.password !== req.body.password2) {
 | 
			
		||||
            res.render("pages/register.ejs", { invalid: "nomatch" });
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const encryptedPassword = await bcrypt.hash(req.body.password, 10);
 | 
			
		||||
 | 
			
		||||
        connection.query("SELECT * FROM users WHERE username = ?", req.body.username, (err, results, fields) => {
 | 
			
		||||
            if(err) throw err;
 | 
			
		||||
 | 
			
		||||
            if(results.length > 0) res.render("pages/register.ejs", { invalid: "exists" });
 | 
			
		||||
            else {
 | 
			
		||||
                connection.query("INSERT INTO users VALUES (NULL, ?, ?)", [req.body.username, encryptedPassword], (errr, resultss, fieldss) => {
 | 
			
		||||
                    if(errr) throw errr
 | 
			
		||||
                    res.render("pages/register.ejs", { invalid: "created" });
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import { Request, Response } from 'express';
 | 
			
		|||
import { existsSync, writeFileSync, readFileSync } from 'fs'
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/removeIP/:ip",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,12 +2,19 @@ import { Request, Response } from 'express';
 | 
			
		|||
import { readFileSync } from 'fs';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    method: "GET",
 | 
			
		||||
    url: "/",
 | 
			
		||||
    callback: async (data: any, req: Request, res: Response) => {
 | 
			
		||||
        data.addresses = JSON.parse(readFileSync("../data.json", {encoding:'utf8', flag:'r'}))
 | 
			
		||||
        res.render('pages/index.ejs', {
 | 
			
		||||
        data.addresses = JSON.parse(readFileSync("../data.json", {encoding:'utf8', flag:'r'}));
 | 
			
		||||
        //@ts-ignore
 | 
			
		||||
        if(!req.session.user) res.redirect("/login");
 | 
			
		||||
        else res.render('pages/index.ejs', {
 | 
			
		||||
            addresses: data.addresses,
 | 
			
		||||
            timeoutDelay: data.timeoutDelay
 | 
			
		||||
            timeoutDelay: data.timeoutDelay,
 | 
			
		||||
            //@ts-ignore
 | 
			
		||||
            loggedIn: req.session.user ? true : false,
 | 
			
		||||
            //@ts-ignore
 | 
			
		||||
            username: req.session.user?.username
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,12 +2,7 @@
 | 
			
		|||
    <head>
 | 
			
		||||
        <script>
 | 
			
		||||
        const addresses = ["<%- addresses.join(`", \"`) %>"];
 | 
			
		||||
        function clock() {
 | 
			
		||||
            
 | 
			
		||||
            const x = new Date();
 | 
			
		||||
 | 
			
		||||
            document.getElementById("time").innerHTML = String(x.getHours()).padStart(2, '0') + ":" + String(x.getMinutes()).padStart(2, '0') + ":" + String(x.getSeconds()).padStart(2, '0');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        async function addIP() {
 | 
			
		||||
            const addrElement = document.getElementById("addresses");
 | 
			
		||||
| 
						 | 
				
			
			@ -51,18 +46,11 @@
 | 
			
		|||
        setTimeout(aaa, <%= timeoutDelay %>)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        window.onload = async () => {
 | 
			
		||||
            const x = new Date();
 | 
			
		||||
            document.getElementById("time").innerHTML = String(x.getHours()).padStart(2, '0') + ":" + String(x.getMinutes()).padStart(2, '0') + ":" + String(x.getSeconds()).padStart(2, '0');
 | 
			
		||||
            
 | 
			
		||||
            const clockRefresh = 1000;
 | 
			
		||||
            aaa();
 | 
			
		||||
            setInterval(clock, clockRefresh);
 | 
			
		||||
        }
 | 
			
		||||
        window.onload = aaa;
 | 
			
		||||
    </script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <div id="time">12:00:00</div>
 | 
			
		||||
    <%- include("../partials/navbar.ejs", { activeLink: "home", username, loggedIn }) %>
 | 
			
		||||
    <div id="main"></div>
 | 
			
		||||
    <div id="eta"></div><br />
 | 
			
		||||
    <input type="text" name="ipaddr" id="ipaddr" value="">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>Login</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <%- include("../partials/navbar.ejs", { activeLink: "login", loggedIn: false }) %>
 | 
			
		||||
    <form action="/loginUser" method="post">
 | 
			
		||||
        <h2>Login</h2>
 | 
			
		||||
        <div class="input-field">
 | 
			
		||||
            <input type="text" name="username" id="username" placeholder="Enter Username">
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="input-field">
 | 
			
		||||
            <input type="password" name="password" id="password" placeholder="Enter Password">
 | 
			
		||||
        </div>
 | 
			
		||||
        <input type="submit" value="Login">
 | 
			
		||||
        <% if(invalid == "baduserorpass") { %><span style="color:red;">Bad username or password</span><% } %> 
 | 
			
		||||
    </form>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>Register</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <%- include("../partials/navbar.ejs", { activeLink: "register", loggedIn: false }) %>
 | 
			
		||||
    <form action="/registerUser" method="post">
 | 
			
		||||
        <h2>Register</h2>
 | 
			
		||||
        <div class="input-field">
 | 
			
		||||
            <input type="text" name="username" id="username" placeholder="Enter Username">
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="input-field">
 | 
			
		||||
            <input type="password" name="password" id="password" placeholder="Enter Password">
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="input-field">
 | 
			
		||||
            <input type="password" name="password2" id="password2" placeholder="Confirm Password">
 | 
			
		||||
        </div>
 | 
			
		||||
        <input type="submit" value="Register">
 | 
			
		||||
        <% if(invalid == "exists") { %><span style="color:red;">Account already exists</span>
 | 
			
		||||
        <% } else if(invalid == "noinput") { %><span style="color:red;">Type in username and password</span>
 | 
			
		||||
        <% } else if(invalid == "nomatch") { %><span style="color:red;">Passwords don't match</span>
 | 
			
		||||
        <% } else if(invalid == "created") { %><span style="color:green;">Account created</span><% } %> 
 | 
			
		||||
    </form>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
<style>
 | 
			
		||||
.topnav {
 | 
			
		||||
    background-color: #333;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.topnav a {
 | 
			
		||||
    float: left;
 | 
			
		||||
    color: #f2f2f2;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    padding: 14px 16px;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
    font-size: 17px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.topnav a.hoverable:hover {
 | 
			
		||||
    background-color: #ddd;
 | 
			
		||||
    color: black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.topnav a.active {
 | 
			
		||||
    background-color: #04AA6D;
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.topnav a.right {
 | 
			
		||||
    float: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.topnav a.no-pointer {
 | 
			
		||||
    cursor: default;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<script>
 | 
			
		||||
function clock() {      
 | 
			
		||||
    const x = new Date();
 | 
			
		||||
    document.getElementById("topbar_clock").innerHTML = String(x.getHours()).padStart(2, '0') + ":" + String(x.getMinutes()).padStart(2, '0') + ":" + String(x.getSeconds()).padStart(2, '0');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
setInterval(clock, 100);
 | 
			
		||||
</script>
 | 
			
		||||
<div class="topnav">
 | 
			
		||||
    <a class="no-pointer" id="topbar_clock" href="#">12:00:00</a>
 | 
			
		||||
    <a class="hoverable<% if(activeLink === "home") { %> active<% } %>" id="topnav_home" href="/">Home</a>
 | 
			
		||||
    <% if(!loggedIn) { %> 
 | 
			
		||||
    <a class="hoverable right<% if(activeLink === "login") { %> active<% } %>" id="topnav_login" href="/login">Login</a>
 | 
			
		||||
    <a class="hoverable right<% if(activeLink === "register") { %> active<% } %>" id="topnav_register" href="/register">Register</a>
 | 
			
		||||
    <% } else { %>
 | 
			
		||||
    <a class="hoverable right" id="topnav_logout" href="/logout">Log out</a>
 | 
			
		||||
    <a class="hoverable right" id="topnav_user" href="#"><%- username %></a>
 | 
			
		||||
    <% } %> 
 | 
			
		||||
</div>
 | 
			
		||||
		Loading…
	
		Reference in New Issue