index.js 5.94 KB
var express = require('express');
var nunjucks = require('nunjucks');
var session = require('express-session');
var MongoStore = require('connect-mongo/es5')(session);
var bodyParser = require('body-parser');
var mongoClient = require('mongodb').MongoClient;
var crypto = require('crypto');
var strftime = require('strftime');
var querystring = require('querystring');
var morgan = require('morgan');
var FileStreamRotator = require('file-stream-rotator');
var fs = require('fs');

var config = require('./config.json');

var mongodb;

process.chdir(__dirname);

var logDirectory = __dirname + '/logs';
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);

// create a rotating write stream
var accessLogStream = FileStreamRotator.getStream({
    date_format: 'YYYYMMDD',
    filename: logDirectory + '/access-%DATE%.log',
    frequency: 'daily',
    verbose: false
});

function initMongoClient() {
    if (!config.mongodb || !config.mongodb.url) {
        return;
    }

    try {
        var url = config.mongodb.url;

        mongoClient.connect(url, function(err, db) {
            if (err) {
                console.log('Failed to connect to mongodb');
                return;
            }
            mongodb = db;
            console.log('MongoDB connected');
        });
    }
    catch(err) {
        console.log('Exception when connecting to mongodb');
    }
}
initMongoClient();


var app = express();

app.use(morgan('combined', {stream: accessLogStream}));
app.use(session({
  secret: config.session_secret,
  name: 'cjkmonitor.sid',
  store: new MongoStore({url: config.mongodb.url}),
  resave: false,
  saveUninitialized: false,
}))

app.use(express.static('public', {maxAge: 24 * 3600 * 1000}));
app.use(bodyParser.urlencoded({extended: true}));

app.set('views', './views');
//app.set('view cache', false);

nunjucks.configure('views', {
    autoescape: true,
    express: app
});

function authNeeded(req, res, next) {
    if (req.session.username) {
        next();
    } else {
        res.redirect('/signin');
    }
}

function createPaginatorObject(total, perpage, path, qs) {
    var pageCount = Math.ceil(total / perpage);
    var pages = [];

    var newQs = querystring.parse(querystring.stringify(qs));



    for (var i = 0; i < pageCount; i++) {

        var pageNumber = i + 1;

        pages[i] = {
            'number': pageNumber,
        }

        if (pageNumber == qs.page) {
            pages[i].active = true;
        }

        newQs.page = pageNumber;
        pages[i].link =  path + '?' + querystring.stringify(newQs);

    }
    return pages;
}

function pageHome(req, res, next) {
    var limitPerPage = 50;

    var page = 1;
    if (req.query.page) {
        page = req.query.page;
    } else {
        req.query.page = page;
    }

    var skip = (page - 1) * limitPerPage;

    var trxdate = '';
    if (req.query.trxdate) {
        trxdate = req.query.trxdate;
    }
    else if (req.body.trxdate) {
        trxdate = req.body.trxdate;
    } else {
        trxdate = strftime('%Y-%m-%d', new Date());
        res.redirect('/?trxdate=' + trxdate);
        return;
    }

    var conditions = {
        ts_date: trxdate.trim()
    };

    if (req.query.destination) {
        conditions.destination = req.query.destination.trim();
    }

    if (req.query.product) {
        conditions.product = req.query.product.trim();
    }

    mongodb.collection('trx').find(conditions).count(function(err, count) {

        if (err) {
            var errorMessage = 'Something wrong when retrieving number of docs on mongo: ' + err;
            console.log(errorMessage);
            res.send(errorMessage);
            return;
        }

        var pagecount = Math.ceil(count / limitPerPage);
        var paginator = createPaginatorObject(count, limitPerPage, req.path, req.query);

        mongodb.collection('trx').find(conditions).sort([['ts', -1]]).skip(skip).limit(limitPerPage).toArray(function (err, docs) {

            if (err) {
                var errorMessage = 'Something wrong when retrieving docs from mongo: ' + err;
                console.log(errorMessage);
                res.send(errorMessage);
                return;
            }

            res.render('index.html', {
                title: 'Transactions',
                conditions: conditions,
                trxdate: trxdate,
                trxcount: count,
                pagecount: pagecount,
                limitperpage: limitPerPage,
                paginator: paginator,
                debugmsg: JSON.stringify(paginator),
                trxs: docs,
                suppliers: ['CJK', 'TRUST']
            });
        });
    });
}

function pageTrxView(req, res, next) {

    mongodb.collection('trx').find({requestId: req.params.id}).limit(1).next(function(err, doc) {
        res.render(
            'trx.view.html',
            {
                title: 'Transaction #' + req.params.id,
                trx: doc
            }
        );

    });

}

function pageSigninForm(req, res, next) {
    if (req.session.username) {
        res.redirect('/');
        return;
    }

    res.render('signin.html');
}

function pageSigninPost(req, res, next) {
    var passwordHash = crypto.createHash('sha256').update(req.body.password).digest().toString('hex');
    mongodb.collection('users').findOne({email: req.body.username, password: passwordHash}, function(err, doc) {
        if (err) {
            res.redirect('/signin');
            return;
        }

        if (!doc) {
            res.redirect('/signin');
            return;
        }

        req.session.username = req.body.username;
        res.redirect('/');

    });
}

function logout(req, res, next) {
    req.session.username = null;
    res.redirect('/signin');
}

app.all('/', authNeeded, pageHome);
app.get('/signin', pageSigninForm);
app.post('/signin', pageSigninPost);
app.get('/logout', logout);

app.get('/trx/view/:id', authNeeded, pageTrxView);

app.listen(config.listen_port, function () {
  console.log('Example app listening on port ' + config.listen_port);
});