diff --git a/src/server/admin/adminAPIRoutes.js b/src/server/admin/adminAPIRoutes.js index 75dcb60..892f915 100644 --- a/src/server/admin/adminAPIRoutes.js +++ b/src/server/admin/adminAPIRoutes.js @@ -9,13 +9,14 @@ const posth = require( './api/postHandler.js' ); const geth = require( './api/getHandler.js' ); -const postHandler = new posth(); const path = require( 'path' ); const bodyParser = require( 'body-parser' ); const mlt = require( 'multer' ); const multer = mlt(); const fs = require( 'fs' ); -const getHandler = new geth( JSON.parse( fs.readFileSync( path.join( __dirname + '/../config/settings.config.json' ) ) ) ); +const settings = JSON.parse( fs.readFileSync( path.join( __dirname + '/../config/settings.config.json' ) ) ); +const getHandler = new geth( settings ); +const postHandler = new posth( settings ); // settings is missing in arguments which shouldn't pose any problem @@ -39,6 +40,7 @@ module.exports = ( app ) => { postHandler.handleCall( req.params.call, req.body, req.query.lang ).then( data => { res.send( data ); } ).catch( error => { + console.error( error ); res.status( error.code ).send( error.error ); } ); } else { diff --git a/src/server/admin/api/postHandler.js b/src/server/admin/api/postHandler.js index 653a794..7bbb165 100644 --- a/src/server/admin/api/postHandler.js +++ b/src/server/admin/api/postHandler.js @@ -8,10 +8,12 @@ */ const db = require( '../../backend/db/db.js' ); +const fs = require( 'fs' ); +const path = require( 'path' ); class POSTHandler { - constructor () { - + constructor ( settings ) { + this.settings = settings; } handleCall ( call, data, lang ) { @@ -113,8 +115,12 @@ class POSTHandler { } else if ( call === 'deleteAdminAccount' ) { // TODO: Finish } else if ( call === 'updateSettings' ) { - // TODO: Finish + this.settings[ 'twoFA' ] = data.twoFA; + this.settings[ 'currency' ] = data.currency; + this.settings[ 'payments' ] = data.payments; + fs.writeFileSync( path.join( __dirname + '/../../config/settings.config.json' ), JSON.stringify( this.settings ) ); // TODO: Parse all events and update currency + resolve( 'ok' ); } else { reject( { 'code': 404, 'error': 'Route not found' } ); } diff --git a/src/server/backend/plugins/payments/payrexx/config.payments.json b/src/server/backend/plugins/payments/payrexx/config.payments.json new file mode 100644 index 0000000..07f754e --- /dev/null +++ b/src/server/backend/plugins/payments/payrexx/config.payments.json @@ -0,0 +1,4 @@ +{ + "APISecret": "", + "instance": "" +} \ No newline at end of file diff --git a/src/server/backend/plugins/payments/payrexx/module.payrexx.js b/src/server/backend/plugins/payments/payrexx/module.payrexx.js index 4757eab..de17744 100644 --- a/src/server/backend/plugins/payments/payrexx/module.payrexx.js +++ b/src/server/backend/plugins/payments/payrexx/module.payrexx.js @@ -13,7 +13,7 @@ const qs = require( 'qs' ); const axios = require( 'axios' ); const Base64 = require( 'crypto-js/enc-base64' ); const hmacSHA256 = require( 'crypto-js/hmac-sha256' ); -const payrexxConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'payrexx' ]; +const payrexxConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/config.payments.secret.json' ) ) ); const baseUrl = 'https://api.payrexx.com/v1.0/'; const instance = payrexxConfig.instance; diff --git a/src/server/backend/plugins/payments/payrexx/payrexxRoutes.js b/src/server/backend/plugins/payments/payrexx/payrexxRoutes.js index baa6cde..a2eb63c 100644 --- a/src/server/backend/plugins/payments/payrexx/payrexxRoutes.js +++ b/src/server/backend/plugins/payments/payrexx/payrexxRoutes.js @@ -7,10 +7,11 @@ * */ -const fs = require( 'fs' ); -const path = require( 'path' ); const db = require( '../../../db/db.js' ); -const payrexxConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'payrexx' ]; +// const fs = require( 'fs' ); +// const path = require( 'path' ); +// const payrexxConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'payrexx' ]; +// TODO: Verify that it works with temporary site on webhosting account const bodyParser = require( 'body-parser' ); const ticket = require( '../../../tickets/ticketGenerator.js' ); const payrexxModule = require( './module.payrexx.js' ); @@ -32,7 +33,6 @@ module.exports = ( app, settings ) => { 'failedRedirectUrl': settings.yourDomain + '/payments/failed', 'currency': settings.currency, 'basket': [], - 'pm': payrexxConfig.paymentMethods, 'amount': 0, }; diff --git a/src/server/backend/plugins/payments/stripe/config.payments.json b/src/server/backend/plugins/payments/stripe/config.payments.json new file mode 100644 index 0000000..653b7cd --- /dev/null +++ b/src/server/backend/plugins/payments/stripe/config.payments.json @@ -0,0 +1,4 @@ +{ + "APIKey": "", + "endpointSecret": "" +} \ No newline at end of file diff --git a/src/server/backend/plugins/payments/stripe/stripeRoutes.js b/src/server/backend/plugins/payments/stripe/stripeRoutes.js index adf9095..b25e0e5 100644 --- a/src/server/backend/plugins/payments/stripe/stripeRoutes.js +++ b/src/server/backend/plugins/payments/stripe/stripeRoutes.js @@ -10,7 +10,8 @@ const fs = require( 'fs' ); const path = require( 'path' ); const db = require( '../../../db/db.js' ); -const stripeConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'stripe' ]; +// TODO: update config files to non-secret version for final version +const stripeConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/config.payments.secret.json' ) ) ); const stripe = require( 'stripe' )( stripeConfig[ 'APIKey' ] ); const bodyParser = require( 'body-parser' ); const ticket = require( '../../../tickets/ticketGenerator.js' ); diff --git a/src/server/config/payments.config.json b/src/server/config/payments.config.json deleted file mode 100644 index 9b31ed4..0000000 --- a/src/server/config/payments.config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "stripe": { - "APIKey": "", - "endpointSecret": "" - }, - "payrexx": { - "APISecret": "", - "instance": "", - "pm": [] - } -} \ No newline at end of file diff --git a/src/server/config/settings.config.json b/src/server/config/settings.config.json index 4a05847..1b5caf5 100644 --- a/src/server/config/settings.config.json +++ b/src/server/config/settings.config.json @@ -1,13 +1 @@ -{ - "init": true, - "twoFA": "allow", - "setupKey": "hello world", - "twoFAMode": "enhanced", - "db": "mysql", - "payments": "payrexx", - "name": "libreevent", - "yourDomain": "http://localhost:8080", - "mailSender": "libreevent ", - "maxTickets": 10, - "currency": "CHF" -} \ No newline at end of file +{"init":true,"twoFA":"enforce","setupKey":"hello world","twoFAMode":"enhanced","db":"mysql","payments":"stripe","name":"libreevent","yourDomain":"http://localhost:8080","mailSender":"libreevent ","maxTickets":10,"currency":"CHF"} \ No newline at end of file diff --git a/src/webapp/main/src/views/admin/SettingsView.vue b/src/webapp/main/src/views/admin/SettingsView.vue index a874088..9063d6a 100644 --- a/src/webapp/main/src/views/admin/SettingsView.vue +++ b/src/webapp/main/src/views/admin/SettingsView.vue @@ -26,6 +26,7 @@ +

Detailed explanation of payment gateways can be found here. You may install more payment gateway integrations in the plugins section. Only one may be used at any given time.

@@ -42,6 +43,7 @@
+ @@ -49,6 +51,7 @@ import settings from '@/components/settings/settings.vue'; import popups from '@/components/notifications/popups.vue'; import rightClickMenu from '@/components/settings/rightClickMenu.vue'; + import notifications from '@/components/notifications/notifications.vue'; export default { name: 'adminSettingsView', @@ -56,6 +59,7 @@ settings, popups, rightClickMenu, + notifications, }, data () { return { @@ -66,44 +70,44 @@ 'display': 'Require Two-Factor-Authentication of user', 'id': '2fa', 'tooltip':'Control whether or not users are required to use Two-Factor-Authentication. Defaults to "User can decide", which is recommended', - 'value': 'always', + 'value': 'enforce', 'type': 'select', 'restrictions': { - 'always': { + 'enforce': { 'displayName':'Always require', - 'value': 'always' + 'value': 'enforce' }, - 'userDecided': { + 'allow': { 'displayName':'User can decide', - 'value': 'userDecided' + 'value': 'allow' }, - 'never': { + 'disable': { 'displayName':'Disable', - 'value': 'never' + 'value': 'disable' }, } }, - 'addressRequired': { - 'display': 'Require user to provide address?', - 'id': 'addressRequired', - 'tooltip':'With this toggle you may specify whether or not a user has to provide their address when purchasing something. (Keep GDPR in mind when processing data!)', - 'value': false, - 'type': 'toggle', - }, - 'phoneNumberRequired': { - 'display': 'Require user to provide phone number?', - 'id': 'phoneNumberRequired', - 'tooltip':'With this toggle you may specify whether or not a user has to provide their phone number when purchasing something. (Keep GDPR in mind when processing data!)', - 'value': false, - 'type': 'toggle', - }, - 'dobRequired': { - 'display': 'Require user to provide their birth date?', - 'id': 'dobRequired', - 'tooltip':'With this toggle you may specify whether or not a user has to provide their date of birth when purchasing something. (Keep GDPR in mind when processing data!)', - 'value': false, - 'type': 'toggle', - }, + // 'addressRequired': { + // 'display': 'Require user to provide address?', + // 'id': 'addressRequired', + // 'tooltip':'With this toggle you may specify whether or not a user has to provide their address when purchasing something. (Keep GDPR in mind when processing data!)', + // 'value': false, + // 'type': 'toggle', + // }, + // 'phoneNumberRequired': { + // 'display': 'Require user to provide phone number?', + // 'id': 'phoneNumberRequired', + // 'tooltip':'With this toggle you may specify whether or not a user has to provide their phone number when purchasing something. (Keep GDPR in mind when processing data!)', + // 'value': false, + // 'type': 'toggle', + // }, + // 'dobRequired': { + // 'display': 'Require user to provide their birth date?', + // 'id': 'dobRequired', + // 'tooltip':'With this toggle you may specify whether or not a user has to provide their date of birth when purchasing something. (Keep GDPR in mind when processing data!)', + // 'value': false, + // 'type': 'toggle', + // }, 'currency': { 'display': 'Currency', 'id': 'currency', @@ -118,14 +122,14 @@ 'value': 'stripe', 'type': 'select', 'restrictions': { + 'payrexx': { + 'displayName':'Payrexx', + 'value': 'payrexx' + }, 'stripe': { 'displayName':'Stripe', 'value': 'stripe' }, - 'adyen': { - 'displayName':'Payrexx', - 'value': 'payrexx' - }, } }, } @@ -162,21 +166,12 @@ 'value': false, 'type': 'toggle', }, - 'entryControl': { - 'display': 'Entry control', - 'id': 'entryControl', - 'tooltip':'Change this setting to allow or disallow the selected user to execute entry control at the entrance to your event location.', - 'value': true, - 'type': 'toggle', - }, } , 'settings' ); }, showPaymentSettings () { - this.$refs.popup.openPopup( 'Payment gateway settings', { - 'link': '/payments/settings', - } - , 'iframe' ); + // TODO: Load payment gateway settings from server + this.$refs.popup.openPopup( 'Payment gateway settings', {}, 'string' ); }, createAccount() { this.$refs.popup.openPopup( 'Create new admin user', { @@ -240,7 +235,37 @@ openRightClickMenu( id, event ) { this.$refs.rclk.openRightClickMenu( event, { 'edit': { 'command': 'openPermissions', 'symbol': 'edit', 'display': 'Edit permissions' }, 'delete': { 'command': 'deleteUser', 'symbol': 'delete', 'display': 'Delete User' } } ) this.currentlyOpenMenu = id; + }, + loadData() { + fetch( '/admin/getAPI/getSettings' ).then( res => { + if ( res.status === 200 ) { + res.json().then( json => { + this.settings[ '2fa' ].value = json.twoFA; + this.settings.currency.value = json.currency; + this.settings.paymentGateway.value = json.payments; + } ); + } + } ); + }, + save() { + let fetchOptions = { + method: 'post', + body: JSON.stringify( { 'twoFA': this.settings[ '2fa' ].value, 'currency': this.settings.currency.value, 'payments': this.settings.paymentGateway.value } ), + headers: { + 'Content-Type': 'application/json', + 'charset': 'utf-8' + } + }; + fetch( localStorage.getItem( 'url' ) + '/admin/API/updateSettings', fetchOptions ).then( res => { + if ( res.status === 200 ) { + this.$refs.notification.createNotification( 'Saved settings successfully. Restart libreevent to apply changes', 20, 'ok', 'normal' ); + this.loadData(); + } + } ); } + }, + created () { + this.loadData(); } }; // TODO: Load gateways and settings in general from server. diff --git a/website/src/payments.md b/website/src/payments.md index ee86d2b..e620a10 100644 --- a/website/src/payments.md +++ b/website/src/payments.md @@ -1,13 +1,13 @@ # Payments -Including many payment methods can help the user choose the one that fits them best, but can also be overwhelming and a pain to set up. So please try to use as few different payment gateways as possible. Our recommendation is either *Stripe* or *adyen* as they are the most flexible. +Including many payment methods can help the user choose the one that fits them best, but can also be overwhelming and a pain to set up. So please try to use as few different payment gateways as possible. Officially, libreevent supports *Stripe* and *Payrexx*. More payment gateways might come in the future as a plugin which can be installed by following our guide [here](&/plugins/install#payments) ## Advantages / Disadvantages of each payment gateway ### payrexx -Payrexx is a lesser known payment gateway and it is not ideal for you if you expect to have a low sales volume, as their basic plan costs you EUR 15 a month. If your sales volume is fairly high, it may be worth is as their per-transaction fees are quite a bit lower than Stripe's and they offer more payment options. -See payrexx [pricing here](https://www.payrexx.com/en/pricing/) and sign up [here](https://signup.payrexx.com). You can find a full list of supported payment methods as they should be entered in the GUI [here](https://docs.payrexx.com/developer/general-info/payment-method) +Payrexx is a Swiss, lesser known payment gateway and it is not ideal for you if you expect to have a low sales volume, as their basic plan costs you EUR 15 a month. If your sales volume is fairly high, it may be worth it as their per-transaction fees are quite a bit lower than Stripe's and they offer more payment options. +See payrexx [pricing here](https://www.payrexx.com/en/pricing/) and sign up [here](https://signup.payrexx.com). You can find a full list of supported payment methods [here](https://payrexx.com/en/paymentmethods) ### Stripe -Stripe is one of the most well known payment gateways out there and it is really easy to get started. +Stripe is one of the most well known payment gateways out there and it is really easy to get started. See all their payment methods [here](https://stripe.com/en-ch/payments/payment-methods). If you choose to use Stripe, you may follow their guides on how to set up more payment options [here](https://stripe.com/docs/payments/payment-methods/overview) See [here](https://stripe.com/en-gb/pricing) for pricing information and sign up [here](https://dashboard.stripe.com/register)