Created variables.js to replace duplicate code. Moved more cache.js logs to debug level. Fixed incorrect internal authentication state on status page. Updated dependencies. Fixed incorrect type check on /api/voucher/:type for HA users

This commit is contained in:
Glenn de Haan
2024-09-05 20:44:38 +02:00
parent 228f512ce8
commit 8492616737
13 changed files with 148 additions and 183 deletions

View File

@@ -1,16 +1,13 @@
/** /**
* Import own modules * Import base packages
*/ */
const jwt = require('../modules/jwt');
const oidc = require('express-openid-connect'); const oidc = require('express-openid-connect');
/** /**
* Global variables * Import own modules
*/ */
const authDisabled = (process.env.AUTH_DISABLE === 'true') || false; const variables = require('../modules/variables');
const oidcIssuerBaseUrl = process.env.AUTH_OIDC_ISSUER_BASE_URL || ''; const jwt = require('../modules/jwt');
const oidcAppBaseUrl = process.env.AUTH_OIDC_APP_BASE_URL || '';
const oidcClientId = process.env.AUTH_OIDC_CLIENT_ID || '';
/** /**
* Verifies if a user is signed in * Verifies if a user is signed in
@@ -28,7 +25,7 @@ module.exports = {
*/ */
web: async (req, res, next) => { web: async (req, res, next) => {
// Check if authentication is enabled & OIDC is disabled // Check if authentication is enabled & OIDC is disabled
if(!authDisabled && (oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '')) { if(!variables.authDisabled && (variables.authOidcIssuerBaseUrl === '' && variables.authOidcAppBaseUrl === '' && variables.authOidcClientId === '')) {
// Check if user has an existing authorization cookie // Check if user has an existing authorization cookie
if (!req.cookies.authorization) { if (!req.cookies.authorization) {
res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/login`); res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/login`);
@@ -49,7 +46,7 @@ module.exports = {
} }
// Check if authentication is enabled & OIDC is enabled // Check if authentication is enabled & OIDC is enabled
if(!authDisabled && (oidcIssuerBaseUrl !== '' && oidcAppBaseUrl !== '' && oidcClientId !== '')) { if(!variables.authDisabled && (variables.authOidcIssuerBaseUrl !== '' && variables.authOidcAppBaseUrl !== '' && variables.authOidcClientId !== '')) {
const middleware = oidc.requiresAuth(); const middleware = oidc.requiresAuth();
return middleware(req, res, next); return middleware(req, res, next);
} }
@@ -67,7 +64,7 @@ module.exports = {
*/ */
api: async (req, res, next) => { api: async (req, res, next) => {
// Check if authentication is enabled // Check if authentication is enabled
if(!authDisabled) { if(!variables.authDisabled) {
// Check if user has sent the authorization header // Check if user has sent the authorization header
if (!req.headers.authorization) { if (!req.headers.authorization) {
res.status(401).json({ res.status(401).json({
@@ -78,7 +75,7 @@ module.exports = {
} }
// Check if password is correct // Check if password is correct
const passwordCheck = req.headers.authorization === `Bearer ${(process.env.AUTH_TOKEN || "0000")}`; const passwordCheck = req.headers.authorization === `Bearer ${variables.authToken}`;
if (!passwordCheck) { if (!passwordCheck) {
res.status(403).json({ res.status(403).json({
error: 'Forbidden', error: 'Forbidden',

View File

@@ -6,31 +6,12 @@ const fs = require('fs');
/** /**
* Import own modules * Import own modules
*/ */
const variables = require('./variables');
const log = require('./log'); const log = require('./log');
const config = require('./config');
const logo = require('../utils/logo'); const logo = require('../utils/logo');
const types = require('../utils/types'); const types = require('../utils/types');
const time = require('../utils/time'); const time = require('../utils/time');
/**
* Define global variables
*/
const voucherTypes = types(config('voucher_types') || process.env.VOUCHER_TYPES || '480,1,,,;');
const voucherCustom = config('voucher_custom') !== null ? config('voucher_custom') : process.env.VOUCHER_CUSTOM ? process.env.VOUCHER_CUSTOM !== 'false' : true;
const webService = process.env.SERVICE_WEB ? process.env.SERVICE_WEB !== 'false' : true;
const apiService = config('service_api') || (process.env.SERVICE_API === 'true') || false;
const authDisabled = (process.env.AUTH_DISABLE === 'true') || false;
const printerType = config('printer_type') || process.env.PRINTER_TYPE || '';
const printerIp = config('printer_ip') || process.env.PRINTER_IP || '192.168.1.1';
const smtpFrom = config('smtp_from') || process.env.SMTP_FROM || '';
const smtpHost = config('smtp_host') || process.env.SMTP_HOST || '';
const smtpPort = config('smtp_port') || process.env.SMTP_PORT || 25;
const oidcIssuerBaseUrl = process.env.AUTH_OIDC_ISSUER_BASE_URL || '';
const oidcAppBaseUrl = process.env.AUTH_OIDC_APP_BASE_URL || '';
const oidcClientId = process.env.AUTH_OIDC_CLIENT_ID || '';
const oidcClientType = process.env.AUTH_OIDC_CLIENT_TYPE || 'public';
const oidcClientSecret = process.env.AUTH_OIDC_CLIENT_SECRET || '';
/** /**
* Output info to console * Output info to console
*/ */
@@ -62,43 +43,43 @@ module.exports = () => {
/** /**
* Log service status * Log service status
*/ */
log.info(`[Service][Web] ${webService ? 'Enabled!' : 'Disabled!'}`); log.info(`[Service][Web] ${variables.serviceWeb ? 'Enabled!' : 'Disabled!'}`);
log.info(`[Service][Api] ${apiService ? 'Enabled!' : 'Disabled!'}`); log.info(`[Service][Api] ${variables.serviceApi ? 'Enabled!' : 'Disabled!'}`);
/** /**
* Log voucher types * Log voucher types
*/ */
log.info('[Voucher] Loaded the following types:'); log.info('[Voucher] Loaded the following types:');
voucherTypes.forEach((type, key) => { types(variables.voucherTypes).forEach((type, key) => {
log.info(`[Voucher][Type][${key}] ${time(type.expiration)}, ${type.usage === '1' ? 'single-use' : 'multi-use'}${typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : `${typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${type.upload} kb/s` : ''}${typeof type.download !== "undefined" ? `, download bandwidth limit: ${type.download} kb/s` : ''}${typeof type.megabytes !== "undefined" ? `, quota limit: ${type.megabytes} mb` : ''}`}`); log.info(`[Voucher][Type][${key}] ${time(type.expiration)}, ${type.usage === '1' ? 'single-use' : 'multi-use'}${typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : `${typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${type.upload} kb/s` : ''}${typeof type.download !== "undefined" ? `, download bandwidth limit: ${type.download} kb/s` : ''}${typeof type.megabytes !== "undefined" ? `, quota limit: ${type.megabytes} mb` : ''}`}`);
}); });
log.info(`[Voucher][Custom] ${voucherCustom ? 'Enabled!' : 'Disabled!'}`); log.info(`[Voucher][Custom] ${variables.voucherCustom ? 'Enabled!' : 'Disabled!'}`);
/** /**
* Log auth status * Log auth status
*/ */
log.info(`[Auth] ${authDisabled ? 'Disabled!' : `Enabled! Type: ${(oidcIssuerBaseUrl !== '' || oidcAppBaseUrl !== '' || oidcClientId !== '') ? 'OIDC' : 'Internal'}`}`); log.info(`[Auth] ${variables.authDisabled ? 'Disabled!' : `Enabled! Type: ${(variables.authOidcIssuerBaseUrl !== '' || variables.authOidcAppBaseUrl !== '' || variables.authOidcClientId !== '') ? 'OIDC' : 'Internal'}`}`);
/** /**
* Verify OIDC configuration * Verify OIDC configuration
*/ */
if(oidcIssuerBaseUrl !== '' && (oidcAppBaseUrl === '' || oidcClientId === '')) { if(variables.authOidcIssuerBaseUrl !== '' && (variables.authOidcAppBaseUrl === '' || variables.authOidcClientId === '')) {
log.error(`[OIDC] Incorrect Configuration Detected!. Verify 'AUTH_OIDC_ISSUER_BASE_URL', 'AUTH_OIDC_APP_BASE_URL' and 'AUTH_OIDC_CLIENT_ID' are set! Authentication will be unstable or disabled until issue is resolved!`); log.error(`[OIDC] Incorrect Configuration Detected!. Verify 'AUTH_OIDC_ISSUER_BASE_URL', 'AUTH_OIDC_APP_BASE_URL' and 'AUTH_OIDC_CLIENT_ID' are set! Authentication will be unstable or disabled until issue is resolved!`);
} }
if(oidcIssuerBaseUrl !== '' && oidcClientType === 'confidential' && oidcClientSecret === '') { if(variables.authOidcIssuerBaseUrl !== '' && variables.authOidcClientType === 'confidential' && variables.authOidcClientSecret === '') {
log.error(`[OIDC] Incorrect Configuration Detected!. Verify 'AUTH_OIDC_CLIENT_SECRET' is set! Authentication will be unstable or disabled until issue is resolved!`); log.error(`[OIDC] Incorrect Configuration Detected!. Verify 'AUTH_OIDC_CLIENT_SECRET' is set! Authentication will be unstable or disabled until issue is resolved!`);
} }
/** /**
* Log printer status * Log printer status
*/ */
log.info(`[Printer] ${printerType !== '' ? `Enabled! Type: ${printerType}${printerType === 'escpos' ? `, IP: ${printerIp}` : ''}` : 'Disabled!'}`); log.info(`[Printer] ${variables.printerType !== '' ? `Enabled! Type: ${variables.printerType}${variables.printerType === 'escpos' ? `, IP: ${variables.printerIp}` : ''}` : 'Disabled!'}`);
/** /**
* Log email status * Log email status
*/ */
if(smtpFrom !== '' && smtpHost !== '' && smtpPort !== '') { if(variables.smtpFrom !== '' && variables.smtpHost !== '' && variables.smtpPort !== '') {
log.info(`[Email] Enabled! SMTP Server: ${smtpHost}:${smtpPort}`); log.info(`[Email] Enabled! SMTP Server: ${variables.smtpHost}:${variables.smtpPort}`);
} else { } else {
log.info(`[Email] Disabled!`); log.info(`[Email] Disabled!`);
} }
@@ -106,5 +87,5 @@ module.exports = () => {
/** /**
* Log controller * Log controller
*/ */
log.info(`[UniFi] Using Controller on: ${config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1'}:${config('unifi_port') || process.env.UNIFI_PORT || 443} (Site ID: ${config('unifi_site_id') || process.env.UNIFI_SITE_ID || 'default'})`); log.info(`[UniFi] Using Controller on: ${variables.unifiIp}:${variables.unifiPort} (Site ID: ${variables.unifiSiteId})`);
}; };

View File

@@ -6,12 +6,7 @@ const log = require('js-logger');
/** /**
* Import own modules * Import own modules
*/ */
const config = require('./config'); const variables = require('./variables');
/**
* Define global variables
*/
const level = config('log_level') || process.env.LOG_LEVEL || "info";
/** /**
* Setup logger * Setup logger
@@ -59,7 +54,7 @@ log.setHandler((messages, context) => {
/** /**
* Set log level * Set log level
*/ */
log.setLevel(logConvert(level)); log.setLevel(logConvert(variables.logLevel));
/** /**
* Export the application logger * Export the application logger

View File

@@ -8,29 +8,19 @@ const nodemailer = require('nodemailer');
/** /**
* Import own modules * Import own modules
*/ */
const config = require('./config'); const variables = require('./variables');
const log = require('./log'); const log = require('./log');
/**
* Define global variables
*/
const smtpFrom = config('smtp_from') || process.env.SMTP_FROM || '';
const smtpHost = config('smtp_host') || process.env.SMTP_HOST || '';
const smtpPort = config('smtp_port') || process.env.SMTP_PORT || 25;
const smtpSecure = config('smtp_secure') || process.env.SMTP_SECURE || false;
const smtpUsername = config('smtp_username') || process.env.SMTP_USERNAME || '';
const smtpPassword = config('smtp_password') || process.env.SMTP_PASSWORD || '';
/** /**
* Create nodemailer transport * Create nodemailer transport
*/ */
const transport = nodemailer.createTransport({ const transport = nodemailer.createTransport({
host: smtpHost, host: variables.smtpHost,
port: parseInt(smtpPort), port: parseInt(variables.smtpPort),
secure: (smtpSecure === 'true' || smtpSecure === true), secure: (variables.smtpSecure === 'true' || variables.smtpSecure === true),
auth: { auth: {
user: smtpUsername, user: variables.smtpUsername,
pass: smtpPassword pass: variables.smtpPassword
} }
}); });
@@ -48,7 +38,7 @@ module.exports = {
send: (to, voucher) => { send: (to, voucher) => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
await transport.sendMail({ await transport.sendMail({
from: smtpFrom, from: variables.smtpFrom,
to: to, to: to,
subject: 'Your WiFi Voucher', subject: 'Your WiFi Voucher',
text: `Hi there,\n\nSomeone generated a WiFi Voucher, please use this code when connecting:\n\n${voucher.code.slice(0, 5)}-${voucher.code.slice(5)}`, text: `Hi there,\n\nSomeone generated a WiFi Voucher, please use this code when connecting:\n\n${voucher.code.slice(0, 5)}-${voucher.code.slice(5)}`,

View File

@@ -7,6 +7,7 @@ const oidc = require('express-openid-connect');
/** /**
* Import own modules * Import own modules
*/ */
const variables = require('./variables');
const log = require('./log'); const log = require('./log');
/** /**
@@ -15,16 +16,16 @@ const log = require('./log');
* @type {{baseURL: string, idpLogout: boolean, authRequired: boolean, clientID: string, issuerBaseURL: string, clientSecret: string, secret: string, authorizationParams: {scope: string, response_type: (string), response_mode: (string)}}} * @type {{baseURL: string, idpLogout: boolean, authRequired: boolean, clientID: string, issuerBaseURL: string, clientSecret: string, secret: string, authorizationParams: {scope: string, response_type: (string), response_mode: (string)}}}
*/ */
const settings = { const settings = {
issuerBaseURL: process.env.AUTH_OIDC_ISSUER_BASE_URL, issuerBaseURL: variables.authOidcIssuerBaseUrl,
baseURL: process.env.AUTH_OIDC_APP_BASE_URL, baseURL: variables.authOidcAppBaseUrl,
clientID: process.env.AUTH_OIDC_CLIENT_ID, clientID: variables.authOidcClientId,
clientSecret: process.env.AUTH_OIDC_CLIENT_SECRET, clientSecret: variables.authOidcClientSecret,
secret: '', secret: '',
idpLogout: true, idpLogout: true,
authRequired: false, authRequired: false,
authorizationParams: { authorizationParams: {
response_type: (process.env.AUTH_OIDC_CLIENT_TYPE === 'confidential') ? 'code' : 'id_token', response_type: (variables.authOidcClientType === 'confidential') ? 'code' : 'id_token',
response_mode: (process.env.AUTH_OIDC_CLIENT_TYPE === 'confidential') ? 'query' : 'form_post', response_mode: (variables.authOidcClientType === 'confidential') ? 'query' : 'form_post',
scope: 'openid profile email' scope: 'openid profile email'
} }
}; };
@@ -42,6 +43,6 @@ module.exports = {
settings.secret = crypto.randomBytes(20).toString('hex'); settings.secret = crypto.randomBytes(20).toString('hex');
log.info(`[OIDC] Set secret: ${settings.secret}`); log.info(`[OIDC] Set secret: ${settings.secret}`);
app.use(oidc.auth(settings)); app.use(oidc.auth(settings));
log.info(`[OIDC] Issuer: ${settings.issuerBaseURL}, Client: ${settings.clientID}, Type: ${process.env.AUTH_OIDC_CLIENT_TYPE || 'public'}`); log.info(`[OIDC] Issuer: ${settings.issuerBaseURL}, Client: ${settings.clientID}, Type: ${variables.authOidcClientType}`);
} }
}; };

View File

@@ -8,17 +8,12 @@ const PrinterTypes = require('node-thermal-printer').types;
/** /**
* Import own modules * Import own modules
*/ */
const variables = require('./variables');
const log = require('./log'); const log = require('./log');
const config = require('./config');
const time = require('../utils/time'); const time = require('../utils/time');
const bytes = require('../utils/bytes'); const bytes = require('../utils/bytes');
const size = require('../utils/size'); const size = require('../utils/size');
/**
* Define global variables
*/
const printerIp = config('printer_ip') || process.env.PRINTER_IP || '192.168.1.1';
/** /**
* Exports the printer module * Exports the printer module
*/ */
@@ -139,7 +134,7 @@ module.exports = {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const printer = new ThermalPrinter({ const printer = new ThermalPrinter({
type: PrinterTypes.EPSON, type: PrinterTypes.EPSON,
interface: `tcp://${printerIp}` interface: `tcp://${variables.printerIp}`
}); });
const status = await printer.isPrinterConnected(); const status = await printer.isPrinterConnected();

View File

@@ -6,18 +6,18 @@ const unifi = require('node-unifi');
/** /**
* Import own modules * Import own modules
*/ */
const config = require('./config'); const variables = require('./variables');
const log = require('./log'); const log = require('./log');
/** /**
* UniFi Settings * UniFi Settings
*/ */
const settings = { const settings = {
ip: config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1', ip: variables.unifiIp,
port: config('unifi_port') || process.env.UNIFI_PORT || 443, port: variables.unifiPort,
username: config('unifi_username') || process.env.UNIFI_USERNAME || 'admin', username: variables.unifiUsername,
password: config('unifi_password') || process.env.UNIFI_PASSWORD || 'password', password: variables.unifiPassword,
siteID: config('unifi_site_id') || process.env.UNIFI_SITE_ID || 'default' siteID: variables.unifiSiteId
}; };
/** /**

36
modules/variables.js Normal file
View File

@@ -0,0 +1,36 @@
/**
* Import own modules
*/
const config = require('./config');
/**
* Exports all global variables used within the application
*/
module.exports = {
unifiIp: config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1',
unifiPort: config('unifi_port') || process.env.UNIFI_PORT || 443,
unifiUsername: config('unifi_username') || process.env.UNIFI_USERNAME || 'admin',
unifiPassword: config('unifi_password') || process.env.UNIFI_PASSWORD || 'password',
unifiSiteId: config('unifi_site_id') || process.env.UNIFI_SITE_ID || 'default',
voucherTypes: config('voucher_types') || process.env.VOUCHER_TYPES || '480,1,,,;',
voucherCustom: config('voucher_custom') !== null ? config('voucher_custom') : process.env.VOUCHER_CUSTOM ? process.env.VOUCHER_CUSTOM !== 'false' : true,
serviceWeb: process.env.SERVICE_WEB ? process.env.SERVICE_WEB !== 'false' : true,
serviceApi: config('service_api') || (process.env.SERVICE_API === 'true') || false,
authPassword: process.env.AUTH_PASSWORD || '0000',
authToken: process.env.AUTH_TOKEN || '0000',
authOidcIssuerBaseUrl: process.env.AUTH_OIDC_ISSUER_BASE_URL || '',
authOidcAppBaseUrl: process.env.AUTH_OIDC_APP_BASE_URL || '',
authOidcClientId: process.env.AUTH_OIDC_CLIENT_ID || '',
authOidcClientType: process.env.AUTH_OIDC_CLIENT_TYPE || 'public',
authOidcClientSecret: process.env.AUTH_OIDC_CLIENT_SECRET || '',
authDisabled: (process.env.AUTH_DISABLE === 'true') || false,
printerType: config('printer_type') || process.env.PRINTER_TYPE || '',
printerIp: config('printer_ip') || process.env.PRINTER_IP || '192.168.1.1',
smtpFrom: config('smtp_from') || process.env.SMTP_FROM || '',
smtpHost: config('smtp_host') || process.env.SMTP_HOST || '',
smtpPort: config('smtp_port') || process.env.SMTP_PORT || 25,
smtpSecure: config('smtp_secure') || process.env.SMTP_SECURE || false,
smtpUsername: config('smtp_username') || process.env.SMTP_USERNAME || '',
smtpPassword: config('smtp_password') || process.env.SMTP_PASSWORD || '',
logLevel: config('log_level') || process.env.LOG_LEVEL || 'info'
};

19
package-lock.json generated
View File

@@ -18,11 +18,11 @@
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"node-thermal-printer": "^4.4.3", "node-thermal-printer": "^4.4.3",
"node-unifi": "^2.5.1", "node-unifi": "^2.5.1",
"nodemailer": "^6.9.14", "nodemailer": "^6.9.15",
"pdfkit": "^0.15.0" "pdfkit": "^0.15.0"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.8",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"tailwindcss": "^3.4.10" "tailwindcss": "^3.4.10"
}, },
@@ -317,15 +317,16 @@
} }
}, },
"node_modules/@tailwindcss/forms": { "node_modules/@tailwindcss/forms": {
"version": "0.5.7", "version": "0.5.8",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.8.tgz",
"integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==", "integrity": "sha512-DJs7B7NPD0JH7BVvdHWNviWmunlFhuEkz7FyFxE4japOWYMLl9b1D6+Z9mivJJPWr6AEbmlPqgiFRyLwFB1SgQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"mini-svg-data-uri": "^1.2.3" "mini-svg-data-uri": "^1.2.3"
}, },
"peerDependencies": { "peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20"
} }
}, },
"node_modules/@types/cacheable-request": { "node_modules/@types/cacheable-request": {
@@ -2603,9 +2604,9 @@
} }
}, },
"node_modules/nodemailer": { "node_modules/nodemailer": {
"version": "6.9.14", "version": "6.9.15",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz",
"integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==",
"license": "MIT-0", "license": "MIT-0",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"

View File

@@ -29,11 +29,11 @@
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"node-thermal-printer": "^4.4.3", "node-thermal-printer": "^4.4.3",
"node-unifi": "^2.5.1", "node-unifi": "^2.5.1",
"nodemailer": "^6.9.14", "nodemailer": "^6.9.15",
"pdfkit": "^0.15.0" "pdfkit": "^0.15.0"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.8",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"tailwindcss": "^3.4.10" "tailwindcss": "^3.4.10"
} }

View File

@@ -9,7 +9,7 @@ const cookieParser = require('cookie-parser');
/** /**
* Import own modules * Import own modules
*/ */
const config = require('./modules/config'); const variables = require('./modules/variables');
const log = require('./modules/log'); const log = require('./modules/log');
const cache = require('./modules/cache'); const cache = require('./modules/cache');
const jwt = require('./modules/jwt'); const jwt = require('./modules/jwt');
@@ -39,22 +39,6 @@ const status = require('./utils/status');
*/ */
const app = express(); const app = express();
/**
* Define global variables
*/
const voucherTypes = types(config('voucher_types') || process.env.VOUCHER_TYPES || '480,1,,,;');
const voucherCustom = config('voucher_custom') !== null ? config('voucher_custom') : process.env.VOUCHER_CUSTOM ? process.env.VOUCHER_CUSTOM !== 'false' : true;
const webService = process.env.SERVICE_WEB ? process.env.SERVICE_WEB !== 'false' : true;
const apiService = config('service_api') || (process.env.SERVICE_API === 'true') || false;
const authDisabled = (process.env.AUTH_DISABLE === 'true') || false;
const printerType = config('printer_type') || process.env.PRINTER_TYPE || '';
const smtpFrom = config('smtp_from') || process.env.SMTP_FROM || '';
const smtpHost = config('smtp_host') || process.env.SMTP_HOST || '';
const smtpPort = config('smtp_port') || process.env.SMTP_PORT || 25;
const oidcIssuerBaseUrl = process.env.AUTH_OIDC_ISSUER_BASE_URL || '';
const oidcAppBaseUrl = process.env.AUTH_OIDC_APP_BASE_URL || '';
const oidcClientId = process.env.AUTH_OIDC_CLIENT_ID || '';
/** /**
* Output info * Output info
*/ */
@@ -63,7 +47,7 @@ info();
/** /**
* Initialize JWT * Initialize JWT
*/ */
if(!authDisabled && (oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '')) { if(!variables.authDisabled && (variables.authOidcIssuerBaseUrl === '' && variables.authOidcAppBaseUrl === '' && variables.authOidcClientId === '')) {
jwt.init(); jwt.init();
} }
@@ -94,7 +78,7 @@ app.get('/_health', (req, res) => {
/** /**
* Initialize OIDC * Initialize OIDC
*/ */
if(!authDisabled && (oidcIssuerBaseUrl !== '' && oidcAppBaseUrl !== '' && oidcClientId !== '')) { if(!variables.authDisabled && (variables.authOidcIssuerBaseUrl !== '' && variables.authOidcAppBaseUrl !== '' && variables.authOidcClientId !== '')) {
oidc.init(app); oidc.init(app);
} }
@@ -130,7 +114,7 @@ app.use(express.static(`${__dirname}/public`));
* Configure routers * Configure routers
*/ */
app.get('/', (req, res) => { app.get('/', (req, res) => {
if(webService) { if(variables.serviceWeb) {
res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`); res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`);
} else { } else {
res.status(501).send(); res.status(501).send();
@@ -138,11 +122,11 @@ app.get('/', (req, res) => {
}); });
// Check if web service is enabled // Check if web service is enabled
if(webService) { if(variables.serviceWeb) {
if(oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '') { if(variables.authOidcIssuerBaseUrl === '' && variables.authOidcAppBaseUrl === '' && variables.authOidcClientId === '') {
app.get('/login', (req, res) => { app.get('/login', (req, res) => {
// Check if authentication is disabled // Check if authentication is disabled
if (authDisabled) { if (variables.authDisabled) {
res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`); res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`);
return; return;
} }
@@ -163,7 +147,7 @@ if(webService) {
return; return;
} }
const passwordCheck = req.body.password === (process.env.AUTH_PASSWORD || "0000"); const passwordCheck = req.body.password === variables.authPassword;
if (!passwordCheck) { if (!passwordCheck) {
res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Password Invalid!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/login`); res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Password Invalid!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/login`);
@@ -180,7 +164,7 @@ if(webService) {
} }
if(req.body['voucher-type'] !== 'custom') { if(req.body['voucher-type'] !== 'custom') {
const typeCheck = (config('voucher_types') || process.env.VOUCHER_TYPES || '480,1,,,;').split(';').includes(req.body['voucher-type']); const typeCheck = (variables.voucherTypes).split(';').includes(req.body['voucher-type']);
if (!typeCheck) { if (!typeCheck) {
res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Unknown Type!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`); res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Unknown Type!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`);
@@ -234,7 +218,7 @@ if(webService) {
} }
}); });
app.get('/voucher/:id/print', [authorization.web], async (req, res) => { app.get('/voucher/:id/print', [authorization.web], async (req, res) => {
if(printerType === '') { if(variables.printerType === '') {
res.status(501).send(); res.status(501).send();
return; return;
} }
@@ -244,7 +228,7 @@ if(webService) {
}); });
if(voucher) { if(voucher) {
if(printerType === 'pdf') { if(variables.printerType === 'pdf') {
const buffers = await print.pdf(voucher); const buffers = await print.pdf(voucher);
const pdfData = Buffer.concat(buffers); const pdfData = Buffer.concat(buffers);
res.writeHead(200, { res.writeHead(200, {
@@ -254,7 +238,7 @@ if(webService) {
}).end(pdfData); }).end(pdfData);
} }
if(printerType === 'escpos') { if(variables.printerType === 'escpos') {
const printResult = await print.escpos(voucher).catch((e) => { const printResult = await print.escpos(voucher).catch((e) => {
res.cookie('flashMessage', JSON.stringify({type: 'error', message: e}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`); res.cookie('flashMessage', JSON.stringify({type: 'error', message: e}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`);
}); });
@@ -271,7 +255,7 @@ if(webService) {
} }
}); });
app.get('/voucher/:id/email', [authorization.web], async (req, res) => { app.get('/voucher/:id/email', [authorization.web], async (req, res) => {
if(smtpFrom === '' || smtpHost === '' || smtpPort === '') { if(variables.smtpFrom === '' || variables.smtpHost === '' || variables.smtpPort === '') {
res.status(501).send(); res.status(501).send();
return; return;
} }
@@ -296,7 +280,7 @@ if(webService) {
} }
}); });
app.post('/voucher/:id/email', [authorization.web], async (req, res) => { app.post('/voucher/:id/email', [authorization.web], async (req, res) => {
if(smtpFrom === '' || smtpHost === '' || smtpPort === '') { if(variables.smtpFrom === '' || variables.smtpHost === '' || variables.smtpPort === '') {
res.status(501).send(); res.status(501).send();
return; return;
} }
@@ -357,10 +341,10 @@ if(webService) {
error_text: req.flashMessage.message || '', error_text: req.flashMessage.message || '',
timeConvert: time, timeConvert: time,
bytesConvert: bytes, bytesConvert: bytes,
email_enabled: smtpFrom !== '' && smtpHost !== '' && smtpPort !== '', email_enabled: variables.smtpFrom !== '' && variables.smtpHost !== '' && variables.smtpPort !== '',
printer_enabled: printerType !== '', printer_enabled: variables.printerType !== '',
voucher_types: voucherTypes, voucher_types: types(variables.voucherTypes),
voucher_custom: voucherCustom, voucher_custom: variables.voucherCustom,
vouchers: cache.vouchers, vouchers: cache.vouchers,
updated: cache.updated updated: cache.updated
}); });
@@ -397,7 +381,7 @@ if(webService) {
}); });
} }
if(apiService) { if(variables.serviceApi) {
app.get('/api', (req, res) => { app.get('/api', (req, res) => {
res.json({ res.json({
error: null, error: null,
@@ -417,12 +401,12 @@ if(apiService) {
error: null, error: null,
data: { data: {
message: 'OK', message: 'OK',
types: voucherTypes types: types(variables.voucherTypes)
} }
}); });
}); });
app.get('/api/voucher/:type', [authorization.api], async (req, res) => { app.get('/api/voucher/:type', [authorization.api], async (req, res) => {
const typeCheck = (process.env.VOUCHER_TYPES || '480,1,,,;').split(';').includes(req.params.type); const typeCheck = (variables.voucherTypes).split(';').includes(req.params.type);
if(!typeCheck) { if(!typeCheck) {
res.json({ res.json({

View File

@@ -18,7 +18,7 @@ module.exports = {
*/ */
updateCache: () => { updateCache: () => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
log.info('[Cache] Requesting UniFi Vouchers...'); log.debug('[Cache] Requesting UniFi Vouchers...');
const vouchers = await unifi.list().catch(() => { const vouchers = await unifi.list().catch(() => {
log.error('[Cache] Error requesting vouchers!'); log.error('[Cache] Error requesting vouchers!');
@@ -30,7 +30,7 @@ module.exports = {
log.debug(`[Cache] Saved ${vouchers.length} voucher(s)`); log.debug(`[Cache] Saved ${vouchers.length} voucher(s)`);
} }
log.info('[Cache] Requesting UniFi Guests...'); log.debug('[Cache] Requesting UniFi Guests...');
const guests = await unifi.guests().catch(() => { const guests = await unifi.guests().catch(() => {
log.error('[Cache] Error requesting guests!'); log.error('[Cache] Error requesting guests!');

View File

@@ -1,22 +1,7 @@
/** /**
* Import own modules * Import own modules
*/ */
const config = require('../modules/config'); const variables = require('../modules/variables');
/**
* Define global variables
*/
const webService = process.env.SERVICE_WEB ? process.env.SERVICE_WEB !== 'false' : true;
const apiService = config('service_api') || (process.env.SERVICE_API === 'true') || false;
const printerType = config('printer_type') || process.env.PRINTER_TYPE || '';
const printerIp = config('printer_ip') || process.env.PRINTER_IP || '192.168.1.1';
const smtpFrom = config('smtp_from') || process.env.SMTP_FROM || '';
const smtpHost = config('smtp_host') || process.env.SMTP_HOST || '';
const smtpPort = config('smtp_port') || process.env.SMTP_PORT || 25;
const authDisabled = (process.env.AUTH_DISABLE === 'true') || false;
const oidcIssuerBaseUrl = process.env.AUTH_OIDC_ISSUER_BASE_URL || '';
const oidcAppBaseUrl = process.env.AUTH_OIDC_APP_BASE_URL || '';
const oidcClientId = process.env.AUTH_OIDC_CLIENT_ID || '';
/** /**
* Util to return status of all application components and features * Util to return status of all application components and features
@@ -27,26 +12,26 @@ module.exports = () => {
return { return {
app: { app: {
status: { status: {
text: webService || apiService ? 'Enabled' : 'Disabled', text: variables.serviceWeb || variables.serviceApi ? 'Enabled' : 'Disabled',
state: webService || apiService ? 'green' : 'red' state: variables.serviceWeb || variables.serviceApi ? 'green' : 'red'
}, },
details: webService || apiService ? 'Service has been configured.' : 'No services enabled.', details: variables.serviceWeb || variables.serviceApi ? 'Service has been configured.' : 'No services enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#services', info: 'https://github.com/glenndehaan/unifi-voucher-site#services',
modules: { modules: {
web: { web: {
status: { status: {
text: webService ? 'Enabled' : 'Disabled', text: variables.serviceWeb ? 'Enabled' : 'Disabled',
state: webService ? 'green' : 'red' state: variables.serviceWeb ? 'green' : 'red'
}, },
details: webService || apiService ? 'Service running on http://0.0.0.0:3000.' : 'Web service not enabled.', details: variables.serviceWeb || variables.serviceApi ? 'Service running on http://0.0.0.0:3000.' : 'Web service not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#web-service' info: 'https://github.com/glenndehaan/unifi-voucher-site#web-service'
}, },
api: { api: {
status: { status: {
text: apiService ? 'Enabled' : 'Disabled', text: variables.serviceApi ? 'Enabled' : 'Disabled',
state: apiService ? 'green' : 'red' state: variables.serviceApi ? 'green' : 'red'
}, },
details: webService || apiService ? 'Service running on http://0.0.0.0:3000/api.' : 'Api service not enabled.', details: variables.serviceWeb || variables.serviceApi ? 'Service running on http://0.0.0.0:3000/api.' : 'Api service not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#api-service' info: 'https://github.com/glenndehaan/unifi-voucher-site#api-service'
} }
} }
@@ -56,67 +41,67 @@ module.exports = () => {
text: 'Enabled', text: 'Enabled',
state: 'green' state: 'green'
}, },
details: `UniFi Voucher is connected with UniFi on: ${config('unifi_ip') || process.env.UNIFI_IP || '192.168.1.1'}:${config('unifi_port') || process.env.UNIFI_PORT || 443}.`, details: `UniFi Voucher is connected with UniFi on: ${variables.unifiIp}:${variables.unifiPort}.`,
info: 'https://github.com/glenndehaan/unifi-voucher-site#prerequisites', info: 'https://github.com/glenndehaan/unifi-voucher-site#prerequisites',
modules: {} modules: {}
}, },
printing: { printing: {
status: { status: {
text: printerType !== '' ? 'Enabled' : 'Disabled', text: variables.printerType !== '' ? 'Enabled' : 'Disabled',
state: printerType !== '' ? 'green' : 'red' state: variables.printerType !== '' ? 'green' : 'red'
}, },
details: printerType !== '' ? 'Printing service has been configured.' : 'No printing service enabled.', details: variables.printerType !== '' ? 'Printing service has been configured.' : 'No printing service enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#print-functionality', info: 'https://github.com/glenndehaan/unifi-voucher-site#print-functionality',
modules: { modules: {
pdf: { pdf: {
status: { status: {
text: printerType === 'pdf' ? 'Enabled' : 'Disabled', text: variables.printerType === 'pdf' ? 'Enabled' : 'Disabled',
state: printerType === 'pdf' ? 'green' : 'red' state: variables.printerType === 'pdf' ? 'green' : 'red'
}, },
details: printerType === 'pdf' ? 'PDF Service enabled.' : 'PDF Service not enabled.', details: variables.printerType === 'pdf' ? 'PDF Service enabled.' : 'PDF Service not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#pdf' info: 'https://github.com/glenndehaan/unifi-voucher-site#pdf'
}, },
escpos: { escpos: {
status: { status: {
text: printerType === 'escpos' ? 'Enabled' : 'Disabled', text: variables.printerType === 'escpos' ? 'Enabled' : 'Disabled',
state: printerType === 'escpos' ? 'green' : 'red' state: variables.printerType === 'escpos' ? 'green' : 'red'
}, },
details: printerType === 'escpos' ? `ESC/POS Printing on ${printerIp}.` : 'ESC/POS Service not enabled.', details: variables.printerType === 'escpos' ? `ESC/POS Printing on ${variables.printerIp}.` : 'ESC/POS Service not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#escpos' info: 'https://github.com/glenndehaan/unifi-voucher-site#escpos'
} }
} }
}, },
email: { email: {
status: { status: {
text: (smtpFrom !== '' && smtpHost !== '' && smtpPort !== '') ? 'Enabled' : 'Disabled', text: (variables.smtpFrom !== '' && variables.smtpHost !== '' && variables.smtpPort !== '') ? 'Enabled' : 'Disabled',
state: (smtpFrom !== '' && smtpHost !== '' && smtpPort !== '') ? 'green' : 'red' state: (variables.smtpFrom !== '' && variables.smtpHost !== '' && variables.smtpPort !== '') ? 'green' : 'red'
}, },
details: (smtpFrom !== '' && smtpHost !== '' && smtpPort !== '') ? `Email service sending to ${smtpHost}:${smtpPort}.` : 'Email service not enabled.', details: (variables.smtpFrom !== '' && variables.smtpHost !== '' && variables.smtpPort !== '') ? `Email service sending to ${variables.smtpHost}:${variables.smtpPort}.` : 'Email service not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#email-functionality', info: 'https://github.com/glenndehaan/unifi-voucher-site#email-functionality',
modules: {} modules: {}
}, },
authentication: { authentication: {
status: { status: {
text: !authDisabled ? 'Enabled' : 'Disabled', text: !variables.authDisabled ? 'Enabled' : 'Disabled',
state: !authDisabled ? 'green' : 'red' state: !variables.authDisabled ? 'green' : 'red'
}, },
details: !authDisabled ? 'Authentication service has been configured.' : 'Authentication has been disabled.', details: !variables.authDisabled ? 'Authentication service has been configured.' : 'Authentication has been disabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#authentication', info: 'https://github.com/glenndehaan/unifi-voucher-site#authentication',
modules: { modules: {
internal: { internal: {
status: { status: {
text: (oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '') ? 'Enabled' : 'Disabled', text: (!variables.authDisabled && variables.authOidcIssuerBaseUrl === '' && variables.authOidcAppBaseUrl === '' && variables.authOidcClientId === '') ? 'Enabled' : 'Disabled',
state: (oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '') ? 'green' : 'red' state: (!variables.authDisabled && variables.authOidcIssuerBaseUrl === '' && variables.authOidcAppBaseUrl === '' && variables.authOidcClientId === '') ? 'green' : 'red'
}, },
details: (oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '') ? 'Internal Authentication enabled.' : 'Internal Authentication not enabled.', details: (!variables.authDisabled && variables.authOidcIssuerBaseUrl === '' && variables.authOidcAppBaseUrl === '' && variables.authOidcClientId === '') ? 'Internal Authentication enabled.' : 'Internal Authentication not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#1-internal-authentication-default' info: 'https://github.com/glenndehaan/unifi-voucher-site#1-internal-authentication-default'
}, },
oidc: { oidc: {
status: { status: {
text: (oidcIssuerBaseUrl !== '' && oidcAppBaseUrl !== '' && oidcClientId !== '') ? 'Enabled' : 'Disabled', text: (!variables.authDisabled && variables.authOidcIssuerBaseUrl !== '' && variables.authOidcAppBaseUrl !== '' && variables.authOidcClientId !== '') ? 'Enabled' : 'Disabled',
state: (oidcIssuerBaseUrl !== '' && oidcAppBaseUrl !== '' && oidcClientId !== '') ? 'green' : 'red' state: (!variables.authDisabled && variables.authOidcIssuerBaseUrl !== '' && variables.authOidcAppBaseUrl !== '' && variables.authOidcClientId !== '') ? 'green' : 'red'
}, },
details: (oidcIssuerBaseUrl !== '' && oidcAppBaseUrl !== '' && oidcClientId !== '') ? `OIDC Authentication via ${oidcIssuerBaseUrl}.` : 'OIDC Authentication not enabled.', details: (!variables.authDisabled && variables.authOidcIssuerBaseUrl !== '' && variables.authOidcAppBaseUrl !== '' && variables.authOidcClientId !== '') ? `OIDC Authentication via ${variables.authOidcIssuerBaseUrl}.` : 'OIDC Authentication not enabled.',
info: 'https://github.com/glenndehaan/unifi-voucher-site#2-openid-connect-oidc-authentication' info: 'https://github.com/glenndehaan/unifi-voucher-site#2-openid-connect-oidc-authentication'
} }
} }