5 Commits

Author SHA1 Message Date
TheGreyDiamond
cc7a918a27 Merge branch 'central' of https://github.com/TheGreyDiamond/elevatormapRewritten into central 2021-05-30 00:45:54 +02:00
TheGreyDiamond
f365ab3486 t 2021-05-30 00:45:52 +02:00
TheGreyDiamond
7e6e636b58 Create node.js.yml 2021-05-30 00:44:32 +02:00
TheGreyDiamond
31db4c25a8 Update README.md 2021-05-30 00:44:04 +02:00
TheGreyDiamond
14189365e0 Created login system 2021-05-30 00:42:03 +02:00
12 changed files with 1910 additions and 149 deletions

30
.github/workflows/node.js.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node.js CI
on:
push:
branches: [ central ]
pull_request:
branches: [ central ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 15.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test

1
.gitignore vendored
View File

@@ -104,4 +104,3 @@ dist
.tern-port .tern-port
testingDONOTCOMMITME.json testingDONOTCOMMITME.json
package-lock.json

View File

@@ -1,2 +1,2 @@
# Elevatormap Rewritten # Elevatormap Rewritten
The elevator map at thegreydiamond.de/elevatormap has been offline for some time now, as it was very ineffective and didn't accept user contributions. This is an attempted my the original author to rewrite the project in Node.js. The elevator map at thegreydiamond.de/elevatormap has been offline for some time now, as it was very ineffective and didn't accept user contributions. This is an attempted by the original author to rewrite the project in Node.js.

443
index.js
View File

@@ -5,10 +5,12 @@ const Eta = require("eta");
const winston = require("winston"); const winston = require("winston");
const mysql = require("mysql"); const mysql = require("mysql");
const bodyParser = require("body-parser"); const bodyParser = require("body-parser");
const bcrypt = require('bcrypt'); const bcrypt = require("bcrypt");
const {verify} = require('hcaptcha'); const { verify } = require("hcaptcha");
const csp = require(`helmet`) const csp = require(`helmet`);
const session = require("express-session");
const nodemailer = require("nodemailer");
const crypto = require("crypto");
// Inting the logger // Inting the logger
const logger = winston.createLogger({ const logger = winston.createLogger({
@@ -55,11 +57,13 @@ app.use(csp.contentSecurityPolicy({
}, },
})) }))
*/ */
// Settings // Settings
const port = 3000; const port = 3000;
const startUpTime = Math.floor(new Date().getTime() / 1000); const startUpTime = Math.floor(new Date().getTime() / 1000);
const saltRounds = 10;
// Load config // Load config
try { try {
@@ -77,12 +81,42 @@ try {
var mapboxAccessToken = jsonConfig.mapboxAccessToken; var mapboxAccessToken = jsonConfig.mapboxAccessToken;
var mysqlData = jsonConfig.mysql; var mysqlData = jsonConfig.mysql;
var hCaptcha = jsonConfig.hCaptcha; var hCaptcha = jsonConfig.hCaptcha;
var mailConf = jsonConfig.mail;
var serverAdress = jsonConfig.serverAdress;
var cookieSecret =
jsonConfig.cookieSecret || "saF0DSF65AS4DF0S4D6F0S54DF0Fad";
} catch (error) { } catch (error) {
logger.error( logger.error(
"While reading the config an error occured. The error was: " + error "While reading the config an error occured. The error was: " + error
); );
} }
var transport = nodemailer.createTransport({
host: mailConf.host,
port: mailConf.port,
requireTLS: true,
secure: false,
debug: true,
disableFileAccess: true,
//authMethod: "START TLS",
auth: {
user: mailConf.username,
pass: mailConf.password,
},
});
//let transporter = nodemailer.createTransport(transport)
//console.log(transport.host)
logger.info("Testing SMTP connection");
transport.verify(function (error, success) {
if (error) {
logger.error(error);
} else {
logger.info("SMPT server is ready to accept messages");
}
});
app.use(session({ secret: cookieSecret }));
// Basic defines for html // Basic defines for html
const author = "TheGreydiamond"; const author = "TheGreydiamond";
@@ -99,6 +133,44 @@ var con = mysql.createConnection({
database: mysqlData.database, database: mysqlData.database,
}); });
// sendVerificationMail(2);
function sendVerificationMail(userId) {
// Query for the mail
const stmt = "SELECT * FROM mailverification WHERE id=" + userId;
con.query(stmt, function (err, result, fields) {
if (err) throw err; // TODO proper error handling
if (result.length == 0) {
logger.warn(
"sendVerificationMail failed because ID " + userId + " doesnt exist!"
);
} else {
const emailContent =
"Hi! \n You have created an account for the open elevator map. To finalize the process please verify your E-Mail adress. Use this link: http://" +
serverAdress +
"/verify/" +
result[0].token;
let info = transport.sendMail({
from: '"Elevator map " <' + mailConf.username + ">", // sender address
to: result[0].targetMail, // list of receivers
subject: "[Elevator map] Please verify your Mailadress", // Subject line
text: emailContent, // plain text body
html: emailContent.replace("\n", "<br>"), // html body
});
}
console.log(result);
});
/*
let info = await transporter.sendMail({
from: '"Elevator map " <' + mysqlData.username + '>', // sender address
to: "bar@example.com, baz@example.com", // list of receivers
subject: "Hello ✔", // Subject line
text: "Hello world?", // plain text body
html: "<b>Hello world?</b>", // html body
});*/
}
function checkIfMySQLStructureIsReady() { function checkIfMySQLStructureIsReady() {
if (mysqlIsUpAndOkay) { if (mysqlIsUpAndOkay) {
// Only if MySQL is ready // Only if MySQL is ready
@@ -118,7 +190,11 @@ function checkIfMySQLStructureIsReady() {
const newSql = const newSql =
"CREATE TABLE `" + "CREATE TABLE `" +
mysqlData.database + mysqlData.database +
"`.`users` ( `id` INT NOT NULL AUTO_INCREMENT , `email` VARCHAR(255) NOT NULL , `username` VARCHAR(255) NOT NULL , `passwordHash` VARCHAR(512) NOT NULL , `permLevel` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`)) ENGINE = InnoDB;"; "`.`users` ( `id` INT NOT NULL AUTO_INCREMENT , `email` VARCHAR(255) NOT NULL , `username` VARCHAR(255) NOT NULL , `passwordHash` VARCHAR(512) NOT NULL , `permLevel` INT NOT NULL DEFAULT '0' , `verificationState` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`), UNIQUE KEY (`email`)) ENGINE = InnoDB;";
const newSqlMailVeri =
"CREATE TABLE `" +
mysqlData.database +
"`.`mailverification` ( `id` INT NOT NULL AUTO_INCREMENT , `targetMail` VARCHAR(512) NOT NULL , `userID` INT NOT NULL , `token` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;";
con.query(sql, function (err, result) { con.query(sql, function (err, result) {
if (err) throw err; if (err) throw err;
logger.info("Table created"); logger.info("Table created");
@@ -128,6 +204,11 @@ function checkIfMySQLStructureIsReady() {
if (err) throw err; if (err) throw err;
logger.info("Usertable created"); logger.info("Usertable created");
}); });
con.query(newSqlMailVeri, function (err, result) {
if (err) throw err;
logger.info("Email verification table created");
});
} else { } else {
// We cannot do that. Welp. // We cannot do that. Welp.
logger.warn( logger.warn(
@@ -170,29 +251,95 @@ app.get("/", function (req, res) {
app.post("/login", function (req, res) { app.post("/login", function (req, res) {
const password = req.body.pass; const password = req.body.pass;
const mail = req.body.email; const mail = req.body.email;
var sess = req.session;
console.log(req.body.pass); console.log(req.body.pass);
// Check if okay // Check if okay
if(mail != undefined && mail != "" && password != undefined && password != ""){ if (
mail != undefined &&
const data = fs.readFileSync("templates/genericError.html", "utf8"); mail != "" &&
var displayText = password != undefined &&
"There is no error"; password != ""
) {
const mailRegex =
/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
if (mailRegex.test(mail)) {
const stmt = "SELECT * FROM users WHERE email='" + mail + "';";
con.query(stmt, function (err, result, fields) {
if (err) throw err; // TODO proper error page
if (result.length == 0) {
const data = fs.readFileSync("templates/login.html", "utf8");
res.send( res.send(
Eta.render(data, { Eta.render(data, {
author: author, author: author,
desc: desc, desc: desc,
siteTitel: sitePrefix + "Ok", siteTitel: sitePrefix + "Ok",
fontawesomeKey: fontawesomeKey, fontawesomeKey: fontawesomeKey,
displayText: displayText, error: true,
errorMessage: "This user does not exist!",
}) })
); );
} else {
bcrypt.compare(
password,
result[0].passwordHash,
function (error, response) {
if (response) {
// Login okay
sess.username = result[0].username;
sess.id = result[0].id;
sess.mail = result[0].email;
}else{ const data = fs.readFileSync("templates/redirect.html", "utf8");
logger.warn("The login form did not sent all data. Dump: \n Password: " + password + " \n E-Mail: " + mail) res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Ok",
fontawesomeKey: fontawesomeKey,
url: "/profile",
})
);
} else {
// Password falsch
const data = fs.readFileSync("templates/login.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Ok",
fontawesomeKey: fontawesomeKey,
error: true,
errorMessage: "The given password is wrong.",
})
);
}
}
);
}
});
} else {
const data = fs.readFileSync("templates/login.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Ok",
fontawesomeKey: fontawesomeKey,
error: true,
errorMessage: "The given E-Mail is invalid.",
})
);
}
} else {
logger.warn(
"The login form did not sent all data. Dump: \n Password: " +
password +
" \n E-Mail: " +
mail
);
const data = fs.readFileSync("templates/genericError.html", "utf8"); const data = fs.readFileSync("templates/genericError.html", "utf8");
var displayText = var displayText = "The form did not sent all the information needed.";
"The form did not sent all the information needed.";
res.send( res.send(
Eta.render(data, { Eta.render(data, {
author: author, author: author,
@@ -241,9 +388,68 @@ app.get("/login", function (req, res) {
} }
}); });
app.get("/profile", function (req, res) {
if (mysqlIsUpAndOkay) {
if (req.session.username != undefined) {
var Hour = new Date().getHours();
var greeting = "Good night, ";
if (Hour > 18) {
greeting = "Good evening, "
} else if (Hour > 13) {
greeting = "Good afternoon, ";
} else if (Hour > 5) {
greeting = "Good morning, ";
}
greeting += req.session.username
const hash = crypto.createHash('md5').update(req.session.mail.replace(" ", "").toLowerCase()).digest('hex');
gravatarURL = "https://www.gravatar.com/avatar/" + hash
const data = fs.readFileSync("templates/profile.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Profile",
fontawesomeKey: fontawesomeKey,
greeting: greeting,
gravatarURL: gravatarURL
})
);
} else {
const data = fs.readFileSync("templates/redirect.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Profile",
fontawesomeKey: fontawesomeKey,
url: "/login",
})
);
}
} else {
const data = fs.readFileSync("templates/dbError.html", "utf8");
var displayText =
"This might be an artifact of a recent restart. Maybe wait a few minutes and reload this page.";
if (startUpTime + 60 <= Math.floor(new Date().getTime() / 1000)) {
displayText =
"The server failed to connect to the MySQL server. This means it was unable to load any data.";
}
if (mySQLstate == 1) {
displayText =
"There is a problem with the database servers setup. Please check the log for more info.";
}
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Error",
fontawesomeKey: fontawesomeKey,
displayText: displayText,
})
);
}
});
app.get("/register", function (req, res) { app.get("/register", function (req, res) {
if (mysqlIsUpAndOkay) { if (mysqlIsUpAndOkay) {
@@ -254,7 +460,7 @@ app.get("/register", function (req, res) {
desc: desc, desc: desc,
siteTitel: sitePrefix + "Register", siteTitel: sitePrefix + "Register",
fontawesomeKey: fontawesomeKey, fontawesomeKey: fontawesomeKey,
sitekey: hCaptcha.sitekey sitekey: hCaptcha.sitekey,
}) })
); );
} else { } else {
@@ -282,15 +488,19 @@ app.get("/register", function (req, res) {
} }
}); });
app.post("/register", function (req, res) { app.post("/register", function (req, res) {
if (mysqlIsUpAndOkay) { if (mysqlIsUpAndOkay) {
console.log(req.body) var sess = req.session;
var resu; var resu;
verify(hCaptcha.secret, req.body["g-recaptcha-response"]) verify(hCaptcha.secret, req.body["g-recaptcha-response"]).then(
.then((data) => resu = data) (data) => (resu = data)
.catch(setTimeout(() => { );
/*.catch(setTimeout(() => {
//if(resu.success == false){
console.log("HERE");
const data = fs.readFileSync("templates/genericError.html", "utf8"); const data = fs.readFileSync("templates/genericError.html", "utf8");
resu = "-1";
con
res.send( res.send(
Eta.render(data, { Eta.render(data, {
author: author, author: author,
@@ -300,25 +510,134 @@ app.post("/register", function (req, res) {
displayText: "There was an issue with the Captcha", displayText: "There was an issue with the Captcha",
}) })
); );
}, 0)); //}
}, 0)
);*/
if (req.body.pass == req.body.pass2) {
const mailRegex =
/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
if (mailRegex.test(req.body.email)) {
setTimeout(() => { setTimeout(() => {
console.log(resu) console.log(resu);
if(resu.success == true){ if (resu.success == true) {
res.send("OK") bcrypt.hash(req.body.pass, saltRounds, (err, hash) => {
}else{ const data = fs.readFileSync(
const data = fs.readFileSync("templates/genericError.html", "utf8"); "templates/genericError.html",
"utf8"
);
// SQL INSERT
var stmt =
"INSERT INTO users(email, username, passwordHash) VALUES(?, ?, ?)";
var stmt2 =
"INSERT INTO mailverification(targetMail, userID, token) VALUES(?, ?, ?)";
crypto.randomBytes(48, function (err, buffer) {
var token = buffer.toString("hex");
con.query(
stmt,
[req.body.email, req.body.username, token],
(err, results1, fields) => {
if (err) {
res.send( res.send(
Eta.render(data, { Eta.render(data, {
author: author, author: author,
desc: desc, desc: desc,
siteTitel: sitePrefix + "Error", siteTitel: sitePrefix + "Error",
fontawesomeKey: fontawesomeKey, fontawesomeKey: fontawesomeKey,
displayText: "The captcha returned a negativ result", displayText:
"An error occured while creating your account.",
})
);
return console.error(err.message);
} else {
// Create mail verification
con.query(
stmt2,
[req.body.email, results1.insertId, hash],
(err, results, fields) => {
if (err) {
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Error",
fontawesomeKey: fontawesomeKey,
displayText:
"An error occured while creating your account.",
})
);
return console.error(err.message);
} else {
sess.username = req.body.username;
sess.id = results1.insertId;
sess.mail = req.body.email;
// get inserted id
logger.info("Inserted Id:" + results.insertId);
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Error",
fontawesomeKey: fontawesomeKey,
displayText: "OK " + hash,
})
);
sendVerificationMail(results.insertId);
}
}
);
}
}
);
});
});
} else {
const data = fs.readFileSync("templates/register.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Register",
fontawesomeKey: fontawesomeKey,
sitekey: hCaptcha.sitekey,
error: true,
errorMessage: "You failed the captcha, please try again.",
}) })
); );
} }
}, 200); }, 200);
} else {
// Passwords don't match up
const data = fs.readFileSync("templates/register.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Register",
fontawesomeKey: fontawesomeKey,
sitekey: hCaptcha.sitekey,
error: true,
errorMessage: "The E-Mail given is not valid",
})
);
}
} else {
// Passwords don't match up
const data = fs.readFileSync("templates/register.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Register",
fontawesomeKey: fontawesomeKey,
sitekey: hCaptcha.sitekey,
error: true,
errorMessage: "The password have to match up.",
})
);
}
} else { } else {
const data = fs.readFileSync("templates/dbError.html", "utf8"); const data = fs.readFileSync("templates/dbError.html", "utf8");
var displayText = var displayText =
@@ -344,8 +663,70 @@ app.post("/register", function (req, res) {
} }
}); });
// Routes
app.get("/verify*", function (req, res) {
console.log(req.url.split("/")[2]);
const data = fs.readFileSync("templates/genericError.html", "utf8");
const stmt = "SELECT * FROM mailverification WHERE token = ?;";
con.query(stmt, [req.url.split("/")[2]], function (err, result, fields) {
if (err) {
res.status(404);
res.send(
JSON.stringify({ state: "Failed", message: "Database error occured" })
);
logger.error(err);
} else {
if (result.length == 0) {
res.status(404);
res.send(
JSON.stringify({ state: "Failed", message: "Link already done" })
);
} else {
console.log(result);
res.status(200);
stmt2 = "DELETE FROM mailverification WHERE id=?";
console.log(result[0].id);
con.query(stmt2, [result[0].id], function (err, result, fields) {
// TODO handling of this
//logger.debug(err)
//console.log(result)
});
stmt3 = "UPDATE users SET verificationState=1 WHERE email=?";
con.query(
stmt3,
[result[0].targetMail],
function (err, result, fields) {
// TODO handling of this
//logger.debug(err)
//console.log(result)
}
);
res.send(JSON.stringify({ state: "OK", message: "Done!" }));
}
}
});
});
app.get("/logout", function (req, res) {
req.session.destroy();
const data = fs.readFileSync("templates/redirect.html", "utf8");
res.send(
Eta.render(data, {
author: author,
desc: desc,
siteTitel: sitePrefix + "Logout",
fontawesomeKey: fontawesomeKey,
url: "/",
})
);
});
app.get("/debug/showSessionInfo", function (req, res) {
res.send(JSON.stringify(req.session));
});
app.get("/map", function (req, res) { app.get("/map", function (req, res) {
if (mysqlIsUpAndOkay) { if (mysqlIsUpAndOkay) {

1135
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -22,9 +22,11 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"eta": "^1.12.1", "eta": "^1.12.1",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.17.2",
"hcaptcha": "0.0.2", "hcaptcha": "0.0.2",
"helmet": "^4.6.0", "helmet": "^4.6.0",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"nodemailer": "^6.6.1",
"winston": "^3.3.3" "winston": "^3.3.3"
} }
} }

View File

@@ -476,3 +476,24 @@ there.
/* Larger than tablet */ /* Larger than tablet */
@media (min-width: 1200px) {} @media (min-width: 1200px) {}
header {
margin: 0px;
height: 20px;
width: 100%;
position: fixed;
top: 0px;
left: 0px;
border-bottom: solid 1px rgba(73, 73, 73, 0.473)
}
.rightMount {
position: fixed;
right: 10px;
}
/*
* {
border: 1px red solid;
}
*/

View File

@@ -40,6 +40,7 @@
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
box-sizing: border-box; box-sizing: border-box;
transition: 0.2s;
} }
body, html { body, html {
@@ -107,6 +108,8 @@ textarea:focus, input:focus {
border-color: transparent !important; border-color: transparent !important;
} }
input:focus::-webkit-input-placeholder { color:transparent; } input:focus::-webkit-input-placeholder { color:transparent; }
input:focus:-moz-placeholder { color:transparent; } input:focus:-moz-placeholder { color:transparent; }
input:focus::-moz-placeholder { color:transparent; } input:focus::-moz-placeholder { color:transparent; }
@@ -495,5 +498,25 @@ iframe {
} }
} }
.alert {
padding: 20px;
background-color: #f44336;
color: white;
transition: 0.5s;
}
.closebtn {
margin-left: 15px;
color: white;
font-weight: bold;
float: right;
font-size: 22px;
line-height: 20px;
cursor: pointer;
transition: 0.5s;
}
.closebtn:hover {
color: black;
transition: 0.5s;
}

View File

@@ -36,6 +36,19 @@
<div class="container-login100"> <div class="container-login100">
<div class="wrap-login100"> <div class="wrap-login100">
<% if(it.error == true) { %>
<div class="alert" id="alert">
<span class="closebtn" id="closeBtn">&times;</span>
<%= it.errorMessage %>
</div>
<script>
$("#closeBtn").click(function () {
$("#alert").fadeOut("slow", function () {
// Animation complete.
});
});
</script>
<% } %>
<div> <div>
<a href="/"><i class="fas fa-arrow-left"></i> Back</a> <a href="/"><i class="fas fa-arrow-left"></i> Back</a>

56
templates/profile.html Normal file
View File

@@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Basic Page Needs
-->
<meta charset="utf-8">
<title><%= it.siteTitel %></title>
<meta name="description" content="<%= it.desc %>">
<meta name="author" content="<%= it.author %>">
<!-- Mobile Specific Metas
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- FONT
-->
<!--<link href="//fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css">-->
<!-- CSS
-->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/barebones.css">
<!-- Favicon
-->
<link rel="icon" type="image/png" href="images/favicon-16.png">
<script async defer src="/js/site.js"></script>
<script src="https://kit.fontawesome.com/<%= it.fontawesomeKey %>.js" crossorigin="anonymous"></script>
</head>
<body>
<!-- Primary Page Layout
-->
<header>
<a class="rightMount" href="/logout"><i class="fas fa-sign-out-alt"></i></a>
</header>
<div class="grid-container thirds" style="margin-top: 5%;">
<div></div>
<div>
<img src="<%= it.gravatarURL %>">
<h1><%= it.greeting %></h1>
<p>This site is still a bit of a placeholder. But it exists.</p>
</div>
</div>
</div>
</div>
<!-- End Document
-->
</body>
</html>

63
templates/redirect.html Normal file
View File

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Basic Page Needs
-->
<meta charset="utf-8">
<title><%= it.siteTitel %></title>
<meta name="description" content="<%= it.desc %>">
<meta name="author" content="<%= it.author %>">
<!-- Mobile Specific Metas
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS
-->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/barebones.css">
<!-- Favicon
-->
<link rel="icon" type="image/png" href="images/favicon-16.png">
<script async defer src="/js/site.js"></script>
<script src="https://kit.fontawesome.com/<%= it.fontawesomeKey %>.js" crossorigin="anonymous"></script>
</head>
<body>
<!-- Primary Page Layout
-->
<div class="grid-container thirds" style="margin-top: 5%;">
<div></div>
<div>
<h1><i class="fas fas fa-arrow-right"></i></h1>
</div>
</div>
</div>
<div class="grid-container thirds" style="margin-top: 5%;">
<div></div>
<div>
<h1>You are being redirected</h1>
<script>
window.location.replace("<%= it.url %>");
</script>
<a href="<%= it.url %>">Click here if you are not being redirected.</a>
<br>
<a href="/"><button class="button-primary">
Return to the startpage
</button>
</a>
</p>
</div>
</div>
</div>
<!-- End Document
-->
</body>
</html>

View File

@@ -1,91 +1,131 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<!-- Basic Page Needs <!-- Basic Page Needs
--> -->
<meta charset="utf-8"> <meta charset="utf-8" />
<title><%= it.siteTitel %></title> <title><%= it.siteTitel %></title>
<meta name="description" content="<%= it.desc %>"> <meta name="description" content="<%= it.desc %>" />
<meta name="author" content="<%= it.author %>"> <meta name="author" content="<%= it.author %>" />
<!-- Mobile Specific Metas <!-- Mobile Specific Metas
--> -->
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- CSS <!-- CSS
--> -->
<link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css"> <link
<link rel="stylesheet" type="text/css" href="vendor/animate/animate.css"> rel="stylesheet"
<link rel="stylesheet" type="text/css" href="vendor/css-hamburgers/hamburgers.min.css"> type="text/css"
<link rel="stylesheet" type="text/css" href="vendor/animsition/css/animsition.min.css"> href="vendor/bootstrap/css/bootstrap.min.css"
<link rel="stylesheet" type="text/css" href="vendor/select2/select2.min.css"> />
<link rel="stylesheet" type="text/css" href="css/util.css"> <link rel="stylesheet" type="text/css" href="vendor/animate/animate.css" />
<link rel="stylesheet" type="text/css" href="css/main.css"> <link
rel="stylesheet"
type="text/css"
href="vendor/css-hamburgers/hamburgers.min.css"
/>
<link
rel="stylesheet"
type="text/css"
href="vendor/animsition/css/animsition.min.css"
/>
<link
rel="stylesheet"
type="text/css"
href="vendor/select2/select2.min.css"
/>
<link rel="stylesheet" type="text/css" href="css/util.css" />
<link rel="stylesheet" type="text/css" href="css/main.css" />
<!-- Favicon <!-- Favicon
--> -->
<link rel="icon" type="image/png" href="images/favicon-16.png"> <link rel="icon" type="image/png" href="images/favicon-16.png" />
<script src="https://kit.fontawesome.com/<%= it.fontawesomeKey %>.js" crossorigin="anonymous"></script> <script
src="https://kit.fontawesome.com/<%= it.fontawesomeKey %>.js"
crossorigin="anonymous"
</head> ></script>
<body> <script src="vendor/jquery/jquery-3.2.1.min.js"></script>
</head>
<body>
<div class="limiter"> <div class="limiter">
<div class="container-login100"> <div class="container-login100">
<div class="wrap-login100"> <div class="wrap-login100">
<% if(it.error == true) { %>
<div class="alert" id="alert">
<span class="closebtn" id="closeBtn">&times;</span>
<%= it.errorMessage %>
</div>
<script>
$("#closeBtn").click(function () {
$("#alert").fadeOut("slow", function () {
// Animation complete.
});
});
</script>
<% } %>
<div> <div>
<a href="/"><i class="fas fa-arrow-left"></i> Back</a> <a href="/"><i class="fas fa-arrow-left"></i> Back</a>
</div> </div>
<form class="login100-form validate-form" method="post"> <form class="login100-form validate-form" method="post">
<span class="login100-form-title p-b-26"> <span class="login100-form-title p-b-26"> Welcome </span>
Welcome
</span>
<span class="login100-form-title p-b-48"> <span class="login100-form-title p-b-48">
<i class="zmdi zmdi-font"></i> <i class="zmdi zmdi-font"></i>
</span> </span>
<div class="wrap-input100"> <div class="wrap-input100">
<input class="input100" type="text" name="username"> <input class="input100" type="text" name="username" />
<span class="focus-input100" data-placeholder="Username"></span> <span class="focus-input100" data-placeholder="Username"></span>
</div> </div>
<div class="wrap-input100 validate-input" data-validate = "Valid email is: john@test.com"> <div
<input class="input100" type="text" name="email"> class="wrap-input100 validate-input"
data-validate="Valid email is: john@test.com"
>
<input class="input100" type="text" name="email" />
<span class="focus-input100" data-placeholder="Email"></span> <span class="focus-input100" data-placeholder="Email"></span>
</div> </div>
<div
<div class="wrap-input100 validate-input" data-validate="Enter password"> class="wrap-input100 validate-input"
data-validate="Enter password"
>
<span class="btn-show-pass"> <span class="btn-show-pass">
<i class="zmdi zmdi-eye"></i> <i class="zmdi zmdi-eye"></i>
</span> </span>
<input class="input100" type="password" name="pass"> <input class="input100" type="password" name="pass" />
<span class="focus-input100" data-placeholder="Password"></span> <span class="focus-input100" data-placeholder="Password"></span>
</div> </div>
<div class="wrap-input100 validate-input" data-validate="Repeat password"> <div
class="wrap-input100 validate-input"
data-validate="Repeat password"
>
<span class="btn-show-pass"> <span class="btn-show-pass">
<i class="zmdi zmdi-eye"></i> <i class="zmdi zmdi-eye"></i>
</span> </span>
<input class="input100" type="password" name="pass2"> <input class="input100" type="password" name="pass2" />
<span class="focus-input100" data-placeholder="Repeat Password"></span> <span
class="focus-input100"
data-placeholder="Repeat Password"
></span>
</div> </div>
<div class="h-captcha" data-sitekey="<%= it.sitekey %>"></div> <div class="h-captcha" data-sitekey="<%= it.sitekey %>"></div>
<script src="https://hcaptcha.com/1/api.js" async defer unsafe-eval></script> <script
src="https://hcaptcha.com/1/api.js"
async
defer
unsafe-eval
></script>
<div class="container-login100-form-btn"> <div class="container-login100-form-btn">
<div class="wrap-login100-form-btn"> <div class="wrap-login100-form-btn">
<div class="login100-form-bgbtn"></div> <div class="login100-form-bgbtn"></div>
<button class="login100-form-btn"> <button class="login100-form-btn">Create a new account</button>
Create a new account
</button>
</div> </div>
</div> </div>
</form> </form>
@@ -93,10 +133,8 @@
</div> </div>
</div> </div>
<div id="dropDownSelect1"></div> <div id="dropDownSelect1"></div>
<script src="vendor/jquery/jquery-3.2.1.min.js"></script>
<script src="vendor/animsition/js/animsition.min.js"></script> <script src="vendor/animsition/js/animsition.min.js"></script>
<script src="vendor/bootstrap/js/popper.js"></script> <script src="vendor/bootstrap/js/popper.js"></script>
<script src="vendor/bootstrap/js/bootstrap.min.js"></script> <script src="vendor/bootstrap/js/bootstrap.min.js"></script>
@@ -104,7 +142,7 @@
<script src="vendor/daterangepicker/moment.min.js"></script> <script src="vendor/daterangepicker/moment.min.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
<!-- End Document <!-- End Document
--> -->
</body> </body>
</html> </html>