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": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bcrypt": "^5.0.1",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
"ejs": "^3.1.8",
|
"ejs": "^3.1.8",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.22.0",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
|
"express-session": "^1.17.3",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
"ping": "^0.4.2",
|
"ping": "^0.4.2",
|
||||||
"typescript": "^4.7.4"
|
"typescript": "^4.7.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/cookie-parser": "^1.4.3",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
|
"@types/express-session": "^1.17.5",
|
||||||
|
"@types/mysql": "^2.15.21",
|
||||||
"@types/node": "^18.7.6",
|
"@types/node": "^18.7.6",
|
||||||
"@types/ping": "^0.4.1"
|
"@types/ping": "^0.4.1"
|
||||||
}
|
}
|
||||||
|
|
42
src/index.ts
42
src/index.ts
|
@ -1,6 +1,10 @@
|
||||||
import express, { Request, Response } from 'express';
|
import express, { Request, Response } from 'express';
|
||||||
import * as Ping from 'ping';
|
import * as Ping from 'ping';
|
||||||
import { existsSync, readdirSync, writeFileSync, readFileSync } from 'fs';
|
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 ping = async (host: string) => {
|
||||||
const result = await Ping.promise.probe(host, {
|
const result = await Ping.promise.probe(host, {
|
||||||
|
@ -10,8 +14,28 @@ const ping = async (host: string) => {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const connection = mysql.createConnection({
|
||||||
|
host: "localhost",
|
||||||
|
user: "root",
|
||||||
|
password: "root",
|
||||||
|
database: "sshmon"
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.connect();
|
||||||
|
|
||||||
const app = express();
|
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();
|
const pings = new Map();
|
||||||
|
|
||||||
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
|
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
|
||||||
|
@ -22,16 +46,24 @@ const timeoutDelay = 60000;
|
||||||
const routes = readdirSync("./routes");
|
const routes = readdirSync("./routes");
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
const file = require(`./routes/${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'));
|
app.listen(8080, () => console.log('rdy'));
|
||||||
|
|
||||||
export interface Data {
|
interface Data {
|
||||||
ping: Function,
|
ping: Function,
|
||||||
pings: Map<string, number>,
|
pings: Map<string, number>,
|
||||||
addresses: Array<string>,
|
addresses: Array<string>,
|
||||||
timeoutDelay: number
|
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'
|
import { existsSync, writeFileSync, readFileSync } from 'fs'
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
method: "GET",
|
||||||
url: "/addIP/:ip",
|
url: "/addIP/:ip",
|
||||||
callback: async (data: any, req: Request, res: Response) => {
|
callback: async (data: any, req: Request, res: Response) => {
|
||||||
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
|
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
method: "GET",
|
||||||
url: "/downtime/:ip",
|
url: "/downtime/:ip",
|
||||||
callback: async (data: any, req: Request, res: Response) => {
|
callback: async (data: any, req: Request, res: Response) => {
|
||||||
const ip = req.params.ip;
|
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';
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
method: "GET",
|
||||||
url: "/ping/:ip",
|
url: "/ping/:ip",
|
||||||
callback: async (data: any, req: Request, res: Response) => {
|
callback: async (data: any, req: Request, res: Response) => {
|
||||||
const ip = req.params.ip;
|
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'
|
import { existsSync, writeFileSync, readFileSync } from 'fs'
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
method: "GET",
|
||||||
url: "/removeIP/:ip",
|
url: "/removeIP/:ip",
|
||||||
callback: async (data: any, req: Request, res: Response) => {
|
callback: async (data: any, req: Request, res: Response) => {
|
||||||
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
|
if(!existsSync("../data.json")) writeFileSync("../data.json", "[]");
|
||||||
|
|
|
@ -2,12 +2,19 @@ import { Request, Response } from 'express';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
method: "GET",
|
||||||
url: "/",
|
url: "/",
|
||||||
callback: async (data: any, req: Request, res: Response) => {
|
callback: async (data: any, req: Request, res: Response) => {
|
||||||
data.addresses = JSON.parse(readFileSync("../data.json", {encoding:'utf8', flag:'r'}))
|
data.addresses = JSON.parse(readFileSync("../data.json", {encoding:'utf8', flag:'r'}));
|
||||||
res.render('pages/index.ejs', {
|
//@ts-ignore
|
||||||
|
if(!req.session.user) res.redirect("/login");
|
||||||
|
else res.render('pages/index.ejs', {
|
||||||
addresses: data.addresses,
|
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>
|
<head>
|
||||||
<script>
|
<script>
|
||||||
const addresses = ["<%- addresses.join(`", \"`) %>"];
|
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() {
|
async function addIP() {
|
||||||
const addrElement = document.getElementById("addresses");
|
const addrElement = document.getElementById("addresses");
|
||||||
|
@ -51,18 +46,11 @@
|
||||||
setTimeout(aaa, <%= timeoutDelay %>)
|
setTimeout(aaa, <%= timeoutDelay %>)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = async () => {
|
window.onload = aaa;
|
||||||
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);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="time">12:00:00</div>
|
<%- include("../partials/navbar.ejs", { activeLink: "home", username, loggedIn }) %>
|
||||||
<div id="main"></div>
|
<div id="main"></div>
|
||||||
<div id="eta"></div><br />
|
<div id="eta"></div><br />
|
||||||
<input type="text" name="ipaddr" id="ipaddr" value="">
|
<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