pw reset done

This commit is contained in:
2023-08-10 13:54:17 +02:00
parent dfda842c7b
commit 0735224dd1
10 changed files with 148 additions and 14 deletions

View File

@@ -11,7 +11,6 @@ const express = require( 'express' );
let app = express(); let app = express();
const path = require( 'path' ); const path = require( 'path' );
const expressSession = require( 'express-session' ); const expressSession = require( 'express-session' );
const bodyParser = require( 'body-parser' );
const cookieParser = require( 'cookie-parser' ); const cookieParser = require( 'cookie-parser' );
const http = require( 'http' ); const http = require( 'http' );
const fs = require( 'fs' ); const fs = require( 'fs' );
@@ -77,7 +76,7 @@ app.use( expressSession( {
// app.use( bodyParser.json() ); // app.use( bodyParser.json() );
app.use( cookieParser() ); app.use( cookieParser() );
let file = path.join( __dirname + '/../webapp/main/dist/index.html' ); let file = path.join( __dirname + '/webapp/index.html' );
console.log( '[ Server ] loading backend components' ); console.log( '[ Server ] loading backend components' );
if ( settings.init ) { if ( settings.init ) {

View File

@@ -38,6 +38,8 @@ class GETHandler {
} }
} else if ( call === 'getName' ) { } else if ( call === 'getName' ) {
resolve( { 'name': settings.name } ); resolve( { 'name': settings.name } );
} else {
reject( { 'code': 404, 'message': 'Route not found' } );
} }
} ); } );
} }

View File

@@ -10,6 +10,7 @@
const path = require( 'path' ); const path = require( 'path' );
const db = require( '../db/db.js' ); const db = require( '../db/db.js' );
const fs = require( 'fs' ); const fs = require( 'fs' );
const pwHandler = require( '../credentials/pwdmanager.js' );
class POSTHandler { class POSTHandler {
constructor () { constructor () {
@@ -153,6 +154,18 @@ class POSTHandler {
console.error( error ); console.error( error );
reject( { 'code': 500, 'message': 'ERR_DB' } ); reject( { 'code': 500, 'message': 'ERR_DB' } );
} ); } );
} else if ( call === 'resetPW' ) {
pwHandler.resetPassword( data.email ).then( () => {
resolve( 'ok' );
} ).catch( error => {
if ( error.code ) {
reject( error );
} else {
reject( { 'code': 500, 'message': error } );
}
} );
} else {
reject( { 'code': 404, 'message': 'Route not found' } );
} }
} ); } );
} }

View File

@@ -65,13 +65,7 @@ class TwoFA {
else return 'invalid'; else return 'invalid';
} }
generatePwdChangeToken () {
// TODO: Gen token and store in store
return 'test';
}
async generateTwoFAMail ( token, ip, domain, pageName ) { async generateTwoFAMail ( token, ip, domain, pageName ) {
const tok = this.generatePwdChangeToken();
const app = createSSRApp( { const app = createSSRApp( {
data() { data() {
return { return {
@@ -79,7 +73,6 @@ class TwoFA {
ip: ip, ip: ip,
host: domain, host: domain,
pageName: pageName, pageName: pageName,
pwdChangeToken: tok,
}; };
}, },
template: '' + fs.readFileSync( path.join( __dirname + '/twoFAMail.html' ) ) template: '' + fs.readFileSync( path.join( __dirname + '/twoFAMail.html' ) )

View File

@@ -15,6 +15,15 @@
// import and init // import and init
const bcrypt = require( 'bcrypt' ); const bcrypt = require( 'bcrypt' );
const db = require( '../db/db.js' ); const db = require( '../db/db.js' );
const mm = require( '../mail/mailSender.js' );
const mailManager = new mm();
const fs = require( 'fs' );
const path = require( 'path' );
const token = require( '../token.js' );
let createSSRApp = require( 'vue' ).createSSRApp;
let renderToString = require( 'vue/server-renderer' ).renderToString;
const settings = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../config/settings.config.json' ) ) );
module.exports.checkpassword = function checkpassword ( email, password ) { module.exports.checkpassword = function checkpassword ( email, password ) {
return new Promise( resolve => { return new Promise( resolve => {
@@ -38,4 +47,33 @@ module.exports.hashPassword = ( password ) => {
return new Promise( resolve => { return new Promise( resolve => {
resolve( bcrypt.hashSync( password, 10 ) ); resolve( bcrypt.hashSync( password, 10 ) );
} ); } );
};
module.exports.resetPassword = ( email ) => {
return new Promise( ( resolve, reject ) => {
db.checkDataAvailability( 'users', 'email', email ).then( dat => {
if ( dat ) {
const newPW = token.generateToken( 20 );
this.hashPassword( newPW ).then( hash => {
( async () => {
db.writeDataSimple( 'users', 'email', email, { 'pass': hash } );
const app = createSSRApp( {
data() {
return {
password: newPW,
host: settings.yourDomain
};
},
template: '' + fs.readFileSync( path.join( __dirname + '/../../ui/en/signup/pwReset.html' ) )
} );
mailManager.sendMail( email, await renderToString( app ), 'Password reset', settings.mailSender );
resolve( 'ok' );
} )();
} );
} else {
reject( { 'code': 404, 'message': 'ERR_USER_NOT_FOUND' } );
}
} );
} );
}; };

View File

@@ -62,7 +62,7 @@
<div class="content"> <div class="content">
<img :src="host + '/otherAssets/logo.png'" alt="Logo" class="logo"> <img :src="host + '/otherAssets/logo.png'" alt="Logo" class="logo">
<h1>Welcome back!</h1> <h1>Welcome back!</h1>
<p>It looks like someone is trying to sign in to your account at {{ pageName }}. If it was you, please click the button below to confirm the login. If not, please <a :href="host + '/account/changePassword?token=' + pwdChangeToken">change</a> your password immediately.</p> <p>It looks like someone is trying to sign in to your account at {{ pageName }}. If it was you, please click the button below to confirm the login. If not, please change your password immediately.</p>
<p class="ip">Logging in from IP {{ ip }}.</p> <p class="ip">Logging in from IP {{ ip }}.</p>
<a :href="host + '/user/2fa?token=' + token" class="verify">Verify</a> <a :href="host + '/user/2fa?token=' + token" class="verify">Verify</a>
</div> </div>

View File

@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Two-Factor Authentication</title>
<style>
body {
font-family: sans-serif;
width: 100%;
height: 800px;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.content {
width: 80%;
height: 90%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.ip {
color: rgb(94, 94, 94);
}
.logo {
width: 70vw;
}
.verify {
padding: 20px 30px;
background-color: rgb(0, 7, 87);
text-decoration: none;
color: white;
transition: 0.5s all;
border-radius: 5px;
margin-bottom: 20px;
}
.verify:hover {
background-color: rgb(0, 12, 139);
}
@media only screen and (min-width: 999px) {
.logo {
width: 20vw;
}
.content {
width: 40vw;
}
}
</style>
</head>
<body>
<div class="content">
<img :src="host + '/otherAssets/logo.png'" alt="Logo" class="logo">
<h1>Password reset</h1>
<p>Your new password is:</p>
<p>{{ password }}</p>
<p>Use it to sign into your account now and change it as soon as you have logged in.</p>
</div>
</body>
</html>

1
src/server/webapp Symbolic link
View File

@@ -0,0 +1 @@
../webapp/main/dist/

View File

@@ -32,10 +32,26 @@
methods: { methods: {
reset() { reset() {
const startNotification = this.$refs.notification.createNotification( 'Starting password reset', 20, 'progress', 'normal' ); const startNotification = this.$refs.notification.createNotification( 'Starting password reset', 20, 'progress', 'normal' );
this.$refs.notification.cancelNotification( startNotification ); let fetchOptions = {
this.$refs.notification.createNotification( 'An account with this email address does not exist.', 5, 'error', 'normal' ); method: 'post',
this.$refs.notification.cancelNotification( startNotification ); body: JSON.stringify( {'email': this.email } ),
this.$refs.notification.createNotification( 'Password reset email sent. Please follow the instructions given there.', 30, 'ok', 'normal' ); headers: {
'Content-Type': 'application/json',
'charset': 'utf-8'
}
};
fetch( localStorage.getItem( 'url' ) + '/API/resetPW', fetchOptions ).then( res => {
if ( res.status !== 200 ) {
this.$refs.notification.cancelNotification( startNotification );
this.$refs.notification.createNotification( 'An account with this email address does not exist.', 5, 'error', 'normal' );
} else {
this.$refs.notification.cancelNotification( startNotification );
this.$refs.notification.createNotification( 'Password reset email sent. Please follow the instructions given there.', 30, 'ok', 'normal' );
setTimeout( () => {
location.href = '/login';
}, 10000 );
}
} );
} }
} }
} }

View File

@@ -46,6 +46,8 @@
<tr> <tr>
<td> <td>
<label for="news">Do you want to potentially get newsletter?</label><br> <label for="news">Do you want to potentially get newsletter?</label><br>
</td>
<td>
<input type="checkbox" v-model="formData[ 'newsletter' ]" name="news" id="news"><br><br> <input type="checkbox" v-model="formData[ 'newsletter' ]" name="news" id="news"><br><br>
</td> </td>
</tr> </tr>