'use strict'; process.env.TZ = 'Etc/GMT'; console.log('Loading Goodtimes'); const express = require('express'), bodyParser = require('body-parser'), config = require('config'), session = require('express-session'), sqliteStoreFactory = require('express-session-sqlite').default, basePath = require('./basepath'), app = express(), csrf = require('csurf'), http = require('http'), methodOverride = require('method-override'), cookieParser = require('cookie-parser'), { goodTimesDB } = require('./db.js'), sqlite3 = require('sqlite3'), SqliteStore = sqliteStoreFactory(session); require('./console-line.js'); /* Monkey-patch console.log with line numbers */ /* App is behind an nginx proxy which we trust, so use the remote address * set in the headers */ app.set('trust proxy', true); app.use(session({ secret: 'm@g1x!c00k13$', maxAge: 14 * 24 * 60 * 60 * 1000, /* 2 weeks */ resave: true, saveUninitialized: false, cookie: { secure: true }, store: new SqliteStore({ driver: sqlite3.Database, path: config.get('sessions.db'), ttl: 5000, cleanupInterval: 300000 }), })); app.use(bodyParser.urlencoded({ extended: false })); app.use((req, res, next) => { console.log('CSRF debug: ', { token: req.header('CSRF-Token'), method: req.method }); next(); }); app.use(cookieParser()); app.use(csrf({ cookie: true })); app.use(bodyParser.json()); //const ws = require('express-ws')(app, server); /* Initialize the data base, configure routes, and open server */ goodTimesDB.init().then((db) => { console.log('DB connected. Configuring routes.'); app.locals.db = db; app.set('basePath', basePath); // eslint-disable-next-line no-unused-vars app.use((req, _res, next) => { console.log( `${req.method} ${req.path} - ` + `${req.session.userId ? req.session.userId : 'Not logged in'}` ); next(); }); app.use(`${basePath}api/v1/users`, require('./routes/users')); app.use((req, res, next) => { if (!req.session.userId) { return res.status(401).send({ message: `You must be logged in.` }); } next(); }); app.use(`${basePath}api/v1/groups`, require('./routes/groups')); app.use(`${basePath}api/v1/events`, require('./routes/events')); app.use(`${basePath}api/v1/locations`, require('./routes/locations')); /* Error handler and catch for 404 */ app.use(methodOverride()); // eslint-disable-next-line no-unused-vars app.use((err, req, res, _next) => { console.log('CSRF debug: ', { token: req.header('CSRF-Token'), csrf: req.csrfToken(), method: req.method }); console.error(err); res.status(err.status || 500).json({ message: err.message, error: {} }); }); }).then(() => { const server = http.createServer(app), serverConfig = config.get('server'); console.log('Hosting server from: ' + basePath); app.set('port', serverConfig.port); process.on('SIGINT', () => { console.log('Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds'); setTimeout(() => process.exit(-1), 2000); server.close(() => process.exit(1)); }); server.on('error', function (error) { if (error.syscall !== 'listen') { throw error; } // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(serverConfig.port + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(serverConfig.port + ' is already in use'); process.exit(1); break; default: throw error; } }); server.listen(serverConfig.port, () => { console.log(`http server listening on ${serverConfig.port}`); }); });