Updated dependencies. Introduced a styled 404 page. Implemented a new authorization system including separate login flow. Implemented flash message system to removal all query url parameters. Made SID more persistent between sessions. Implemented new vouchers overview. Improved color scheme for info and error flash messages. Updated README.md

This commit is contained in:
Glenn de Haan
2024-01-22 19:27:42 +01:00
parent 172473536b
commit 03fb5356ef
12 changed files with 549 additions and 196 deletions

135
server.js
View File

@@ -3,8 +3,7 @@
*/
const express = require('express');
const multer = require('multer');
const { v4: uuidv4 } = require('uuid');
const app = express();
const cookieParser = require('cookie-parser');
/**
* Import own modules
@@ -14,6 +13,18 @@ const types = require('./modules/types');
const time = require('./modules/time');
const unifi = require('./modules/unifi');
/**
* Import own middlewares
*/
const authorization = require('./middlewares/authorization');
const flashMessage = require('./middlewares/flashMessage');
const sid = require('./middlewares/sid');
/**
* Setup Express app
*/
const app = express();
/**
* Define global functions and variables
*/
@@ -54,11 +65,31 @@ app.set('views', `${__dirname}/template`);
*/
app.use(multer().none());
/**
* Enable cookie-parser
*/
app.use(cookieParser());
/**
* Enable flash-message
*/
app.use(flashMessage);
/**
* Enable session id
*/
app.use(sid);
/**
* Request logger
*/
app.use((req, res, next) => {
console.log(`[Web]: ${req.originalUrl}`);
if(req.originalUrl.includes('/images') || req.originalUrl.includes('/dist') || req.originalUrl.includes('/manifest')) {
console.log(`[Web]: ${req.originalUrl}`);
} else {
console.log(`[Web][${req.sid}]: ${req.originalUrl}`);
}
next();
});
@@ -71,20 +102,21 @@ app.use(express.static(`${__dirname}/public`));
* Configure routers
*/
app.get('/', (req, res) => {
res.redirect(302, '/voucher');
});
app.get('/login', (req, res) => {
const hour = new Date().getHours();
const timeHeader = hour < 12 ? 'Good Morning' : hour < 18 ? 'Good Afternoon' : 'Good Evening';
res.render('home', {
error: typeof req.query.error === 'string' && req.query.error !== '',
error_text: req.query.error || '',
res.render('login', {
error: req.flashMessage.type === 'error',
error_text: req.flashMessage.message || '',
banner_image: process.env.BANNER_IMAGE || `/images/bg-${random(1, 10)}.jpg`,
app_header: timeHeader,
sid: uuidv4(),
timeConvert: time,
voucher_types: voucherTypes
sid: req.sid
});
});
app.post('/', async (req, res) => {
app.post('/login', async (req, res) => {
if(typeof req.body === "undefined") {
res.status(400).send();
return;
@@ -93,44 +125,74 @@ app.post('/', async (req, res) => {
const passwordCheck = req.body.password === (process.env.SECURITY_CODE || "0000");
if(!passwordCheck) {
res.redirect(encodeURI(`/?error=Invalid password!`));
res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Password Invalid!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, '/login');
return;
}
res.cookie('authorization', req.body.password, {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, '/voucher');
});
app.get('/voucher', [authorization], async (req, res) => {
const hour = new Date().getHours();
const timeHeader = hour < 12 ? 'Good Morning' : hour < 18 ? 'Good Afternoon' : 'Good Evening';
res.render('voucher', {
info: req.flashMessage.type === 'info',
info_text: req.flashMessage.message || '',
error: req.flashMessage.type === 'error',
error_text: req.flashMessage.message || '',
banner_image: process.env.BANNER_IMAGE || `/images/bg-${random(1, 10)}.jpg`,
app_header: timeHeader,
sid: req.sid,
timeConvert: time,
voucher_types: voucherTypes,
vouchers_popup: false
});
});
app.post('/voucher', [authorization], async (req, res) => {
if(typeof req.body === "undefined") {
res.status(400).send();
return;
}
const typeCheck = (process.env.VOUCHER_TYPES || '480,0,,,;').split(';').includes(req.body['voucher-type']);
if(!typeCheck) {
res.redirect(encodeURI(`/?error=Unknown type!`));
res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Unknown Type!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, '/voucher');
return;
}
res.redirect(encodeURI(`/voucher?code=${req.body.password}&type=${req.body['voucher-type']}`));
// Create voucher code
const voucherCode = await unifi(types(req.body['voucher-type'], true)).catch((e) => {
res.cookie('flashMessage', JSON.stringify({type: 'error', message: e}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, '/voucher');
});
if(voucherCode) {
res.cookie('flashMessage', JSON.stringify({type: 'info', message: `Voucher Created: ${voucherCode}`}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, '/voucher');
}
});
app.get('/voucher', async (req, res) => {
if(req.query.code !== (process.env.SECURITY_CODE || "0000")) {
res.status(403).send();
return;
}
if(!(process.env.VOUCHER_TYPES || '480,0,,,;').split(';').includes(req.query.type)) {
res.status(400).send();
return;
}
app.get('/vouchers', [authorization], async (req, res) => {
const hour = new Date().getHours();
const timeHeader = hour < 12 ? 'Good Morning' : hour < 18 ? 'Good Afternoon' : 'Good Evening';
const voucherCode = await unifi(types(req.query.type, true));
res.render('voucher', {
error: typeof req.query.error === 'string' && req.query.error !== '',
error_text: req.query.error || '',
banner_image: process.env.BANNER_IMAGE || `/images/bg-${random(1, 10)}.jpg`,
app_header: timeHeader,
code: req.query.code,
type: req.query.type,
voucher_code: voucherCode,
sid: uuidv4()
const vouchers = await unifi('', false).catch((e) => {
res.cookie('flashMessage', JSON.stringify({type: 'error', message: e}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, '/voucher');
});
if(vouchers) {
res.render('voucher', {
info: req.flashMessage.type === 'info',
info_text: req.flashMessage.message || '',
error: req.flashMessage.type === 'error',
error_text: req.flashMessage.message || '',
banner_image: process.env.BANNER_IMAGE || `/images/bg-${random(1, 10)}.jpg`,
app_header: timeHeader,
sid: req.sid,
timeConvert: time,
voucher_types: voucherTypes,
vouchers_popup: true,
vouchers
});
}
});
/**
@@ -138,7 +200,10 @@ app.get('/voucher', async (req, res) => {
*/
app.use((req, res) => {
res.status(404);
res.send('Not Found!');
res.render('404', {
banner_image: process.env.BANNER_IMAGE || `/images/bg-${random(1, 10)}.jpg`,
sid: req.sid
});
});
/**