user account page done (- styling)

This commit is contained in:
2023-09-07 08:40:21 +02:00
parent 10d0703d78
commit 733cbf2dbb
4 changed files with 238 additions and 85 deletions

View File

@@ -150,7 +150,7 @@ class SQLDB {
command = 'UPDATE ' + table + ' SET '; command = 'UPDATE ' + table + ' SET ';
let updatedValues = ''; let updatedValues = '';
for ( let value in operation.newValues ) { for ( let value in operation.newValues ) {
updatedValues += value + ' = ' + this.sqlConnection.escape( operation.newValues[ value ] ) + ', '; updatedValues += value + ' = ' + this.sqlConnection.escape( String( operation.newValues[ value ] ) ) + ', ';
} }
command += updatedValues.slice( 0, updatedValues.length - 2 ); command += updatedValues.slice( 0, updatedValues.length - 2 );
command += ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery ); command += ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery );

View File

@@ -41,7 +41,6 @@ module.exports = ( app, settings ) => {
response.status( 500 ).send( { 'data': 'There was an error reading data from the database. If this error persists, please contact the administrators', 'status': false } ); response.status( 500 ).send( { 'data': 'There was an error reading data from the database. If this error persists, please contact the administrators', 'status': false } );
} ); } );
} else { } else {
console.log( 'unauthorised' );
response.status( 403 ).sendFile( path.join( __dirname + '/../ui/en/errors/403.html' ) ); response.status( 403 ).sendFile( path.join( __dirname + '/../ui/en/errors/403.html' ) );
} }
} ); } );
@@ -84,7 +83,7 @@ module.exports = ( app, settings ) => {
} }
} ); } );
} else { } else {
response.send( 'missingCredentials' ); response.status( 400 ).send( 'missingCredentials' );
} }
} ); } );
@@ -101,7 +100,7 @@ module.exports = ( app, settings ) => {
} else if ( tokType === 'enhanced' ) { } else if ( tokType === 'enhanced' ) {
response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faEnhanced.html' ) ); response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faEnhanced.html' ) );
} else { } else {
response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faInvalid.html' ) ); response.status( 403 ).sendFile( path.join( __dirname + '/../ui/en/2fa/2faInvalid.html' ) );
} }
} ); } );
@@ -117,7 +116,7 @@ module.exports = ( app, settings ) => {
authOk[ request.body.token ] = 'ok'; authOk[ request.body.token ] = 'ok';
} }
response.send( 'ok' ); response.send( 'ok' );
} else response.send( 'wrong' ); } else response.status( 403 ).send( 'wrong' );
} ); } );
app.get( '/user/2fa/check', ( request, response ) => { app.get( '/user/2fa/check', ( request, response ) => {
@@ -148,12 +147,16 @@ module.exports = ( app, settings ) => {
} ); } );
app.get( '/user/resendEmail', ( req, res ) => { app.get( '/user/resendEmail', ( req, res ) => {
if ( req.session.username ) {
( async () => { ( async () => {
let tok = generator.generateToken( 60 ); let tok = generator.generateToken( 60 );
mailTokens[ tok ] = req.session.username; mailTokens[ tok ] = req.session.username;
mailManager.sendMail( req.session.username, await twoFA.generateSignupEmail( tok, settings.yourDomain, settings.name ), 'Confirm your email', settings.mailSender ); mailManager.sendMail( req.session.username, await twoFA.generateSignupEmail( tok, settings.yourDomain, settings.name ), 'Confirm your email', settings.mailSender );
} )(); } )();
res.send( 'sent' ); res.send( 'sent' );
} else {
res.status( 403 ).send( 'unauthorised' );
}
} ); } );
app.post( '/user/signup', bodyParser.json(), ( request, response ) => { app.post( '/user/signup', bodyParser.json(), ( request, response ) => {
@@ -202,7 +205,7 @@ module.exports = ( app, settings ) => {
response.sendFile( path.join( __dirname + '/../ui/en/signup/disallowTwoFA.html' ) ); response.sendFile( path.join( __dirname + '/../ui/en/signup/disallowTwoFA.html' ) );
} }
} else { } else {
response.sendFile( path.join( __dirname + '/../ui/en/signup/invalid.html' ) ); response.status( 400 ).sendFile( path.join( __dirname + '/../ui/en/signup/invalid.html' ) );
} }
} ); } );
@@ -214,7 +217,16 @@ module.exports = ( app, settings ) => {
response.send( 'ok' ); response.send( 'ok' );
} }
} else { } else {
response.send( 'unauthorised' ); response.status( 403 ).send( 'unauthorised' );
}
} );
app.post( '/user/settings', bodyParser.json(), ( req, res ) => {
if ( req.session.username ) {
db.writeDataSimple( 'users', 'email', req.session.username, req.body );
res.send( 'ok' );
} else {
res.status( 403 ).send( 'unauthorised' );
} }
} ); } );

View File

@@ -12,7 +12,6 @@ import { defineStore } from "pinia";
export const useBackendStore = defineStore ( 'backend', { export const useBackendStore = defineStore ( 'backend', {
state: () => ( { 'guestPurchase': false, 'guestPurchaseAllowed': false } ), state: () => ( { 'guestPurchase': false, 'guestPurchaseAllowed': false } ),
getters: { getters: {
getVisitedSetupPages: ( state ) => state.visitedSetupPages,
getIsGuestPurchase: ( state ) => state.guestPurchase, getIsGuestPurchase: ( state ) => state.guestPurchase,
getIsGuestPurchaseAllowed: ( state ) => state.guestPurchaseAllowed, getIsGuestPurchaseAllowed: ( state ) => state.guestPurchaseAllowed,
}, },

View File

@@ -1,15 +1,22 @@
<template> <template>
<div> <div>
<h1>Account</h1> <h1>Account</h1>
<p>Welcome, {{ accountData.first_name }} {{ accountData.name }}!</p> <p>Welcome, {{ accountData.first_name }} {{ accountData.name }}! <button @click="logout()">Log out</button></p>
<button @click="resendMailConfirmation()" v-if="!accountData.mail_confirmed">Resend confirmation email</button> <button @click="resendMailConfirmation()" v-if="!accountData.mail_confirmed">Resend confirmation email</button>
<div class="userData-wrapper">
<table class="userData"> <table class="userData">
<tr> <tr>
<td> <td>
Email Email
</td> </td>
<td> <td>
<div v-if="!isEditingAccount">
{{ accountData.email }} {{ accountData.email }}
</div>
<div v-else>
<input type="email" name="email" id="email" v-model="accountData.email" @keyup="emailLiveChecker()"><br><br>
<p v-if="emailStatus" class="email-status">{{ emailStatus }}</p>
</div>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -17,7 +24,13 @@
Name Name
</td> </td>
<td> <td>
<div v-if="!isEditingAccount">
{{ accountData.first_name }} {{ accountData.name }} {{ accountData.first_name }} {{ accountData.name }}
</div>
<div v-else>
<input type="text" name="first_name" id="first_name" v-model="accountData.first_name">
<input type="text" name="name" id="name" v-model="accountData.name">
</div>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -25,21 +38,42 @@
Email notifications Email notifications
</td> </td>
<td> <td>
<div v-if="accountData.marketing">Enabled</div> <div v-if="!isEditingAccount">
<div v-if="accountData.marketing == 'true'">Enabled</div>
<div v-else>Disabled</div> <div v-else>Disabled</div>
</div>
<select name="emailNotification" id="emailNotification" v-model="accountData.marketing" v-else>
<option value="true">Enabled</option>
<option value="false">Disabled</option>
</select>
</td> </td>
</tr> </tr>
<tr> <tr v-if="accountData.mail_confirmed && twoFASetting !== 'disable'">
<td> <td>
Two-Factor Authentication Two-Factor Authentication
</td> </td>
<td> <td>
<div v-if="!isEditingAccount">
<div v-if="accountData.two_fa == 'enhanced'">Enhanced</div> <div v-if="accountData.two_fa == 'enhanced'">Enhanced</div>
<div v-else-if="accountData.two_fa == 'standard'">Standard</div> <div v-else-if="accountData.two_fa == 'standard'">Standard</div>
<div v-else>Disabled</div> <div v-else>Disabled</div>
</div>
<select name="two_fa" id="two_fa" v-model="accountData.two_fa" v-else>
<option value="enhanced">Enhanced</option>
<option value="standard">Standard</option>
<option value="disabled" v-if="twoFASetting === 'allow'">Disabled</option>
</select>
</td> </td>
</tr> </tr>
</table> </table>
<div>
<button @click="toggleEditing">
<div v-if="!isEditingAccount">Edit</div>
<div v-else>Cancel</div>
</button>
<button @click="save()" v-if="isEditingAccount">Save</button>
</div>
</div>
<notifications ref="notification" location="topright" size="bigger"></notifications> <notifications ref="notification" location="topright" size="bigger"></notifications>
<popups ref="popups" size="big" @data="data => { savePwd( data ) }"></popups> <popups ref="popups" size="big" @data="data => { savePwd( data ) }"></popups>
</div> </div>
@@ -53,9 +87,23 @@
</style> </style>
<style scoped> <style scoped>
.userData-wrapper {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.userData { .userData {
width: 50%; width: 50%;
} }
.email-status {
margin-top: -10px;
color: red;
font-style: italic;
margin-bottom: 20px;
}
</style> </style>
<script> <script>
@@ -68,6 +116,9 @@
data () { data () {
return { return {
accountData: {}, accountData: {},
isEditingAccount: false,
emailStatus: '',
twoFASetting: 'allow',
} }
}, },
components: { components: {
@@ -78,6 +129,38 @@
...mapStores( useUserStore ) ...mapStores( useUserStore )
}, },
methods: { methods: {
logout() {
fetch( '/user/logout' ).then( res => {
this.$router.push( '/login' );
this.userStore.setUserAuth( false );
} );
},
toggleEditing () {
if ( this.isEditingAccount ) {
this.loadData();
} else {
this.emailLiveChecker();
}
this.isEditingAccount = !this.isEditingAccount;
},
save() {
let fetchOptions = {
method: 'post',
body: JSON.stringify( this.accountData ),
headers: {
'Content-Type': 'application/json',
'charset': 'utf-8'
}
};
fetch( localStorage.getItem( 'url' ) + '/user/settings', fetchOptions ).then( res => {
if ( res.status === 200 ) {
this.$refs.notification.createNotification( 'Settings updated!', 5, 'ok', 'normal' );
this.isEditingAccount = false;
} else {
this.$refs.notification.createNotification( 'An error occurred whilst updating the settings. Please retry', 20, 'error', 'normal' );
}
} );
},
resendMailConfirmation() { resendMailConfirmation() {
fetch( localStorage.getItem( 'url' ) + '/user/resendEmail' ).then( res => { fetch( localStorage.getItem( 'url' ) + '/user/resendEmail' ).then( res => {
if ( res.status === 200 ) { if ( res.status === 200 ) {
@@ -86,19 +169,74 @@
this.$refs.notification.createNotification( 'An error occurred whilst sending the confirmation mail. Please retry', 20, 'error', 'normal' ); this.$refs.notification.createNotification( 'An error occurred whilst sending the confirmation mail. Please retry', 20, 'error', 'normal' );
} }
} ); } );
},
emailLiveChecker () {
setTimeout( () => {
if ( this.checkEmail() ) {
this.emailStatus = '';
} else {
this.emailStatus = 'Invalid email address';
}
}, 100 );
},
checkEmail () {
const mail = this.accountData.email ?? '';
let stat = { 'atPos': 0, 'topLevelPos': 0 };
for ( let l in mail ) {
if ( stat[ 'atPos' ] > 0 ) {
if ( mail[ l ] === '@' ) {
return false;
} else if ( mail[ l ] === '.' ) {
if ( stat[ 'topLevelPos' ] > 0 ) {
if ( l > stat[ 'topLevelPos' ] + 2 ) {
stat[ 'topLevelPos' ] = parseInt( l );
} else {
return false;
}
} else {
if ( l > stat[ 'atPos' ] + 2 ) {
stat[ 'topLevelPos' ] = parseInt( l );
} else {
return false;
}
}
} else if ( !( /[a-z]/.test( mail[ l ] ) || /[A-Z]/.test( mail[ l ] ) || /[1-9]/.test( mail[ l ] ) ) ) {
return false
}
} else {
if ( mail[ l ] === '@' ) {
if ( l > 2 ) {
stat[ 'atPos' ] = parseInt( l );
} else {
return false;
}
} else if ( !( /[a-z]/.test( mail[ l ] ) || /[A-Z]/.test( mail[ l ] ) || /[1-9]/.test( mail[ l ] ) || mail[ l ] === '.' ) ) {
return false;
}
}
}
if ( mail.length > stat[ 'topLevelPos' ] + 2 && stat[ 'topLevelPos' ] > 0 && stat[ 'atPos' ] > 0 ) {
return true;
} else {
return false;
} }
}, },
created () { loadData () {
// TODO: FUTURE Also get all orders of user (using join functions) // TODO: FUTURE Also get all orders of user (using join functions)
fetch( localStorage.getItem( 'url' ) + '/settings/2fa' ).then( res => {
if ( res.status === 200 ) {
res.text().then( text => {
this.twoFASetting = text;
} );
}
} );
fetch( localStorage.getItem( 'url' ) + '/user/details' ).then( res => { fetch( localStorage.getItem( 'url' ) + '/user/details' ).then( res => {
if ( res.status === 200 ) { if ( res.status === 200 ) {
res.json().then( data => { res.json().then( data => {
if ( data.status ) { if ( data.status ) {
this.accountData = data.data; this.accountData = data.data;
if ( this.accountData.marketing ) { if ( !this.accountData.two_fa ) {
this.accountData.marketing = true; this.accountData.two_fa = 'disabled';
} else {
this.accountData.marketing = false;
} }
if ( !data.data.mail_confirmed ) { if ( !data.data.mail_confirmed ) {
setTimeout( () => { setTimeout( () => {
@@ -123,5 +261,9 @@
this.userStore.setUser2fa( false ); this.userStore.setUser2fa( false );
} }
} }
},
created () {
this.loadData();
}
} }
</script> </script>