initial commit

This commit is contained in:
Mystikfluu 2022-04-20 21:31:09 +02:00
commit 534d1a6d07
11 changed files with 2217 additions and 0 deletions

132
.gitignore vendored Normal file
View File

@ -0,0 +1,132 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
cookiesecret.txt
mysql_key.txt
register.py
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

99
css/logon.css Normal file
View File

@ -0,0 +1,99 @@
* {
padding: 0px;
margin: 0px;
}
body {
background-color: lightgreen;
}
header {
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 15vh;
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
}
h1 {
letter-spacing: 1.5vw;
font-family: 'system-ui';
text-transform: uppercase;
text-align: center;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 75vh;
width: 100%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Mountains-1412683.svg/1280px-Mountains-1412683.svg.png) no-repeat center center;
background-size: cover;
}
.form_class {
width: 500px;
padding: 40px;
border-radius: 8px;
background-color: white;
font-family: 'system-ui';
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
}
.form_div {
text-transform: uppercase;
}
.form_div > label {
letter-spacing: 3px;
font-size: 1rem;
}
.info_div {
text-align: center;
margin-top: 20px;
}
.info_div {
letter-spacing: 1px;
}
.field_class {
width: 100%;
border-radius: 6px;
border-style: solid;
border-width: 1px;
padding: 5px 0px;
text-indent: 6px;
margin-top: 10px;
margin-bottom: 20px;
font-family: 'system-ui';
font-size: 0.9rem;
letter-spacing: 2px;
}
.submit_class {
border-style: none;
border-radius: 5px;
background-color: #FFE6D4;
padding: 8px 20px;
font-family: 'system-ui';
text-transform: uppercase;
letter-spacing: .8px;
display: block;
margin: auto;
margin-top: 10px;
box-shadow: 2px 2px 5px rgb(0,0,0,0.2);
cursor: pointer;
}
footer {
height: 10vh;
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: -5px -5px 10px rgb(0,0,0,0.3);
}
footer > p {
text-align: center;
font-family: 'system-ui';
letter-spacing: 3px;
}
footer > p > a {
text-decoration: none;
color: white;
font-weight: bold;
}

47
css/main.css Normal file
View File

@ -0,0 +1,47 @@
* {
padding: 0px;
margin: 0px;
}
body {
background-color: lightgreen;
}
header {
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 15vh;
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
}
h1 {
letter-spacing: 1.5vw;
font-family: 'system-ui';
text-transform: uppercase;
text-align: center;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 75vh;
width: 100%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Mountains-1412683.svg/1280px-Mountains-1412683.svg.png) no-repeat center center;
background-size: cover;
}
.info_div {
text-align: center;
margin-top: 20px;
}
.info_div {
letter-spacing: 1px;
}
footer {
height: 10vh;
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: -5px -5px 10px rgb(0,0,0,0.3);
}

14
css/style.css Normal file
View File

@ -0,0 +1,14 @@
* {
font-family: Arial, Helvetica, sans-serif;
}
body {
background-color: black;
color: white;
text-align: center;
}
button {
font-size: 18px;
margin: 10px;
}

1526
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

10
package.json Normal file
View File

@ -0,0 +1,10 @@
{
"dependencies": {
"body-parser": "^1.20.0",
"cookie-parser": "^1.4.6",
"express": "^4.17.3",
"express-fileupload": "^1.3.1",
"express-useragent": "^1.0.15",
"mysql": "^2.18.1"
}
}

273
server.js Normal file
View File

@ -0,0 +1,273 @@
const http = require('http');
const https = require('https');
const crypto = require("crypto");
const express = require("express");
const fs = require("fs");
const router = express.Router();
const redirrouter = express.Router();
const app = express();
const useragent = require('express-useragent');
const fileUpload = require('express-fileupload');
const bodyParser = require("body-parser");
const cookieParser = require('cookie-parser');
const signature = require('cookie-signature')
const mysql = require('mysql');
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: fs.readFileSync("mysql_key.txt").toString()
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
const dir = __dirname + "/"
const cookiesecret = fs.readFileSync("cookiesecret.txt").toString()
function SHA256(str) {
if(!str)return;
return crypto
.createHash("sha256")
.update(str)
.digest("base64");
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function genstring(length) {
var result = "";
var characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
var charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
function clientErrorHandler(err, req, res, next) {
if(err) {
if (req.xhr) {
res.status(200).send({ error: 'Something failed!' });
} else {
console.log(err);
}
} else {
next()
}
}
function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}
function unsign(text,req,res) {
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
let unsigned = signature.unsign(text,cookiesecret+ip)
if(!unsigned) {
res.status(400)
res.json({"error":"Bad auth cookie set"})
}
return unsigned
}
app.use(useragent.express());
app.use(fileUpload())
app.use(bodyParser.json({ limit: "100mb" }));
app.use(bodyParser.urlencoded({ limit: "100mb", extended: true }));
app.use(clientErrorHandler);
app.use(cookieParser(cookiesecret));
router.get("/",function(req,res) {
res.sendFile(dir+"views/index.html")
})
/*
START /API/*
*/
var API_CALLS = {}
function clear_api_calls() {
API_CALLS = {}
}
setInterval(clear_api_calls, 10000)
function increaseAPICall(req,res,next) {
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
if(API_CALLS[ip]==undefined)API_CALLS[ip]=0
if(API_CALLS[ip] >= 20) {
res.status(429)
res.send("You are sending too many api calls!")
console.log("rate limiting " + ip);
return false
}
API_CALLS[ip]++;
if(next)next()
return true
}
router.use("/api/*",async function(req,res,next) {
increaseAPICall(req,res,next)
})
router.get("/api/getuser",async function(req,res) {
let cookie = req.cookies.AUTH_COOKIE
if(!cookie){
res.status(400)
res.json({"error":"you are not logged in!"})
return
}
let unsigned = unsign(cookie,req,res)
let values = unsigned.split(" ")
let hashed_pw = values[1]
let username = values[0]
for (let i = 0; i < 9999; i++) {
hashed_pw = SHA256(hashed_pw)
}
values[1] = hashed_pw
let sql = `select * from zerotwohub.users where User_Name=? and User_PW=?;`
let sent_res = false
con.query(sql, values, function (err, result) {
if (err) throw err;
if(result[0] && result[0].User_Name && result[0].User_Name == username) {
res.json({"username":username})
} else {
res.json({"error":"you are not logged in!"})
}
sent_res = true
});
setTimeout(function(){if(!sent_res)res.json({"error":"timeout"})},3000);
})
router.post("/api/post", async function(req,res) {
res.send("not implemented yet.")
})
/*
END /API/*
*/
router.get("/css/*", (request, response) => {
if(fs.existsSync(__dirname + request.originalUrl)){
response.sendFile(__dirname + request.originalUrl);
} else {
response.status(404).send("no file with that name found")
}
return;
});
router.get("/*", (request, response, next) => {
let originalUrl = request.originalUrl.split("?").shift()
if(fs.existsSync(dir + "views/"+originalUrl+".html")) {
return response.sendFile(dir + "views/"+originalUrl+".html");
}
if(fs.existsSync(dir + "views"+originalUrl)) {
return response.sendFile(dir + "views"+originalUrl);
}
if(fs.existsSync(dir + "views"+originalUrl+".html")) {
return response.sendFile(dir + "views"+originalUrl+".html");
}
if(fs.existsSync(dir + "views"+originalUrl)) {
return response.sendFile(dir + "views"+originalUrl);
}
response.status(200).send("No file with that name found: "+originalUrl)
})
router.post("/register",async function(req,res) {
if(!increaseAPICall(req,res))return;
res.status(200)
let username = req.body.user
username = username.replace(" ","")
let password = req.body.pass
if(!username) {
res.status(400)
res.redirect("/register?success=false&reason=username")
return
}
if(!password) {
res.status(400)
res.redirect("/register?success=false&reason=password")
return
}
let userexistssql = `SELECT User_Name from zerotwohub.users where User_Name = ?`
con.query(userexistssql,[username],function(error,result) {
if(result && result[0] && result[0].User_Name) {
res.status(400)
res.redirect("/register?success=false&reason=already_exists")
return
}
let hashed_pw = password;
for (let i = 0; i < 10000; i++) {
hashed_pw = SHA256(hashed_pw)
}
let values = [username,hashed_pw]
let sql = `INSERT INTO zerotwohub.users (User_Name, User_PW) VALUES (?, ?);`
con.query(sql, values, function (err, result) {
if (err) throw err;
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
let setTo = username + " " + SHA256(password)
let cookiesigned = signature.sign(setTo, cookiesecret+ip);
res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true });
res.redirect("/user?success=true")
});
})
})
router.post("/login",async function(req,res) {
let username = req.body.user
username = username.replace(" ","")
let password = req.body.pass
if(!username) {
res.status(400)
res.send("no username given")
return
}
if(!password) {
res.status(400)
res.send("no password given")
return
}
let hashed_pw = password;
for (let i = 0; i < 10000; i++) {
hashed_pw = SHA256(hashed_pw)
}
let userexistssql = `SELECT * from zerotwohub.users where User_Name = ? and User_PW = ?`
con.query(userexistssql,[username,hashed_pw],function(error,result) {
if(result && result[0] && result[0].User_Name && result[0].User_Name==username && result[0].User_PW && result[0].User_PW == hashed_pw) {
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
let setTo = username + " " + SHA256(password)
let cookiesigned = signature.sign(setTo, cookiesecret+ip);
res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true });
res.redirect("/user?success=true")
} else {
res.redirect("/login?success=false")
}
});
})
app.use(router)
const httpServer = http.createServer(app);
httpServer.listen(25566);

27
views/index.html Normal file
View File

@ -0,0 +1,27 @@
<head>
<style media="screen">
a {
color: red;
text-decoration: none;
}
</style>
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<header>
<h1>Auth website</h1>
</header>
<main>
<div class="info_div">
<p>Do you not have an account? <a href="register">Register now!</a></p>
<br>
<br>
<p>Do you already have an account? <a href="login">Login now!</a></p>
</div>
</main>
<footer>
</footer>
</body>

32
views/login.html Normal file
View File

@ -0,0 +1,32 @@
<head>
<link rel="stylesheet" href="/css/logon.css">
<script type="text/javascript">
function login() {
const user = document.getElementById("user").value
const pw = document.getElementById("pass").value
}
</script>
</head>
<body>
<header>
<h1>Login</h1>
</header>
<main>
<form id="login_form" class="form_class" action="login" method="post">
<div class="form_div">
<label>Username:</label>
<input id="user" class="field_class" name="user" type="text" placeholder="username" autofocus required>
<label>Password:</label>
<input id="pass" class="field_class" name="pass" type="password" placeholder="password" required>
<button class="submit_class" type="submit" form="login_form" onclick="return login()">Login</button>
</div>
<div class="info_div">
<p>Do you not have an account? <a href="register">Register now!</a></p>
</div>
</form>
</main>
<footer>
</footer>
</body>

32
views/register.html Normal file
View File

@ -0,0 +1,32 @@
<head>
<link rel="stylesheet" href="/css/logon.css">
<script type="text/javascript">
function register() {
const user = document.getElementById("user").value
const pw = document.getElementById("pass").value
}
</script>
</head>
<body>
<header>
<h1>Register</h1>
</header>
<main>
<form id="register_form" class="form_class" action="register" method="post">
<div class="form_div">
<label>Username:</label>
<input id="user" class="field_class" name="user" type="text" placeholder="username" autofocus required>
<label>Password:</label>
<input id="pass" class="field_class" name="pass" type="password" placeholder="password" required>
<button class="submit_class" type="submit" form="register_form" onclick="return register()">register</button>
</div>
<div class="info_div">
<p>Do you already have an account? <a href="/login">Login now!</a></p>
</div>
</form>
</main>
<footer>
</footer>
</body>

25
views/user.html Normal file
View File

@ -0,0 +1,25 @@
<!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>Logged In</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body onload="setuser()">
<h1>Welcome Back!</h1>
<h2 id="user">User: USER</h2>
<button onclick="location.assign('/')">To Login Page</button><button onclick="location.assign('/register')">To Register Page</button>
<script>
async function setuser() {
let user = await (await fetch("/api/getuser")).json();
let username
username = user["username"];
if(user["error"])username=user["error"];
document.getElementById("user").innerText = `User: ${username}`;
}
</script>
</body>
</html>