From 38ac725da6c73b970cb9e33c649131902003a32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Kopp?= Date: Wed, 1 Dec 2021 20:44:59 +0100 Subject: [PATCH] top IP list (#36) --- app/db/ip.js | 15 +++++++++----- app/routes/adminRoutes.js | 23 ++++++++++++++++++++- app/routes/apiRoutes.js | 10 +++++++++- app/views/ips.pug | 42 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/app/db/ip.js b/app/db/ip.js index f23d475..c458f06 100644 --- a/app/db/ip.js +++ b/app/db/ip.js @@ -64,7 +64,7 @@ function date2string(date=new Date(), level='month', type='full'){ function createFilter(filter){ - + logger.warn('TODO: validate input'); logger.warn('IP filter is not implemented'); var query={ 'pivot_ip': { @@ -81,7 +81,7 @@ function createFilter(filter){ } }; var values={}; - var header=['ip']; + var header=[]; values.level = filter.period.level; values.period_interval = '1 ' + values.level; @@ -126,6 +126,7 @@ exports.getTop = (filter, ) => { logger.trace(); logger.warn('db.ip.getTop() uses only default settings !!!'); + min_exist = parseInt(min_exist); const {query, values, header} = createFilter({ 'period': { 'start': moment(period_start), @@ -138,11 +139,15 @@ exports.getTop = (filter, }, ...filter }); + return new promise((resolve, reject) => { db.any(` -SELECT * +SELECT + ip, + `+ header.map(v => `COALESCE("${v}",0)`).join('+') +` AS sum, + `+ header.map(v => `"${v}"`).join(',') +` FROM crosstab( - 'SELECT top.ip,to_char(data.period_start_date,''YYYY-MM-DD 00:00:00''),COALESCE(data.cnt_${measure},0) + 'SELECT top.ip, to_char(data.period_start_date,''YYYY-MM-DD 00:00:00''), data.cnt_${measure} FROM ( SELECT DISTINCT ip FROM log_ip_aggr lg @@ -172,7 +177,7 @@ FROM crosstab( .then(data => { logger.trace(); if (data) { - resolve({data: data, header: header}); // data + resolve({data: data, header: ['ip','sum',...header]}); // data } else { reject({ diff --git a/app/routes/adminRoutes.js b/app/routes/adminRoutes.js index 0594495..24140f2 100644 --- a/app/routes/adminRoutes.js +++ b/app/routes/adminRoutes.js @@ -131,7 +131,28 @@ router.get('/admin/user/:userId', function (req, res, next) { router.get('/admin/ips', function (req, res, next) { logger.trace(); let user = req.session.user; - res.render('ips', {user: user, ips_active: true}); + let val = { + measure: req.query.measure || 'units', + level: req.query.level || 'month', + start: req.query.start || (new Date().getFullYear())+'-01-01', + end: req.query.end || (new Date().getFullYear()+1)+'-01-01', + min_exist: req.query.min_exist || 0 + }; + var table_params = []; +logger.error('post ws get !!! ',req); + + for (const [k,v] of Object.entries(val)){ + table_params.push(`${k}=${v}`); + logger.error(`${k}=${v}`); + } + res.render('ips', { + user: user, + ips_active: true, + measures: ["units", "requests", "body_bytes_sent"], + levels: ["month", "day"], + val: val, + table_params: table_params.join('&') + }); }); router.get('/admin/ip/:ip', function (req, res, next) { diff --git a/app/routes/apiRoutes.js b/app/routes/apiRoutes.js index 0f51ddd..e9a9961 100644 --- a/app/routes/apiRoutes.js +++ b/app/routes/apiRoutes.js @@ -298,6 +298,7 @@ router.get('/api/users', function (req, res, next) { router.get('/api/ips', function (req, res, next) { logger.trace(); let user = req.session.user; + if (!user.is_admin) { res.status(403); res.send({ @@ -305,7 +306,14 @@ router.get('/api/ips', function (req, res, next) { error : 'Permission Denied.' }); } else { - dataController.getTopIPs(user.user_id).then(data => { + dataController.getTopIPs(user.user_id, + {}, + (req.query.start || (new Date().getFullYear())+'-01-01')+' 00:00:00', + (req.query.end || (new Date().getFullYear()+1)+'-01-01')+' 00:00:00', + req.query.measure || 'units', + req.query.level || 'month', + req.query.min_exist || 0 + ).then(data => { res.json(data); }).catch(); } diff --git a/app/views/ips.pug b/app/views/ips.pug index 8b87e38..1308f73 100644 --- a/app/views/ips.pug +++ b/app/views/ips.pug @@ -17,8 +17,46 @@ block content .divider .row .col.s12 - h6 Last three months IP list - table.striped(type='lb-datatable' data-type='json' data-field='data' data-url='api/ips' data-header-field='header' data-items-field='header' ) + form(method="get") + .row + .input-field.col.s12 + i.material-icons.prefix format_size + .select-wrapper + select.browser-default#level(name="level") + each l in levels + option(value=l, selected= (l==val.level) ? 'selected' : false)= l + label(for="level") Period level size (table column) + .row + .input-field.col.s6 + i.material-icons.prefix compare + .select-wrapper + select.browser-default#measure(name="measure") + each m in measures + option(value=m, selected= (m==val.measure) ? 'selected' : false)= m + label(for="measure") Measure + .input-field.col.s6 + i.material-icons.prefix chevron_right + input#min_exist.validate(name="min_exist" type="number" step="1" min="0" required="" aria-required="true" value=val.min_exist ) + label(for="min_exist") minimum required value + span.helper-text(data-error="Number Required") + .row + .input-field.col.s6 + i.material-icons.prefix date_range + input#start.validate(name="start" type="date" required="" aria-required="true" value=val.start ) + label(for="start") Start date (included) + span.helper-text(data-error="Date Required") + .input-field.col.s6 + i.material-icons.prefix last_page + input#end.validate(name="end" type="date" required="" aria-required="true" value=val.end ) + label(for="end") End date (excluded) + span.helper-text(data-error="Date Required") + .row + .input-field.col.s12 + button.btn.grey.waves-effect.col.s12.white-text(type="submit") + strong Get Data + .row + .col.s12 + table.striped(type='lb-datatable' data-type='json' data-field='data' data-url='api/ips?'+table_params data-header-field='header' data-items-field='header' ) script. [ { "targets": 0,