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"
|
||||
}
|
||||
|
|
40
src/index.ts
40
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