login system progress

This commit is contained in:
2023-03-26 12:36:21 +02:00
parent 5483f9f46c
commit aa38572aa4
8 changed files with 333 additions and 81 deletions

View File

@@ -0,0 +1,27 @@
/*
* myevent - pwdmanager.js
*
* Created by Janis Hutz 03/26/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
*/
/*
These functions are required to verify user login and to create new users
and to hash new passwords (if user changes password.) This here is only
used for the admin panel, another one is used for the normal user accounts
to separate the two for additional security.
*/
// import and init
const bcrypt = require( 'bcrypt' );
const db = require( '../backend/db/db.js' );
module.exports.checkpassword = function checkpassword ( username, password ) {
return new Promise( resolve => {
db.getData( 'admin', username ).then( data => {
resolve( bcrypt.compareSync( password, data ) );
} );
} );
};

View File

@@ -8,10 +8,45 @@
*/
const path = require( 'path' );
const pwdmanager = require( './pwdmanager.js' );
module.exports = ( app, settings ) => {
/*
Static routes for files like login screen, css, js and assets. Js and assets require login
*/
app.get( '/admin/login', ( request, response ) => {
if ( request.session.loggedIn ) {
response.redirect( '/admin' );
} else {
response.sendFile( path.join( __dirname + '/ui/login.html' ) );
}
} );
app.get( '/admin/loginLangPack', ( request, response ) => {
response.sendFile( path.join( __dirname + '/ui/js/loginLangPack.js' ) );
} );
app.get( '/admin/css/:file', ( request, response ) => {
response.sendFile( path.join( __dirname + '/ui/css/' + request.params.file ) );
} );
/*
Admin login route that checks the password and, if enabled in settings, redirects to 2fa page or directly to admin panel
*/
app.post( '/admin/auth', ( request, response ) => {
pwdmanager.checkpassword( request.body.mail, request.body.pwd ).then( data => {
if ( data ) {
if ( settings.twoFA ) {
response.sendFile( path.join( __dirname + '../admin/ui/2fa.html' ) );
} else {
request.session.loggedIn = true;
response.redirect( '/admin' );
}
} else {
response.send( 'Password wrong' );
}
} );
} );
/*

View File

@@ -0,0 +1,98 @@
:root, :root.light {
--background-color: rgb(202, 223, 255);
--secondary-background: white;
--primary-color: black;
--secondary-color: blue;
--secondary-hover: darkblue;
}
:root.dark {
--background-color: rgb(42, 44, 56);
--secondary-background: rgb(19, 20, 32);
--primary-color: white;
--secondary-color: rgb(94, 94, 226);
--secondary-hover: rgb(155, 155, 255);
}
@media ( prefers-color-scheme: dark ) {
:root {
--background-color: rgb(42, 44, 56);
--secondary-background: rgb(19, 20, 32);
--primary-color: white;
--secondary-color: rgb(94, 94, 226);
--secondary-hover: rgb(155, 155, 255);
}
}
body {
background-color: var(--background-color);
font-family: sans-serif;
font-size: calc(12pt + 0.35vw);
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.login-app {
border-radius: 50px;
margin-top: 2%;
background-color: var(--secondary-background);
color: var(--primary-color);
width: 60%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.form {
width: 80%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 4%;
margin-bottom: 4%;
}
.button {
text-decoration: none;
color: var(--primary-color);
background-color: var(--secondary-color);
padding: 15px;
border-radius: 30px;
transition: 1s;
cursor: pointer;
}
.button:hover {
transition: ease-in-out 0.2s;
background-color: var(--secondary-hover);
border-radius: 5px;
}
.input {
padding: 1%;
width: 80%;
margin-bottom: 3%;
border-radius: 10px;
}
.top-bar {
width: 100%;
display: flex;
align-items: end;
justify-content: end;
}
.selector {
background-color: lightblue;
border-radius: 20px;
padding: 0.5%;
border-style: solid;
border-color: blue;
}

View File

@@ -0,0 +1,32 @@
let themeSelector2 = document.getElementById( 'theme' );
let languageSelector = document.getElementById( 'lang' );
let mailLabel = document.getElementById( 'mailLabel' );
let pwdLabel = document.getElementById( 'pwdLabel' );
let login = document.getElementById( 'login' );
languageSelector.value = sessionStorage.getItem( 'lang' );
function langUpdate () {
if ( sessionStorage.getItem( 'lang' ) === 'de' ) {
themeSelector2.options[0].innerHTML = 'Automatisch';
themeSelector2.options[1].innerHTML = 'Hellmodus';
themeSelector2.options[2].innerHTML = 'Dunkelmodus';
mailLabel.innerHTML = 'Email - Adresse';
pwdLabel.innerHTML = 'Passwort';
login.value = 'Anmelden';
} else {
themeSelector2.options[0].innerHTML = 'System theme';
themeSelector2.options[1].innerHTML = 'Light';
themeSelector2.options[2].innerHTML = 'Dark';
mailLabel.innerHTML = 'Email address';
pwdLabel.innerHTML = 'Password';
login.value = 'Log in';
}
}
function changeLang () {
sessionStorage.setItem( 'lang', languageSelector.value );
langUpdate();
}
langUpdate();

View File

@@ -5,88 +5,17 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login :: myevent - admin panel</title>
<style>
body {
background-color: rgb(202, 223, 255);
font-family: sans-serif;
font-size: calc(12pt + 0.35vw);
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.login-app {
border-radius: 50px;
margin-top: 2%;
background-color: white;
width: 60%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.form {
width: 80%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 4%;
margin-bottom: 4%;
}
.button {
text-decoration: none;
color: white;
background-color: blue;
padding: 15px;
border-radius: 30px;
transition: 1s;
cursor: pointer;
}
.button:hover {
transition: ease-in-out 0.2s;
background-color: darkblue;
border-radius: 5px;
}
.input {
padding: 1%;
width: 80%;
margin-bottom: 3%;
border-radius: 10px;
}
.top-bar {
width: 100%;
display: flex;
align-items: end;
justify-content: end;
}
.selector {
background-color: lightblue;
border-radius: 20px;
padding: 0.5%;
border-style: solid;
border-color: blue;
}
</style>
<link rel="stylesheet" href="/admin/css/loginstyle.css">
<script defer src="/admin/loginLangPack"></script>
</head>
<body>
<div class="content">
<div class="top-bar">
<select name="lang" id="lang" class="selector">
<select name="lang" id="lang" class="selector" onchange="changeLang();">
<option value="en">English</option>
<option value="de">Deutsch</option>
</select>
<select name="theme" id="theme" class="selector">
<select name="theme" id="theme" class="selector" onchange="toggleTheme();">
<option value="system">System theme</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
@@ -97,13 +26,52 @@
<h1>Login</h1>
<footer>myevent - admin panel</footer>
<form action="/admin/auth" method="post" class="form">
<label for="mail">Email address</label><br>
<label for="mail" id="mailLabel">Email address</label><br>
<input type="email" id="mail" name="mail" required class="input"><br>
<label for="pwd">Password</label><br>
<label for="pwd" id="pwdLabel">Password</label><br>
<input type="password" id="pwd" name="pwd" required class="input"><br>
<input type="submit" value="Log in" class="button">
<input type="submit" value="Log in" class="button" id="login">
</form>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
let themeSelector = document.getElementById( 'theme' );
if ( sessionStorage.getItem( 'theme' ) ) {
themeSelector.value = sessionStorage.getItem( 'theme' );
}
if ( window.matchMedia( '(prefers-color-scheme: dark)' ).matches || themeSelector.value === 'dark' ) {
document.documentElement.classList.add( 'dark' );
} else {
document.documentElement.classList.add( 'light' );
};
setTimeout( activate, 500 );
function activate () {
$( 'body' ).css( 'transition', '0.5s' );
}
function toggleTheme () {
sessionStorage.setItem( 'theme', themeSelector.value );
if ( themeSelector.value === 'dark' ) {
document.documentElement.classList.remove( 'light' );
document.documentElement.classList.add( 'dark' );
} else if ( themeSelector.value === 'light' ) {
document.documentElement.classList.remove( 'dark' );
document.documentElement.classList.add( 'light' );
} else if ( themeSelector.value === 'system' ) {
if ( window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {
document.documentElement.classList.remove( 'light' );
document.documentElement.classList.add( 'dark' );
} else {
document.documentElement.classList.remove( 'dark' );
document.documentElement.classList.add( 'light' );
}
}
}
</script>
</body>
</html>

View File

@@ -0,0 +1,76 @@
<!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 :: myevent - admin panel</title>
<link rel="stylesheet" href="/admin/css/loginstyle.css">
</head>
<body>
<div class="content">
<div class="top-bar">
<select name="lang" id="lang" class="selector" onchange="changeLang();">
<option value="en">English</option>
<option value="de">Deutsch</option>
</select>
<select name="theme" id="theme" class="selector" onchange="toggleTheme()">
<option value="system">System theme</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
<a href="https://myevent.janishutz.com"><img src="/assets/logo.png" alt="myevent-logo" style="height: 35vh;"></a>
<div class="login-app">
<h1>Setup</h1>
<footer>myevent - admin panel</footer>
<form action="/admin/auth" method="post" class="form">
<label for="mail">Email address</label><br>
<input type="email" id="mail" name="mail" required class="input"><br>
<label for="pwd">Password</label><br>
<input type="password" id="pwd" name="pwd" required class="input"><br>
<input type="submit" value="Log in" class="button">
</form>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
let themeSelector = document.getElementById( 'theme' );
if ( sessionStorage.getItem( 'theme' ) ) {
themeSelector.value = sessionStorage.getItem( 'theme' );
}
if ( window.matchMedia( '(prefers-color-scheme: dark)' ).matches || themeSelector.value === 'dark' ) {
document.documentElement.classList.add( 'dark' );
} else {
document.documentElement.classList.add( 'light' );
};
setTimeout( activate, 500 );
function activate () {
$( 'body' ).css( 'transition', '0.5s' );
}
function toggleTheme () {
sessionStorage.setItem( 'theme', themeSelector.value );
if ( themeSelector.value === 'dark' ) {
document.documentElement.classList.remove( 'light' );
document.documentElement.classList.add( 'dark' );
} else if ( themeSelector.value === 'light' ) {
document.documentElement.classList.remove( 'dark' );
document.documentElement.classList.add( 'light' );
} else if ( themeSelector.value === 'system' ) {
if ( window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {
document.documentElement.classList.remove( 'light' );
document.documentElement.classList.add( 'dark' );
} else {
document.documentElement.classList.remove( 'dark' );
document.documentElement.classList.add( 'light' );
}
}
}
</script>
</body>
</html>

View File

@@ -0,0 +1,15 @@
/*
* myevent - db.js
*
* Created by Janis Hutz 03/26/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
*/
module.exports.getData = function getData ( db, searchQuery ) {
console.log( db + searchQuery );
return new Promise( resolve => {
resolve( '$2b$05$ElMYWoMjk7567lXkIkee.e.6cxCrWU4gkfuNLB8gmGYLQQPm7gT3O' );
} );
};

View File

@@ -33,6 +33,7 @@
margin: 3%;
margin-bottom: 0;
border-radius: 50px;
width: 40%;
}
.button {
@@ -62,12 +63,12 @@
<div class="lang presented" id="en">
<h1>Welcome to myevent!</h1>
<!-- <p>Thank you for installing and using myevent! Let's get started by setting it up! First plan of action is to log in to the admin panel where you can replace this page here with your own landing page!</p> -->
<a href="/admin/login" class="button">To the admin panel</a>
<a href="/admin/login" class="button" onclick="sessionStorage.setItem( 'lang', 'de' )">To the admin panel</a>
</div>
<div class="lang" id="de">
<h1>Willkommen zu myevent!</h1>
<!-- <p>Vielen Dank für die Installation und Nutzung von myevent! Beginnen wir mit dem Aufsetzen! Der erste Schritt ist, sich ins Admin-Panel einzuloggen um die Seite hier mit deiner eigenen Seite zu ersetzen!</p> -->
<a href="/admin/login?lang=de" class="button">Zum Admin-Panel</a>
<a href="/admin/login" class="button" onclick="sessionStorage.setItem( 'lang', 'de' )">Zum Admin-Panel</a>
</div>
</div>
<script>