Refactored unifi.js to separate logic. Updated application header. Fixed incorrect screen-reader text. Updated sync button text. Implemented last sync date/time. Implemented cache util. Fixed missing vouchers check to prevent 'headers are already send' error. Fixed missing cache sync on api voucher creation. Implemented auto sync every 15 minutes

This commit is contained in:
Glenn de Haan
2024-04-03 23:15:10 +02:00
parent 65c79b1f3d
commit 4404fabafa
4 changed files with 93 additions and 33 deletions

View File

@@ -25,12 +25,16 @@ const config = {
/**
* Exports the UniFi voucher functions
*
* @param type
* @param create
* @returns {Promise<unknown>}
* @type {{create: (function(*): Promise<*>), list: (function(): Promise<*>)}}
*/
module.exports = (type, create = true) => {
if(create) {
module.exports = {
/**
* Creates a new UniFi Voucher
*
* @param type
* @return {Promise<unknown>}
*/
create: (type) => {
return new Promise((resolve, reject) => {
/**
* Create new UniFi controller object
@@ -69,7 +73,14 @@ module.exports = (type, create = true) => {
reject('[UniFi] Error while logging in!');
});
});
} else {
},
/**
* Returns a list with all UniFi Vouchers
*
* @return {Promise<unknown>}
*/
list: () => {
return new Promise((resolve, reject) => {
/**
* Create new UniFi controller object
@@ -102,4 +113,4 @@ module.exports = (type, create = true) => {
});
});
}
};
}

View File

@@ -24,6 +24,11 @@ const unifi = require('./modules/unifi');
const authorization = require('./middlewares/authorization');
const flashMessage = require('./middlewares/flashMessage');
/**
* Import own utils
*/
const {updateCache} = require('./utils/cache');
/**
* Setup Express app
*/
@@ -184,13 +189,13 @@ if(webService) {
}
// Create voucher code
const voucherCode = await unifi(types(req.body['voucher-type'], true)).catch((e) => {
const voucherCode = await unifi.create(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, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`);
});
log.info('[Cache] Requesting UniFi Vouchers...');
const vouchers = await unifi('', false).catch((e) => {
const vouchers = await unifi.list().catch((e) => {
log.error('[Cache] Error requesting vouchers!');
log.error(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`);
@@ -202,7 +207,7 @@ if(webService) {
log.info(`[Cache] Saved ${vouchers.length} voucher(s)`);
}
if(voucherCode) {
if(vouchers && 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, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/vouchers`);
}
});
@@ -210,7 +215,7 @@ if(webService) {
if(req.query.refresh) {
log.info('[Cache] Requesting UniFi Vouchers...');
const vouchers = await unifi('', false).catch((e) => {
const vouchers = await unifi.list().catch((e) => {
log.error('[Cache] Error requesting vouchers!');
log.error(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`);
@@ -235,7 +240,8 @@ if(webService) {
error_text: req.flashMessage.message || '',
timeConvert: time,
voucher_types: voucherTypes,
vouchers: cache.vouchers
vouchers: cache.vouchers,
updated: cache.updated
});
});
}
@@ -275,13 +281,15 @@ if(apiService) {
}
// Create voucher code
const voucherCode = await unifi(types(req.params.type, true)).catch((e) => {
const voucherCode = await unifi.create(types(req.params.type, true)).catch((e) => {
res.json({
error: e,
data: {}
});
});
await updateCache();
if(voucherCode) {
res.json({
error: null,
@@ -314,17 +322,11 @@ app.disable('x-powered-by');
*/
app.listen(3000, '0.0.0.0', async () => {
log.info(`[App] Running on: 0.0.0.0:3000`);
await updateCache();
log.info('[Cache] Requesting UniFi Vouchers...');
const vouchers = await unifi('', false).catch((e) => {
log.error('[Cache] Error requesting vouchers!');
log.error(e);
});
if(vouchers) {
cache.vouchers = vouchers;
cache.updated = new Date().getTime();
log.info(`[Cache] Saved ${vouchers.length} voucher(s)`);
}
// Run auto sync every 15 minutes
setInterval(async () => {
log.info('[Auto Sync] Starting Sync...');
await updateCache();
}, 900000);
});

View File

@@ -33,6 +33,9 @@
<div class="flex">
<div class="flex flex-shrink-0 items-center">
<img class="h-12 w-auto" alt="UniFi Voucher Site Logo" src="<%= baseUrl %>/images/logo.png">
<div class="hidden sm:block ml-4 text-2xl font-semibold leading-7 text-gray-900 dark:text-white">
UniFi Voucher
</div>
</div>
</div>
<div class="flex items-center">
@@ -47,7 +50,7 @@
<div class="ml-4 flex flex-shrink-0 items-center">
<a href="https://github.com/glenndehaan/unifi-voucher-site" aria-label="GitHub Project Link" target="_blank" rel="noreferrer noopener" type="button" class="relative rounded-full p-1 text-gray-500 dark:text-gray-400 hover:text-black dark:hover:text-white">
<span class="absolute -inset-1.5"></span>
<span class="sr-only">View notifications</span>
<span class="sr-only">GitHub Project Link</span>
<svg class="h-6 w-6" viewBox="0 0 42 42" fill="currentColor">
<path d="M21,0.5c-11.6,0-21,9.4-21,21c0,9.3,6,17.1,14.4,19.9c1.1,0.2,1.4-0.5,1.4-1c0-0.5,0-1.8,0-3.6C9.9,38.1,8.7,34,8.7,34c-1-2.4-2.3-3.1-2.3-3.1c-1.9-1.3,0.1-1.3,0.1-1.3c2.1,0.1,3.2,2.2,3.2,2.2c1.9,3.2,4.9,2.3,6.1,1.7c0.2-1.4,0.7-2.3,1.3-2.8c-4.7-0.5-9.6-2.3-9.6-10.4c0-2.3,0.8-4.2,2.2-5.6c-0.2-0.5-0.9-2.7,0.2-5.6c0,0,1.8-0.6,5.8,2.2c1.7-0.5,3.5-0.7,5.3-0.7c1.8,0,3.6,0.2,5.3,0.7c4-2.7,5.8-2.2,5.8-2.2c1.1,2.9,0.4,5,0.2,5.6c1.3,1.5,2.2,3.3,2.2,5.6c0,8.1-4.9,9.8-9.6,10.4c0.8,0.6,1.4,1.9,1.4,3.9c0,2.8,0,5.1,0,5.8c0,0.6,0.4,1.2,1.4,1C36,38.7,42,30.8,42,21.5C42,9.9,32.6,0.5,21,0.5z"></path>
</svg>
@@ -94,14 +97,21 @@
<main class="mx-auto max-w-7xl">
<header class="flex items-center justify-between border-b border-black/5 dark:border-white/5 px-4 py-4 sm:px-6 sm:py-6 lg:px-8">
<h1 class="text-xl font-semibold leading-7 text-gray-900 dark:text-white">Vouchers</h1>
<h1 class="text-2xl font-semibold leading-7 text-gray-900 dark:text-white">
Vouchers
</h1>
<div class="grid">
<a href="<%= baseUrl %>/vouchers?refresh=true" id="reload-vouchers" type="button" class="relative inline-flex items-center gap-x-1.5 rounded-md bg-sky-700 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-sky-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700">
<svg class="-ml-0.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M15.312 11.424a5.5 5.5 0 0 1-9.201 2.466l-.312-.311h2.433a.75.75 0 0 0 0-1.5H3.989a.75.75 0 0 0-.75.75v4.242a.75.75 0 0 0 1.5 0v-2.43l.31.31a7 7 0 0 0 11.712-3.138.75.75 0 0 0-1.449-.39Zm1.23-3.723a.75.75 0 0 0 .219-.53V2.929a.75.75 0 0 0-1.5 0V5.36l-.31-.31A7 7 0 0 0 3.239 8.188a.75.75 0 1 0 1.448.389A5.5 5.5 0 0 1 13.89 6.11l.311.31h-2.432a.75.75 0 0 0 0 1.5h4.243a.75.75 0 0 0 .53-.219Z" clip-rule="evenodd" />
</svg>
Reload Vouchers
Sync Vouchers
</a>
<span class="mt-2 text-xs text-center italic text-gray-900 dark:text-white">
Last Sync: <%= new Intl.DateTimeFormat('en-US', {dateStyle: 'short', timeStyle: 'short', hour12: false}).format(new Date(updated)) %>
</span>
</div>
</header>
<% if(vouchers.length < 1) { %>

37
utils/cache.js Normal file
View File

@@ -0,0 +1,37 @@
/**
* Import own modules
*/
const log = require('../modules/log');
const unifi = require('../modules/unifi');
const cache = require('../modules/cache');
/**
* Exports all cache utils
*
* @type {{updateCache: (function(): Promise<*>)}}
*/
module.exports = {
/**
* Update the cache
*
* @return {Promise<*>}
*/
updateCache: () => {
return new Promise(async (resolve) => {
log.info('[Cache] Requesting UniFi Vouchers...');
const vouchers = await unifi.list().catch((e) => {
log.error('[Cache] Error requesting vouchers!');
log.error(e);
});
if(vouchers) {
cache.vouchers = vouchers;
cache.updated = new Date().getTime();
log.info(`[Cache] Saved ${vouchers.length} voucher(s)`);
}
resolve();
});
}
};