setup app complete

This commit is contained in:
2023-09-08 16:26:37 +02:00
parent 809a05c864
commit defaafdd54
12 changed files with 172 additions and 45 deletions

View File

@@ -9,13 +9,11 @@
const db = require( '../../backend/db/db.js' ); const db = require( '../../backend/db/db.js' );
const pwdmanager = require( '../pwdmanager.js' ); const pwdmanager = require( '../pwdmanager.js' );
const fs = require( 'fs' );
const path = require( 'path' );
const pm = require( '../../backend/plugins/manager.js' ); const pm = require( '../../backend/plugins/manager.js' );
const spm = require( '../startPageManager.js' ); const spm = require( '../startPageManager.js' );
const startPageManager = new spm(); const startPageManager = new spm();
const letters = [ ',', '{' ];
class POSTHandler { class POSTHandler {
constructor ( settings ) { constructor ( settings ) {
@@ -154,18 +152,7 @@ class POSTHandler {
this.settings[ 'currency' ] = data.currency; this.settings[ 'currency' ] = data.currency;
this.settings[ 'payments' ] = data.payments; this.settings[ 'payments' ] = data.payments;
this.settings[ 'ticketTimeout' ] = data.ticketTimeout; this.settings[ 'ticketTimeout' ] = data.ticketTimeout;
const settingsString = JSON.stringify( this.settings ); db.saveSettings( this.settings );
let settingsToSave = '';
for ( let letter in settingsString ) {
if ( letters.includes( settingsString[ letter ] ) ) {
settingsToSave += settingsString[ letter ] + '\n\t';
} else if ( settingsString[ letter ] === '}' ) {
settingsToSave += '\n' + settingsString[ letter ];
} else {
settingsToSave += settingsString[ letter ];
}
}
fs.writeFileSync( path.join( __dirname + '/../../config/settings.config.json' ), settingsToSave );
db.getJSONData( 'events' ).then( dat => { db.getJSONData( 'events' ).then( dat => {
let updated = dat; let updated = dat;
for ( let event in updated ) { for ( let event in updated ) {

View File

@@ -39,7 +39,8 @@ module.exports = ( app ) => {
if ( tickets[ event ] ) { if ( tickets[ event ] ) {
if ( tickets[ event ][ ticket ] ) { if ( tickets[ event ][ ticket ] ) {
if ( !tickets[ event ][ ticket ][ 'invalidated' ] ) { if ( !tickets[ event ][ ticket ][ 'invalidated' ] ) {
// TODO: invalidate ticket! tickets[ event ][ ticket ][ 'invalidated' ] = true;
db.writeDataSimple( 'orders', 'order_name', req.body.ticketID.slice( 0, req.body.ticketID.indexOf( '_' ) ), { 'tickets': JSON.stringify( tickets ) } );
res.send( 'ticketValid' ); res.send( 'ticketValid' );
} else { } else {
res.send( 'ticketInvalid' ); res.send( 'ticketInvalid' );

View File

@@ -11,6 +11,7 @@ let createSSRApp = require( 'vue' ).createSSRApp;
let renderToString = require( 'vue/server-renderer' ).renderToString; let renderToString = require( 'vue/server-renderer' ).renderToString;
const fs = require( 'fs' ); const fs = require( 'fs' );
const path = require( 'path' ); const path = require( 'path' );
const db = require( '../backend/db/db.js' );
class StartPageManager { class StartPageManager {
constructor ( settings ) { constructor ( settings ) {
@@ -42,7 +43,7 @@ class StartPageManager {
setActiveStartPage( startPageName ) { setActiveStartPage( startPageName ) {
this.settings[ 'startPage' ] = startPageName; this.settings[ 'startPage' ] = startPageName;
fs.writeFileSync( path.join( __dirname + '/../config/settings.config.json' ), JSON.stringify( this.settings ) ); db.saveSettings( this.settings );
} }
async renderStartPage( startPageName ) { async renderStartPage( startPageName ) {

View File

@@ -15,6 +15,7 @@ const cookieParser = require( 'cookie-parser' );
const http = require( 'http' ); const http = require( 'http' );
const fs = require( 'fs' ); const fs = require( 'fs' );
const token = require( './backend/token.js' ); const token = require( './backend/token.js' );
const db = require( './backend/db/db.js' );
console.log( ` console.log( `
@@ -58,7 +59,12 @@ if ( settings.setupDone ) {
} ); } );
} }
// TODO: If no init, initialize DB. if ( !settings.init ) {
db.initDB();
let mutSettings = settings;
mutSettings[ 'init' ] = true;
db.saveSettings( mutSettings );
}
// Set up static routes for static file serving (performance wise not // Set up static routes for static file serving (performance wise not

View File

@@ -14,6 +14,8 @@ const settings = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../con
const dbRef = { 'user': 'libreevent_users', 'admin': 'libreevent_admin', 'order': 'libreevent_orders', 'users': 'libreevent_users', 'orders': 'libreevent_orders', 'temp': 'libreevent_temp' }; const dbRef = { 'user': 'libreevent_users', 'admin': 'libreevent_admin', 'order': 'libreevent_orders', 'users': 'libreevent_users', 'orders': 'libreevent_orders', 'temp': 'libreevent_temp' };
const letters = [ ',', '{' ];
let dbh; let dbh;
if ( settings.db === 'mysql' ) { if ( settings.db === 'mysql' ) {
@@ -26,6 +28,14 @@ if ( settings.db === 'mysql' ) {
dbh.connect(); dbh.connect();
} }
module.exports.initDB = () => {
( async() => {
console.log( '[ DB ] Setting up...' );
await dbh.setupDB();
console.log( '[ DB ] Setting up complete!' );
} )();
};
module.exports.getDataSimple = ( db, column, searchQuery ) => { module.exports.getDataSimple = ( db, column, searchQuery ) => {
return new Promise( ( resolve, reject ) => { return new Promise( ( resolve, reject ) => {
dbh.query( { 'command': 'getFilteredData', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( data => { dbh.query( { 'command': 'getFilteredData', 'property': column, 'searchQuery': searchQuery }, dbRef[ db ] ).then( data => {
@@ -185,6 +195,21 @@ module.exports.deleteJSONDataSimple = ( db, identifier ) => {
} ); } );
}; };
module.exports.saveSettings = ( settings ) => {
const settingsString = JSON.stringify( settings );
let settingsToSave = '';
for ( let letter in settingsString ) {
if ( letters.includes( settingsString[ letter ] ) ) {
settingsToSave += settingsString[ letter ] + '\n\t';
} else if ( settingsString[ letter ] === '}' ) {
settingsToSave += '\n' + settingsString[ letter ];
} else {
settingsToSave += settingsString[ letter ];
}
}
fs.writeFileSync( path.join( __dirname + '/../../config/settings.config.json' ), settingsToSave );
};
const gc = () => { const gc = () => {
// this function acts as the database garbage collector. TicketTimeout can be changed from the GUI. // this function acts as the database garbage collector. TicketTimeout can be changed from the GUI.
this.getData( 'temp' ).then( tempData => { this.getData( 'temp' ).then( tempData => {

View File

@@ -22,7 +22,10 @@ class JSONDB {
let data = {}; let data = {};
try { try {
JSON.parse( fs.readFileSync( path.join( __dirname + '/data/db.json' ) ) ); JSON.parse( fs.readFileSync( path.join( __dirname + '/data/db.json' ) ) );
} catch ( err ) {} } catch ( err ) {
console.error( '[ JSON-DB ] CRITICAL INITIALIZATION FAILURE!' + err );
throw ( 'JSONDB failed to start!' );
}
this.db = data[ 'db' ] ?? { 'libreevent_temp': {}, 'libreevent_admin': {}, 'libreevent_orders': {}, 'libreevent_users': {} }; this.db = data[ 'db' ] ?? { 'libreevent_temp': {}, 'libreevent_admin': {}, 'libreevent_orders': {}, 'libreevent_users': {} };
this.dbIndex = data[ 'index' ] ?? { 'libreevent_temp': 0, 'libreevent_admin': 0, 'libreevent_orders': 0, 'libreevent_users': 0 }; this.dbIndex = data[ 'index' ] ?? { 'libreevent_temp': 0, 'libreevent_admin': 0, 'libreevent_orders': 0, 'libreevent_users': 0 };
this.db[ 'libreevent_temp' ] = {}; this.db[ 'libreevent_temp' ] = {};

View File

@@ -1,13 +1,13 @@
{ {
"init":false, "init":true,
"setupDone": true, "setupDone":true,
"twoFA":"enforce", "twoFA":"enforce",
"twoFAMode":"enhanced", "twoFAMode":"enhanced",
"db":"mysql", "db":"mysql",
"payments":"stripe", "payments":"stripe",
"name":"libreevent", "name":"libreevent",
"yourDomain":"http://localhost:8080", "yourDomain":"http://localhost:8080",
"mailSender":"libreevent <info@libreevent.janishutz.com>", "mailSender":"libreevent <no-reply@libreevent.janishutz.com>",
"maxTickets":10, "maxTickets":10,
"currency":"CHF", "currency":"CHF",
"gcInterval":300, "gcInterval":300,

View File

@@ -7,7 +7,9 @@
* *
*/ */
let db = null; // let db = null;
let db = require( '../backend/db/db.js' );
const pwm = require( '../admin/pwdmanager.js' );
const fs = require( 'fs' ); const fs = require( 'fs' );
const path = require( 'path' ); const path = require( 'path' );
const bodyParser = require( 'body-parser' ); const bodyParser = require( 'body-parser' );
@@ -30,7 +32,38 @@ module.exports = ( app, settings ) => {
if ( req.session.setupKeyOk ) { if ( req.session.setupKeyOk ) {
res.send( 'ok' ); res.send( 'ok' );
} else { } else {
res.status( 403 ).send( 'not authorized' ); res.status( 403 ).send( 'unauthorized' );
}
} );
app.post( '/setup/saveBasicSettings', bodyParser.json(), ( req, res ) => {
if ( req.session.setupKeyOk ) {
fs.writeFileSync( path.join( __dirname + '/../config/db.config.json' ), JSON.stringify( req.body.db ) );
fs.writeFileSync( path.join( __dirname + '/../config/mail.config.json' ), JSON.stringify( req.body.email ) );
if ( db === null ) {
db = require( '../backend/db/db.js' );
}
let updatedSettings = settings;
updatedSettings[ 'name' ] = req.body.websiteName;
updatedSettings[ 'mailSender' ] = req.body.mailDisplay;
db.saveSettings( updatedSettings );
res.send( 'ok' );
} else {
res.status( 403 ).send( 'unauthorized' );
}
} );
app.post( '/setup/saveRootAccount', bodyParser.json(), ( req, res ) => {
if ( req.session.setupKeyOk ) {
pwm.hashPassword( req.body.password ).then( hash => {
db.writeJSONData( 'rootAccount', { 'pass': hash, 'email': req.body.mail } );
let updatedSettings = settings;
updatedSettings[ 'setupDone' ] = true;
db.saveSettings( updatedSettings );
res.send( 'ok' );
} );
} else {
res.status( 403 ).send( 'unauthorized' );
} }
} ); } );

View File

@@ -5,7 +5,7 @@
</div> </div>
</template> </template>
<style> <style scoped>
.wrapper { .wrapper {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@@ -29,7 +29,7 @@
<option value="json">JSON-Database</option> <option value="json">JSON-Database</option>
</select> </select>
<form v-if="formData.dbType === 'mysql'"> <form v-if="formData.dbType === 'mysql'">
<label for="host">Database host name</label><br> <label for="host">Database host name (usually domain name or IP of webserver)</label><br>
<input type="url" name="host" id="host" v-model="formData.db.host"><br> <input type="url" name="host" id="host" v-model="formData.db.host"><br>
<label for="database">Database name</label><br> <label for="database">Database name</label><br>
<input type="text" name="database" id="database" v-model="formData.db.database"><br> <input type="text" name="database" id="database" v-model="formData.db.database"><br>
@@ -70,6 +70,7 @@
</form> </form>
<button @click="submit()" class="button">Continue</button> <button @click="submit()" class="button">Continue</button>
</div> </div>
<notifications ref="notification" location="topright" size="bigger"></notifications>
</div> </div>
</template> </template>
@@ -82,8 +83,12 @@
<script> <script>
import { useBackendStore } from '@/stores/backendStore.js'; import { useBackendStore } from '@/stores/backendStore.js';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import notifications from '../components/notifications.vue';
export default { export default {
components: {
notifications,
},
data () { data () {
return { return {
formData: { formData: {
@@ -102,10 +107,46 @@
...mapStores( useBackendStore ) ...mapStores( useBackendStore )
}, },
methods: { methods: {
submit () { submit() {
if ( this.formData.dbType === 'mysql' ) {
if ( !this.formData.db.port || !this.formData.db.host || !this.formData.db.database || !this.formData.db.user || !this.formData.db.password ) {
this.$refs.notification.createNotification( 'Database settings are not complete!', 5, 'error', 'normal' );
return;
}
}
if( this.formData.email.port && this.formData.email.host && this.formData.email.user && this.formData.email.pass
&& this.formData.dpEmail && this.formData.display && this.formData.websiteName ) {
this.formData.mailDisplay = this.formData.display + ' <' + this.formData.dpEmail + '>';
const options = {
method: 'post',
body: JSON.stringify( this.formData ),
headers: {
'Content-Type': 'application/json',
'charset': 'utf-8'
}
};
fetch( '/setup/saveBasicSettings', options ).then( res => {
if ( res.status === 200 ) {
this.continue();
} else {
this.$refs.notification.createNotification( 'Setup key incorrect!', 5, 'error', 'normal' );
}
} );
} else {
this.$refs.notification.createNotification( 'Missing entries', 5, 'error', 'normal' );
return;
}
},
continue () {
sessionStorage.setItem( 'basics', JSON.stringify( this.formData ) );
this.backendStore.addVisitedSetupPages( 'root', true ); this.backendStore.addVisitedSetupPages( 'root', true );
this.$router.push( '/setup/root' ); this.$router.push( '/setup/root' );
} }
}, },
created () {
if ( sessionStorage.getItem( 'basics' ) ) {
this.formData = JSON.parse( sessionStorage.getItem( 'basics' ) );
}
}
}; };
</script> </script>

View File

@@ -20,11 +20,13 @@
<a href="https://libreevent.janishutz.com/docs/setup/afterSetup" target="_blank">here</a></p> <a href="https://libreevent.janishutz.com/docs/setup/afterSetup" target="_blank">here</a></p>
<div class="list-wrapper"> <div class="list-wrapper">
<ul> <ul>
<li>Customize the start page</li>
<li>Choose a payment gateway and set it up</li> <li>Choose a payment gateway and set it up</li>
<li>Create a event location and an event</li> <li>Create a event location and an event</li>
<li>Create other admin accounts with less privileges</li> <li>Create other admin accounts with less privileges</li>
</ul> </ul>
</div> </div>
<button class="button" @click="cleanup()">Done</button>
</div> </div>
</div> </div>
</template> </template>
@@ -47,5 +49,12 @@
windowURL: location.protocol + '//' + location.host +'/admin/login', windowURL: location.protocol + '//' + location.host +'/admin/login',
} }
}, },
methods: {
cleanup() {
sessionStorage.removeItem( 'basics' );
sessionStorage.removeItem( 'root' );
this.$router.push( '/admin/login' );
}
}
}; };
</script> </script>

View File

@@ -154,10 +154,12 @@
} }
} }
} else { } else {
if ( confirm( 'Do you really want to proceed without having your password checked?' ) ) { if ( confirm( 'Do you really want to proceed without having your password checked? This is strongly discouraged as it essentially removes the first factor (the password) of the authentication making it much less secure.' ) ) {
if ( confirm( 'Are you really sure?' ) ) {
this.proceed(); this.proceed();
} }
} }
}
} else { } else {
this.$refs.notification.createNotification( 'Passwords do not match', 10, 'error', 'normal' ); this.$refs.notification.createNotification( 'Passwords do not match', 10, 'error', 'normal' );
} }
@@ -169,11 +171,30 @@
} }
}, },
proceed () { proceed () {
// TODO: Perform checks const options = {
method: 'post',
body: JSON.stringify( this.formData ),
headers: {
'Content-Type': 'application/json',
'charset': 'utf-8'
}
};
fetch( '/setup/saveRootAccount', options ).then( res => {
if ( res.status === 200 ) {
sessionStorage.setItem( 'basics', JSON.stringify( this.formData ) );
this.backendStore.addVisitedSetupPages( 'complete', true ); this.backendStore.addVisitedSetupPages( 'complete', true );
this.$router.push( 'complete' ); this.$router.push( 'complete' );
} else {
this.$refs.notification.createNotification( 'Setup key incorrect!', 5, 'error', 'normal' );
} }
} );
}, },
},
created () {
if ( sessionStorage.getItem( 'root' ) ) {
this.formData = JSON.parse( sessionStorage.getItem( 'root' ) );
}
}
}; };
</script> </script>