mirror of
https://github.com/janishutz/libreevent.git
synced 2025-11-25 05:14:23 +00:00
user account page done (- styling)
This commit is contained in:
@@ -150,7 +150,7 @@ class SQLDB {
|
||||
command = 'UPDATE ' + table + ' SET ';
|
||||
let updatedValues = '';
|
||||
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 += ' WHERE ' + operation.property + ' = ' + this.sqlConnection.escape( operation.searchQuery );
|
||||
|
||||
@@ -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 } );
|
||||
} );
|
||||
} else {
|
||||
console.log( 'unauthorised' );
|
||||
response.status( 403 ).sendFile( path.join( __dirname + '/../ui/en/errors/403.html' ) );
|
||||
}
|
||||
} );
|
||||
@@ -84,7 +83,7 @@ module.exports = ( app, settings ) => {
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
response.send( 'missingCredentials' );
|
||||
response.status( 400 ).send( 'missingCredentials' );
|
||||
}
|
||||
} );
|
||||
|
||||
@@ -101,7 +100,7 @@ module.exports = ( app, settings ) => {
|
||||
} else if ( tokType === 'enhanced' ) {
|
||||
response.sendFile( path.join( __dirname + '/../ui/en/2fa/2faEnhanced.html' ) );
|
||||
} 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';
|
||||
}
|
||||
response.send( 'ok' );
|
||||
} else response.send( 'wrong' );
|
||||
} else response.status( 403 ).send( 'wrong' );
|
||||
} );
|
||||
|
||||
app.get( '/user/2fa/check', ( request, response ) => {
|
||||
@@ -148,12 +147,16 @@ module.exports = ( app, settings ) => {
|
||||
} );
|
||||
|
||||
app.get( '/user/resendEmail', ( req, res ) => {
|
||||
if ( req.session.username ) {
|
||||
( async () => {
|
||||
let tok = generator.generateToken( 60 );
|
||||
mailTokens[ tok ] = req.session.username;
|
||||
mailManager.sendMail( req.session.username, await twoFA.generateSignupEmail( tok, settings.yourDomain, settings.name ), 'Confirm your email', settings.mailSender );
|
||||
} )();
|
||||
res.send( 'sent' );
|
||||
} else {
|
||||
res.status( 403 ).send( 'unauthorised' );
|
||||
}
|
||||
} );
|
||||
|
||||
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' ) );
|
||||
}
|
||||
} 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' );
|
||||
}
|
||||
} 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' );
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import { defineStore } from "pinia";
|
||||
export const useBackendStore = defineStore ( 'backend', {
|
||||
state: () => ( { 'guestPurchase': false, 'guestPurchaseAllowed': false } ),
|
||||
getters: {
|
||||
getVisitedSetupPages: ( state ) => state.visitedSetupPages,
|
||||
getIsGuestPurchase: ( state ) => state.guestPurchase,
|
||||
getIsGuestPurchaseAllowed: ( state ) => state.guestPurchaseAllowed,
|
||||
},
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<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>
|
||||
<div class="userData-wrapper">
|
||||
<table class="userData">
|
||||
<tr>
|
||||
<td>
|
||||
Email
|
||||
</td>
|
||||
<td>
|
||||
<div v-if="!isEditingAccount">
|
||||
{{ 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>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -17,7 +24,13 @@
|
||||
Name
|
||||
</td>
|
||||
<td>
|
||||
<div v-if="!isEditingAccount">
|
||||
{{ 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>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -25,21 +38,42 @@
|
||||
Email notifications
|
||||
</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>
|
||||
<select name="emailNotification" id="emailNotification" v-model="accountData.marketing" v-else>
|
||||
<option value="true">Enabled</option>
|
||||
<option value="false">Disabled</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr v-if="accountData.mail_confirmed && twoFASetting !== 'disable'">
|
||||
<td>
|
||||
Two-Factor Authentication
|
||||
</td>
|
||||
<td>
|
||||
<div v-if="!isEditingAccount">
|
||||
<div v-if="accountData.two_fa == 'enhanced'">Enhanced</div>
|
||||
<div v-else-if="accountData.two_fa == 'standard'">Standard</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>
|
||||
</tr>
|
||||
</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>
|
||||
<popups ref="popups" size="big" @data="data => { savePwd( data ) }"></popups>
|
||||
</div>
|
||||
@@ -53,9 +87,23 @@
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.userData-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.userData {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.email-status {
|
||||
margin-top: -10px;
|
||||
color: red;
|
||||
font-style: italic;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -68,6 +116,9 @@
|
||||
data () {
|
||||
return {
|
||||
accountData: {},
|
||||
isEditingAccount: false,
|
||||
emailStatus: '',
|
||||
twoFASetting: 'allow',
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -78,6 +129,38 @@
|
||||
...mapStores( useUserStore )
|
||||
},
|
||||
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() {
|
||||
fetch( localStorage.getItem( 'url' ) + '/user/resendEmail' ).then( res => {
|
||||
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' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
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)
|
||||
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 => {
|
||||
if ( res.status === 200 ) {
|
||||
res.json().then( data => {
|
||||
if ( data.status ) {
|
||||
this.accountData = data.data;
|
||||
if ( this.accountData.marketing ) {
|
||||
this.accountData.marketing = true;
|
||||
} else {
|
||||
this.accountData.marketing = false;
|
||||
if ( !this.accountData.two_fa ) {
|
||||
this.accountData.two_fa = 'disabled';
|
||||
}
|
||||
if ( !data.data.mail_confirmed ) {
|
||||
setTimeout( () => {
|
||||
@@ -123,5 +261,9 @@
|
||||
this.userStore.setUser2fa( false );
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.loadData();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user