mirror of
https://github.com/janishutz/libreevent.git
synced 2025-11-25 05:14:23 +00:00
working 2fa system
This commit is contained in:
@@ -8,8 +8,10 @@
|
||||
*/
|
||||
|
||||
const token = require( '../backend/token.js' );
|
||||
// let createSSRApp = require( 'vue' ).createSSRApp;
|
||||
// let renderToString = require( 'vue/server-renderer' ).renderToString;
|
||||
let createSSRApp = require( 'vue' ).createSSRApp;
|
||||
let renderToString = require( 'vue/server-renderer' ).renderToString;
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
|
||||
class TwoFA {
|
||||
constructor () {
|
||||
@@ -61,6 +63,22 @@ class TwoFA {
|
||||
} else if ( this.tokenStore[ token ]?.mode === 'enhanced' ) return 'enhanced';
|
||||
else return 'invalid';
|
||||
}
|
||||
|
||||
async generateTwoFAMail ( token, ip, domain, pageName ) {
|
||||
const app = createSSRApp( {
|
||||
data() {
|
||||
return {
|
||||
token: token,
|
||||
ip: ip,
|
||||
host: domain,
|
||||
pageName: pageName,
|
||||
};
|
||||
},
|
||||
template: '' + fs.readFileSync( path.join( __dirname + '/twoFAMail.html' ) )
|
||||
} );
|
||||
|
||||
return await renderToString( app );
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TwoFA;
|
||||
@@ -12,13 +12,15 @@ const pwdmanager = require( './pwdmanager.js' );
|
||||
const auth = require( './2fa.js' );
|
||||
const twoFA = new auth();
|
||||
const path = require( 'path' );
|
||||
const mail = require( '../backend/mail/mailSender.js' );
|
||||
const mailManager = new mail();
|
||||
|
||||
let responseObjects = {};
|
||||
let authOk = {};
|
||||
|
||||
module.exports = ( app, settings ) => {
|
||||
/*
|
||||
Admin login route that checks the password
|
||||
Admin login route that checks the password
|
||||
*/
|
||||
|
||||
app.post( '/admin/auth', ( request, response ) => {
|
||||
@@ -26,18 +28,26 @@ module.exports = ( app, settings ) => {
|
||||
pwdmanager.checkpassword( request.body.mail, request.body.password ).then( data => {
|
||||
request.session.username = request.body.mail;
|
||||
if ( data ) {
|
||||
// TODO: Send mails
|
||||
request.session.username = request.body.mail;
|
||||
// TODO: Check if user has 2fa enabled
|
||||
if ( settings.twoFA === 'standard' ) {
|
||||
let tok = twoFA.registerStandardAuthentication()[ 'token' ];
|
||||
request.session.token = tok;
|
||||
console.log( 'http://localhost:8081/admin/2fa?token=' + tok );
|
||||
response.send( { 'status': '2fa' } );
|
||||
( async () => {
|
||||
let tok = twoFA.registerStandardAuthentication()[ 'token' ];
|
||||
let ipRetrieved = request.headers[ 'x-forwarded-for' ];
|
||||
let ip = ipRetrieved ? ipRetrieved.split( /, / )[ 0 ] : request.connection.remoteAddress;
|
||||
mailManager.sendMail( request.body.mail, await twoFA.generateTwoFAMail( tok, ip, settings.yourDomain, settings.name ), 'Verify admin account login', settings.mailSender );
|
||||
request.session.token = tok;
|
||||
response.send( { 'status': '2fa' } );
|
||||
} )();
|
||||
} else if ( settings.twoFA === 'enhanced' ) {
|
||||
let res = twoFA.registerEnhancedAuthentication();
|
||||
console.log( 'http://localhost:8081/admin/2fa?token=' + res.token );
|
||||
request.session.token = res.token;
|
||||
response.send( { 'status': '2fa+', 'code': res.code } );
|
||||
( async () => {
|
||||
let res = twoFA.registerEnhancedAuthentication();
|
||||
let ipRetrieved = request.headers[ 'x-forwarded-for' ];
|
||||
let ip = ipRetrieved ? ipRetrieved.split( /, / )[ 0 ] : request.connection.remoteAddress;
|
||||
mailManager.sendMail( request.body.mail, await twoFA.generateTwoFAMail( res.token, ip, settings.yourDomain, settings.name ), 'Verify admin account login', settings.mailSender );
|
||||
request.session.token = res.token;
|
||||
response.send( { 'status': '2fa+', 'code': res.code } );
|
||||
} )();
|
||||
} else {
|
||||
request.session.loggedInUser = true;
|
||||
response.send( { 'status': 'ok' } );
|
||||
|
||||
@@ -21,7 +21,17 @@ const db = require( '../backend/db/db.js' );
|
||||
module.exports.checkpassword = ( username, password ) => {
|
||||
return new Promise( resolve => {
|
||||
db.getDataSimple( 'admin', 'email', username ).then( data => {
|
||||
resolve( bcrypt.compareSync( password, data ) );
|
||||
if ( data ) {
|
||||
if ( data[ 0 ] ) {
|
||||
bcrypt.compare( password, data[ 0 ].pass ).then( res => {
|
||||
resolve( res );
|
||||
} );
|
||||
} else {
|
||||
resolve( false );
|
||||
}
|
||||
} else {
|
||||
resolve( false );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
70
src/server/admin/twoFAMail.html
Normal file
70
src/server/admin/twoFAMail.html
Normal 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>Welcome back!</h1>
|
||||
<p>It looks like someone is trying to sign in to your admin account at {{ pageName }}. If it was you, please click the button below to confirm the login. If not, please <a :href="host + '/admin/profile/settings'">change</a> your password immediately or have it changed by the root account!</p>
|
||||
<p class="ip">Logging in from IP {{ ip }}.</p>
|
||||
<a :href="host + '/admin/2fa?token=' + token" class="verify">Verify</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,13 +8,16 @@
|
||||
*/
|
||||
|
||||
const token = require( '../token.js' );
|
||||
// let createSSRApp = require( 'vue' ).createSSRApp;
|
||||
// let renderToString = require( 'vue/server-renderer' ).renderToString;
|
||||
let createSSRApp = require( 'vue' ).createSSRApp;
|
||||
let renderToString = require( 'vue/server-renderer' ).renderToString;
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
|
||||
class TwoFA {
|
||||
constructor () {
|
||||
this.tokenStore = {};
|
||||
this.references = {};
|
||||
this.pwdChangeTokens = {};
|
||||
}
|
||||
|
||||
registerStandardAuthentication () {
|
||||
@@ -61,6 +64,29 @@ class TwoFA {
|
||||
} else if ( this.tokenStore[ token ]?.mode === 'enhanced' ) return 'enhanced';
|
||||
else return 'invalid';
|
||||
}
|
||||
|
||||
generatePwdChangeToken () {
|
||||
// TODO: Gen token and store in store
|
||||
return 'test';
|
||||
}
|
||||
|
||||
async generateTwoFAMail ( token, ip, domain, pageName ) {
|
||||
const tok = this.generatePwdChangeToken();
|
||||
const app = createSSRApp( {
|
||||
data() {
|
||||
return {
|
||||
token: token,
|
||||
ip: ip,
|
||||
host: domain,
|
||||
pageName: pageName,
|
||||
pwdChangeToken: tok,
|
||||
};
|
||||
},
|
||||
template: '' + fs.readFileSync( path.join( __dirname + '/twoFAMail.html' ) )
|
||||
} );
|
||||
|
||||
return await renderToString( app );
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TwoFA;
|
||||
@@ -19,9 +19,17 @@ const db = require( '../db/db.js' );
|
||||
module.exports.checkpassword = function checkpassword ( email, password ) {
|
||||
return new Promise( resolve => {
|
||||
db.getDataSimple( 'user', 'email', email ).then( data => {
|
||||
bcrypt.compare( password, data ).then( data => {
|
||||
resolve( data );
|
||||
} );
|
||||
if ( data ) {
|
||||
if ( data[ 0 ] ) {
|
||||
bcrypt.compare( password, data[ 0 ].pass ).then( res => {
|
||||
resolve( res );
|
||||
} );
|
||||
} else {
|
||||
resolve( false );
|
||||
}
|
||||
} else {
|
||||
resolve( false );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
70
src/server/backend/credentials/twoFAMail.html
Normal file
70
src/server/backend/credentials/twoFAMail.html
Normal 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>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 class="ip">Logging in from IP {{ ip }}.</p>
|
||||
<a :href="host + '/user/2fa?token=' + token" class="verify">Verify</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -55,11 +55,11 @@ class SQLDB {
|
||||
if ( error ) throw error;
|
||||
if ( results[ 0 ][ '@@default_storage_engine' ] !== 'InnoDB' ) return 'DB HAS TO USE InnoDB!';
|
||||
} );
|
||||
this.sqlConnection.query( 'CREATE TABLE libreevent_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, pass TEXT, street TEXT, house_number TINYTEXT, country TEXT, phone TEXT, name TEXT, first_name TEXT, data VARCHAR( 10000 ), PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => {
|
||||
this.sqlConnection.query( 'CREATE TABLE libreevent_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, pass TEXT, street TEXT, house_number TINYTEXT, country TEXT, phone TEXT, name TEXT, first_name TEXT, two_fa TINYTEXT, PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => {
|
||||
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
|
||||
this.sqlConnection.query( 'CREATE TABLE libreevent_orders ( order_id INT ( 10 ) NOT NULL AUTO_INCREMENT, account_id INT ( 10 ) NOT NULL, seats VARCHAR( 60000 ), PRIMARY KEY ( order_id ), FOREIGN KEY ( account_id ) REFERENCES libreevent_users( account_id ) ) ENGINE=INNODB;', ( error ) => {
|
||||
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
|
||||
this.sqlConnection.query( 'CREATE TABLE libreevent_admin ( account_id INT NOT NULL AUTO_INCREMENT, email TINYTEXT, pass TEXT, permissions VARCHAR( 1000 ), PRIMARY KEY ( account_id ) );', ( error ) => {
|
||||
this.sqlConnection.query( 'CREATE TABLE libreevent_admin ( account_id INT NOT NULL AUTO_INCREMENT, email TINYTEXT, pass TEXT, permissions VARCHAR( 1000 ), username TINYTEXT, two_fa TINYTEXT, PRIMARY KEY ( account_id ) );', ( error ) => {
|
||||
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
|
||||
this.sqlConnection.query( 'CREATE TABLE libreevent_temp ( entry_id INT NOT NULL AUTO_INCREMENT, user_id TINYTEXT, data VARCHAR( 60000 ), timestamp TINYTEXT, PRIMARY KEY ( entry_id ) );', ( error ) => {
|
||||
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
|
||||
|
||||
@@ -12,32 +12,61 @@ const pwdmanager = require( './credentials/pwdmanager.js' );
|
||||
const auth = require( './credentials/2fa.js' );
|
||||
const twoFA = new auth();
|
||||
const path = require( 'path' );
|
||||
const mail = require( './mail/mailSender.js' );
|
||||
const mailManager = new mail();
|
||||
|
||||
let responseObjects = {};
|
||||
let authOk = {};
|
||||
|
||||
module.exports = ( app, settings ) => {
|
||||
app.post( '/api/reserveTicket', ( request, response ) => {
|
||||
db.getData( 'test', request.body );
|
||||
response.send( 'ok' );
|
||||
app.get( '/user/details', ( request, response ) => {
|
||||
if ( request.session.loggedInUser ) {
|
||||
db.getDataSimple( 'users', 'email', request.session.username ).then( data => {
|
||||
if ( data[ 0 ] ) {
|
||||
let dat = data[ 0 ];
|
||||
delete dat[ 'pass' ];
|
||||
response.send( { 'data': dat, 'status': true } );
|
||||
} else {
|
||||
response.send( { 'data': 'This user does not exist', 'status': false } );
|
||||
}
|
||||
} ).catch( () => {
|
||||
response.send( { 'data': 'There was an error reading data from the database. If this error persists, please contact the administrators', 'status': false } );
|
||||
} );
|
||||
} else {
|
||||
response.status( 403 ).send( path.join( __dirname + '/../ui/en/errors/403.html' ) );
|
||||
}
|
||||
} );
|
||||
|
||||
app.get( '/test/user', ( req, res ) => {
|
||||
req.session.loggedInUser = true;
|
||||
req.session.username = 'info@janishutz.com';
|
||||
res.send( 'ok' );
|
||||
} );
|
||||
|
||||
app.post( '/user/login', ( request, response ) => {
|
||||
if ( request.body.mail && request.body.password ) {
|
||||
pwdmanager.checkpassword( request.body.mail, request.body.password ).then( data => {
|
||||
request.session.username = request.body.mail;
|
||||
// TODO: Check if user has 2fa enabled
|
||||
if ( data ) {
|
||||
// TODO: Send mails
|
||||
if ( settings.twoFA === 'standard' ) {
|
||||
let tok = twoFA.registerStandardAuthentication()[ 'token' ];
|
||||
request.session.token = tok;
|
||||
console.log( 'http://localhost:8081/user/2fa?token=' + tok );
|
||||
response.send( { 'status': '2fa' } );
|
||||
( async () => {
|
||||
let tok = twoFA.registerStandardAuthentication()[ 'token' ];
|
||||
let ipRetrieved = request.headers[ 'x-forwarded-for' ];
|
||||
let ip = ipRetrieved ? ipRetrieved.split( /, / )[ 0 ] : request.connection.remoteAddress;
|
||||
mailManager.sendMail( request.body.mail, await twoFA.generateTwoFAMail( tok, ip, settings.yourDomain, settings.name ), 'Verify login', settings.mailSender );
|
||||
request.session.token = tok;
|
||||
response.send( { 'status': '2fa' } );
|
||||
} )();
|
||||
} else if ( settings.twoFA === 'enhanced' ) {
|
||||
let res = twoFA.registerEnhancedAuthentication();
|
||||
console.log( 'http://localhost:8081/user/2fa?token=' + res.token );
|
||||
request.session.token = res.token;
|
||||
response.send( { 'status': '2fa+', 'code': res.code } );
|
||||
( async () => {
|
||||
let res = twoFA.registerEnhancedAuthentication();
|
||||
let ipRetrieved = request.headers[ 'x-forwarded-for' ];
|
||||
let ip = ipRetrieved ? ipRetrieved.split( /, / )[ 0 ] : request.connection.remoteAddress;
|
||||
mailManager.sendMail( request.body.mail, await twoFA.generateTwoFAMail( res.token, ip, settings.yourDomain, settings.name ), 'Verify login', settings.mailSender );
|
||||
request.session.token = res.token;
|
||||
response.send( { 'status': '2fa+', 'code': res.code } );
|
||||
} )();
|
||||
} else {
|
||||
request.session.loggedInUser = true;
|
||||
response.send( { 'status': 'ok' } );
|
||||
@@ -108,6 +137,11 @@ module.exports = ( app, settings ) => {
|
||||
} );
|
||||
|
||||
app.post( '/user/signup', ( request, response ) => {
|
||||
// TODO: Make sure that user does not exist yet first and if user
|
||||
// exists, send back info that it is that way
|
||||
response.send( 'ok' );
|
||||
db.writeDataSimple( 'users', 'email', request.body.email, { 'pass': pwdmanager.hashPassword( request.query.password ), 'street': '', 'house_number': '', 'country': request.query.country, 'first_name': request.query.firstName, 'name': request.query.name, 'two_fa': String( request.query.twoFA ) } ).then( res => {
|
||||
console.log( res );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
@@ -4,5 +4,6 @@
|
||||
"db": "mysql",
|
||||
"payments": "stripe",
|
||||
"name": "libreevent",
|
||||
"yourDomain": "http://localhost:8081"
|
||||
"yourDomain": "http://localhost:8081",
|
||||
"mailSender": "libreevent <info@libreevent.janishutz.com>"
|
||||
}
|
||||
209
src/server/package-lock.json
generated
209
src/server/package-lock.json
generated
@@ -21,7 +21,8 @@
|
||||
"nodemailer": "^6.9.3",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"serve-static": "^1.15.0",
|
||||
"stripe": "^12.14.0"
|
||||
"stripe": "^12.14.0",
|
||||
"vue": "^3.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "^8.8.2",
|
||||
@@ -59,6 +60,17 @@
|
||||
"yocto-queue": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.22.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
|
||||
"integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
||||
@@ -104,8 +116,7 @@
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.18",
|
||||
@@ -242,6 +253,108 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.4.tgz",
|
||||
"integrity": "sha512-CukZhumInROvLq3+b5gLev+vgpsIqC2D0deQr/yS1WnxvmYLlJXZpaQrQiseMY+6xusl79E04UjWoqyr+t1/Ew=="
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
|
||||
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.21.3",
|
||||
"@vue/shared": "3.3.4",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
|
||||
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
|
||||
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.20.15",
|
||||
"@vue/compiler-core": "3.3.4",
|
||||
"@vue/compiler-dom": "3.3.4",
|
||||
"@vue/compiler-ssr": "3.3.4",
|
||||
"@vue/reactivity-transform": "3.3.4",
|
||||
"@vue/shared": "3.3.4",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.0",
|
||||
"postcss": "^8.1.10",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
|
||||
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
|
||||
"integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity-transform": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
|
||||
"integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.20.15",
|
||||
"@vue/compiler-core": "3.3.4",
|
||||
"@vue/shared": "3.3.4",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
|
||||
"integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
|
||||
"integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
|
||||
"dependencies": {
|
||||
"@vue/runtime-core": "3.3.4",
|
||||
"@vue/shared": "3.3.4",
|
||||
"csstype": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
|
||||
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
|
||||
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
@@ -615,6 +728,11 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -774,6 +892,11 @@
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
@@ -1429,6 +1552,17 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.2",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz",
|
||||
"integrity": "sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
@@ -1625,6 +1759,23 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -1848,6 +1999,38 @@
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.27",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
|
||||
"integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.6",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
@@ -2159,6 +2342,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
@@ -2397,6 +2588,18 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz",
|
||||
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.3.4",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
"@vue/runtime-dom": "3.3.4",
|
||||
"@vue/server-renderer": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
"nodemailer": "^6.9.3",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"serve-static": "^1.15.0",
|
||||
"stripe": "^12.14.0"
|
||||
"stripe": "^12.14.0",
|
||||
"vue": "^3.3.4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "test.js"
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
const sql = require( './backend/db/mysqldb.js' );
|
||||
const sqlDB = new sql();
|
||||
|
||||
const db = require( './backend/db/db.js' );
|
||||
|
||||
sqlDB.connect();
|
||||
// sqlDB.resetDB();
|
||||
sqlDB.setupDB();
|
||||
|
||||
sqlDB.resetDB();
|
||||
|
||||
setTimeout( () => {
|
||||
sqlDB.setupDB();
|
||||
|
||||
setTimeout( () => {
|
||||
db.writeDataSimple( 'admin', 'email', 'info@janishutz.com', { 'email': 'info@janishutz.com', 'pass': '$2b$05$ElMYWoMjk7567lXkIkee.e.6cxCrWU4gkfuNLB8gmGYLQQPm7gT3O', 'username': 'jhutz' } );
|
||||
}, 1000 );
|
||||
|
||||
setTimeout( () => {
|
||||
db.writeDataSimple( 'user', 'email', 'info@janishutz.com', { 'email': 'info@janishutz.com', 'pass': '$2b$05$ElMYWoMjk7567lXkIkee.e.6cxCrWU4gkfuNLB8gmGYLQQPm7gT3O', 'name': 'Hutz', 'first_name': 'Janis', 'two_fa': 'true' } );
|
||||
}, 1000 );
|
||||
|
||||
setTimeout( () => {
|
||||
db.writeDataSimple( 'admin', 'email', 'info@janishutz.com', { 'email': 'info@janishutz.com', 'pass': '$2b$05$ElMYWoMjk7567lXkIkee.e.6cxCrWU4gkfuNLB8gmGYLQQPm7gT3O', 'username': 'jhutz', 'permissions': JSON.stringify( { 'test': true } ), 'two_fa': true } );
|
||||
}, 2000 );
|
||||
}, 1000 );
|
||||
@@ -1,9 +1,16 @@
|
||||
# Account view:
|
||||
- Maybe add multi-language support
|
||||
|
||||
- make pricing groups changeable in UI (event categories)
|
||||
|
||||
- Create password changing endpoint (to reset forgotten pwd)
|
||||
- Add Admin profile (page to change account settings per person like changing pwd)
|
||||
|
||||
|
||||
- Fix text field overflow (text too big for box)
|
||||
- Other optimisation for seat plan editor
|
||||
|
||||
|
||||
- Implement Permission system
|
||||
|
||||
- Seat numbering
|
||||
|
||||
@@ -116,6 +116,15 @@ export default [
|
||||
transition: 'scale'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/guest',
|
||||
name: 'guestPurchase',
|
||||
component: () => import( '@/views/purchasing/GuestPurchaseView.vue' ),
|
||||
meta: {
|
||||
title: 'Guest purchase - ',
|
||||
transition: 'scale'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/admin/seatplan',
|
||||
name: 'adminSeatplanEditor',
|
||||
|
||||
@@ -32,64 +32,72 @@
|
||||
...mapStores( useUserStore ),
|
||||
},
|
||||
created () {
|
||||
if ( !!window.EventSource ) {
|
||||
setTimeout( () => {
|
||||
let startNotification = this.$refs.notification.createNotification( 'Connecting to status service', 20, 'progress', 'normal' );
|
||||
let source = new EventSource( localStorage.getItem( 'url' ) + '/admin/2fa/check', { withCredentials: true } );
|
||||
|
||||
let self = this;
|
||||
if ( this.userStore.getAdminTwoFACompliant ) {
|
||||
if ( !!window.EventSource ) {
|
||||
setTimeout( () => {
|
||||
let startNotification = this.$refs.notification.createNotification( 'Connecting to status service', 20, 'progress', 'normal' );
|
||||
let source = new EventSource( localStorage.getItem( 'url' ) + '/admin/2fa/check', { withCredentials: true } );
|
||||
|
||||
let self = this;
|
||||
|
||||
source.onmessage = ( e ) => {
|
||||
if ( e.data === 'authenticated' ) {
|
||||
self.userStore.setAdminAuth( true );
|
||||
self.$router.push( '/admin' );
|
||||
console.log( e.data );
|
||||
source.onmessage = ( e ) => {
|
||||
if ( e.data === 'authenticated' ) {
|
||||
self.userStore.setAdminAuth( true );
|
||||
self.$router.push( '/admin' );
|
||||
console.log( e.data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source.onopen = e => {
|
||||
self.$refs.notification.createNotification( 'Connected to status service', 5, 'ok', 'normal' );
|
||||
self.$refs.notification.cancelNotification( startNotification );
|
||||
};
|
||||
|
||||
source.addEventListener( 'error', function(e) {
|
||||
if ( e.eventPhase == EventSource.CLOSED ) source.close();
|
||||
|
||||
if ( e.target.readyState == EventSource.CLOSED ) {
|
||||
console.log( e );
|
||||
source.onopen = e => {
|
||||
self.$refs.notification.createNotification( 'Connected to status service', 5, 'ok', 'normal' );
|
||||
self.$refs.notification.cancelNotification( startNotification );
|
||||
self.$refs.notification.createNotification( 'Could not connect to status service', 5, 'error', 'normal' );
|
||||
}
|
||||
}, false)
|
||||
}, 300 );
|
||||
} else {
|
||||
setTimeout( () => {
|
||||
this.$refs.notification.createNotification( 'Unsupported browser detected. Redirection might take longer to occur!', 20, 'warning', 'normal' );
|
||||
}, 300 );
|
||||
// ping server every 5s to check if logged in
|
||||
this.serverPing = setInterval( () => {
|
||||
fetch( '/admin/2fa/ping' ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( data => {
|
||||
if ( data ) {
|
||||
if ( data.status === 'ok' ) {
|
||||
this.userStore.setUserAuth( true );
|
||||
this.$router.push( sessionStorage.getItem( 'redirect' ) ?? '/account' );
|
||||
};
|
||||
|
||||
source.addEventListener( 'error', function(e) {
|
||||
if ( e.eventPhase == EventSource.CLOSED ) source.close();
|
||||
|
||||
if ( e.target.readyState == EventSource.CLOSED ) {
|
||||
console.log( e );
|
||||
self.$refs.notification.cancelNotification( startNotification );
|
||||
self.$refs.notification.createNotification( 'Could not connect to status service', 5, 'error', 'normal' );
|
||||
}
|
||||
}, false)
|
||||
}, 300 );
|
||||
} else {
|
||||
setTimeout( () => {
|
||||
this.$refs.notification.createNotification( 'Unsupported browser detected. Redirection might take longer to occur!', 20, 'warning', 'normal' );
|
||||
}, 300 );
|
||||
// ping server every 5s to check if logged in
|
||||
this.serverPing = setInterval( () => {
|
||||
fetch( '/admin/2fa/ping' ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( data => {
|
||||
if ( data ) {
|
||||
if ( data.status === 'ok' ) {
|
||||
this.userStore.setUserAuth( true );
|
||||
this.$router.push( sessionStorage.getItem( 'redirect' ) ?? '/account' );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
console.error( 'Request failed' );
|
||||
} );
|
||||
} else {
|
||||
console.error( 'Request failed' );
|
||||
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
|
||||
}
|
||||
} ).catch( error => {
|
||||
console.error( error );
|
||||
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
|
||||
}
|
||||
} ).catch( error => {
|
||||
console.error( error );
|
||||
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
|
||||
} );
|
||||
}, 5000 );
|
||||
} );
|
||||
}, 5000 );
|
||||
}
|
||||
let code = sessionStorage.getItem( '2faCode' ) ? sessionStorage.getItem( '2faCode' ) : '';
|
||||
this.code = { '1': code.slice( 0, 3 ), '2': code.substring( 3 ) };
|
||||
} else {
|
||||
if ( this.userStore.getAdminAuthenticated ) {
|
||||
this.$router.push( '/admin' );
|
||||
} else {
|
||||
this.$router.push( '/admin/login' );
|
||||
}
|
||||
}
|
||||
let code = sessionStorage.getItem( '2faCode' ) ? sessionStorage.getItem( '2faCode' ) : '';
|
||||
this.code = { '1': code.slice( 0, 3 ), '2': code.substring( 3 ) };
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -5,4 +5,16 @@
|
||||
* https://janishutz.com, development@janishutz.com
|
||||
*
|
||||
*
|
||||
-->
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Guest purchase</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
@@ -217,6 +217,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
loadData () {
|
||||
// TODO: Also load the customer data from server!
|
||||
this.cartNotEmpty = false;
|
||||
let cart = JSON.parse( localStorage.getItem( 'cart' ) );
|
||||
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
|
||||
<p>Welcome, {{ accountData.first_name }} {{ accountData.name }}!</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
Email
|
||||
</td>
|
||||
<td>
|
||||
{{ accountData.email }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<notifications ref="notification" location="topright" size="bigger"></notifications>
|
||||
<popups ref="popups" size="big" @data="data => { savePwd( data ) }"></popups>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -10,4 +22,50 @@
|
||||
nav {
|
||||
display: initial;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
import { mapStores } from 'pinia';
|
||||
import notifications from '@/components/notifications/notifications.vue';
|
||||
import popups from '@/components/notifications/popups.vue';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
accountData: {},
|
||||
}
|
||||
},
|
||||
components: {
|
||||
notifications,
|
||||
popups,
|
||||
},
|
||||
computed: {
|
||||
...mapStores( useUserStore )
|
||||
},
|
||||
created () {
|
||||
// TODO: Also get all orders of user (using join functions)
|
||||
fetch( '/user/details' ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( data => {
|
||||
if ( data.status ) {
|
||||
this.accountData = data.data;
|
||||
console.log( data.data );
|
||||
} else {
|
||||
this.userStore.setUserAuth( false );
|
||||
this.userStore.setUser2fa( false );
|
||||
this.$router.push( '/login' );
|
||||
}
|
||||
} );
|
||||
} else if ( res.status === 403 ) {
|
||||
this.userStore.setUserAuth( false );
|
||||
this.userStore.setUser2fa( false );
|
||||
this.$router.push( '/login' );
|
||||
}
|
||||
} );
|
||||
if ( this.userStore.getUserTwoFACompliant ) {
|
||||
this.userStore.setUser2fa( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -33,62 +33,70 @@
|
||||
...mapStores( useUserStore ),
|
||||
},
|
||||
created () {
|
||||
if ( !!window.EventSource ) {
|
||||
setTimeout( () => {
|
||||
let startNotification = this.$refs.notification.createNotification( 'Connecting to status service', 20, 'progress', 'normal' );
|
||||
let source = new EventSource( localStorage.getItem( 'url' ) + '/user/2fa/check', { withCredentials: true } );
|
||||
|
||||
let self = this;
|
||||
if ( this.userStore.getUserTwoFACompliant ) {
|
||||
if ( !!window.EventSource ) {
|
||||
setTimeout( () => {
|
||||
let startNotification = this.$refs.notification.createNotification( 'Connecting to status service', 20, 'progress', 'normal' );
|
||||
let source = new EventSource( localStorage.getItem( 'url' ) + '/user/2fa/check', { withCredentials: true } );
|
||||
|
||||
let self = this;
|
||||
|
||||
source.onmessage = ( e ) => {
|
||||
if ( e.data === 'authenticated' ) {
|
||||
self.userStore.setUserAuth( true );
|
||||
self.$router.push( sessionStorage.getItem( 'redirect' ) ?? '/account' );
|
||||
source.onmessage = ( e ) => {
|
||||
if ( e.data === 'authenticated' ) {
|
||||
self.userStore.setUserAuth( true );
|
||||
self.$router.push( sessionStorage.getItem( 'redirect' ) ?? '/account' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source.onopen = e => {
|
||||
self.$refs.notification.createNotification( 'Connected to status service', 5, 'ok', 'normal' );
|
||||
self.$refs.notification.cancelNotification( startNotification );
|
||||
};
|
||||
|
||||
source.addEventListener( 'error', function( e ) {
|
||||
if ( e.eventPhase == EventSource.CLOSED ) source.close();
|
||||
|
||||
if ( e.target.readyState == EventSource.CLOSED ) {
|
||||
source.onopen = e => {
|
||||
self.$refs.notification.createNotification( 'Connected to status service', 5, 'ok', 'normal' );
|
||||
self.$refs.notification.cancelNotification( startNotification );
|
||||
self.$refs.notification.createNotification( 'Could not connect to status service', 5, 'error', 'normal' );
|
||||
}
|
||||
}, false)
|
||||
}, 300 );
|
||||
} else {
|
||||
setTimeout( () => {
|
||||
this.$refs.notification.createNotification( 'Unsupported browser detected. Redirection might take longer to occur!', 20, 'warning', 'normal' );
|
||||
}, 300 );
|
||||
// ping server every 5s to check if logged in
|
||||
this.serverPing = setInterval( () => {
|
||||
fetch( '/user/2fa/ping' ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( data => {
|
||||
if ( data ) {
|
||||
if ( data.status === 'ok' ) {
|
||||
this.userStore.setUserAuth( true );
|
||||
this.$router.push( sessionStorage.getItem( 'redirect' ) ?? '/account' );
|
||||
};
|
||||
|
||||
source.addEventListener( 'error', function( e ) {
|
||||
if ( e.eventPhase == EventSource.CLOSED ) source.close();
|
||||
|
||||
if ( e.target.readyState == EventSource.CLOSED ) {
|
||||
self.$refs.notification.cancelNotification( startNotification );
|
||||
self.$refs.notification.createNotification( 'Could not connect to status service', 5, 'error', 'normal' );
|
||||
}
|
||||
}, false)
|
||||
}, 300 );
|
||||
} else {
|
||||
setTimeout( () => {
|
||||
this.$refs.notification.createNotification( 'Unsupported browser detected. Redirection might take longer to occur!', 20, 'warning', 'normal' );
|
||||
}, 300 );
|
||||
// ping server every 5s to check if logged in
|
||||
this.serverPing = setInterval( () => {
|
||||
fetch( '/user/2fa/ping' ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( data => {
|
||||
if ( data ) {
|
||||
if ( data.status === 'ok' ) {
|
||||
this.userStore.setUserAuth( true );
|
||||
this.$router.push( sessionStorage.getItem( 'redirect' ) ?? '/account' );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
console.error( 'Request failed' );
|
||||
} );
|
||||
} else {
|
||||
console.error( 'Request failed' );
|
||||
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
|
||||
}
|
||||
} ).catch( error => {
|
||||
console.error( error );
|
||||
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
|
||||
}
|
||||
} ).catch( error => {
|
||||
console.error( error );
|
||||
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
|
||||
} );
|
||||
}, 5000 );
|
||||
} );
|
||||
}, 5000 );
|
||||
}
|
||||
let code = sessionStorage.getItem( '2faCode' ) ? sessionStorage.getItem( '2faCode' ) : '';
|
||||
this.code = { '1': code.slice( 0, 3 ), '2': code.substring( 3 ) };
|
||||
} else {
|
||||
if ( this.userStore.getUserAuthenticated ) {
|
||||
this.$router.push( '/account' );
|
||||
} else {
|
||||
this.$router.push( '/login' );
|
||||
}
|
||||
}
|
||||
let code = sessionStorage.getItem( '2faCode' ) ? sessionStorage.getItem( '2faCode' ) : '';
|
||||
this.code = { '1': code.slice( 0, 3 ), '2': code.substring( 3 ) };
|
||||
},
|
||||
unmounted() {
|
||||
clearInterval( this.serverPing );
|
||||
|
||||
Reference in New Issue
Block a user