/** * Express based http & https server * * Requires express >= 4 */ var common = require ('./server/common'), authorize = require ('./server/authorization'); /* dbs = require ('./server/dbs'), files = require ('./server/files'); */ const fs = common.fs, // file sync, read certificates http = common.http, // http handler https = require ('https'), // https handler express = require ('express'), // node server framework session = require ('express-session'), // session management (security) morgan = require ('morgan'), // logger //serveFavicon = require ('serve-favicon'), bodyParser = require ('body-parser'), // post request bodyparser MongoStore = require ('connect-mongo')(session), // use mongodb as session storage Message = require('./database/message.model.js'); var app = express(); /* * Init */ common .init (); authorize.init (common); //dbs .init (common); //files .init (common); /* * Security * * TODO: Install helmet * https://expressjs.com/de/advanced/best-practice-security.html * * (Disable Header information: Powerd by Express) * -> Information disclosure */ app.disable ('x-powered-by'); // Session Management app.set('trust proxy', 1) // trust first proxy, neccessary for cookie secure: true flag app.use (session({ secret: 'ahhgylhuvh', // caesar(3) 2 letter surname resave: false, saveUninitialized: false, cookie: { maxAge: 30*24*3600*1000, // TODO: ttl for session as well (Store) secure: true, // true for https only (since our app works only with https) }, name: 'om.sid', store: new MongoStore ({mongooseConnection: common.mongoose.connection, ttl: 30*24*3600}), // mongoose + connect-mongo //store: new MemoryStore ({checkPeriod: 24*3600*1000}), // memorystore })); /* * Route Control */ // Fastpaths //app.use (serveFavicon (__dirname + '/public/favicon.ico')); // Minimal Logging //app.use (morgan ('dev')); // Advanced Logging morgan.token ('user', function (req, res) { return (req.session && req.session.user) || '-'; }); morgan.token ('userColored', function (req, res) { var color = 0; if (req.session && req.session.roles) color = req.session.roles.admin ? 31 // red : req.session.roles.user ? 34 // blue : 0; // no color return '\x1b[' + color + 'm' + ((req.session && req.session.user) || '-') + '\x1b[0m'; }); morgan.token ('statusColored', function (req, res) { var color = res.statusCode >= 500 ? 31 // red : res.statusCode >= 400 ? 33 // yellow : res.statusCode >= 300 ? 36 // cyan : res.statusCode >= 200 ? 32 // green : 0; // no color return '\x1b[' + color + 'm' + (res.headersSent ? res.statusCode : '-') + '\x1b[0m'; }); app.use (morgan (':date[iso] :statusColored :method :url :userColored :response-time ms :res[content-length]')); // BodyParser // Returns middleware that only parses json bodies. // (https://www.npmjs.com/package/body-parser#bodyparserjsonoptions) app.use (bodyParser.json()); // Returns middleware that only parses urlencoded bodies // with qs library (https://www.npmjs.com/package/qs#readme) app.use (bodyParser.urlencoded({extended: true})); // API var api_routes = express.Router(); // express app-object routing app.use ('/api', api_routes); // Static Files // Allow server access to 'public' folder app.use(express.static(__dirname + '/public')); // Other stuff is NOT authorized unless logged in //app.use (authorize.genCheckAuthorized ('user')); // Uploaded files //app.use ('/uploads', express.static(__dirname + '/uploads')); // Configuring the database //var dbConfig = require('./mongodb.config.js'); common.mongoose.Promise = global.Promise; // Connecting to the database // Local db: common.config.dbLocalConn // Efi db: common.config.dbConn common.mongoose.connect (common.config.dbLocalConn, {useNewUrlParser: true}) .then( () => { console.log("Successfully connected to MongoDB."); }).catch( err => { console.log('Could not connect to MongoDB.'); process.exit(); }); // No error so far? Then it's a 404! //app.use (function (req, res, next) { next (common.genError (404, req.url)); }); //app.use (routes.errorHandler (true)); /* true: show stack traces */ /* * API */ /* // API allowed for all api_routes.post ('/login', authorize.login); // /api/login // Validate all other API calls api_routes.use (authorize.genCheckAuthorized ('user')); api_routes.post ('/logout', authorize.logout); function addRoutes (r) { for (var e in r.routes) { var params = r.routes[e].params ? "/" + r.routes[e].params : ""; console.log ("Adding routes for /" + e + params + ":" + (r.routes[e].get ? " get":" ") + (r.routes[e].post ? " post":" ") + (r.routes[e].put ? " put":" ") + (r.routes[e].delete ? " delete":" ")); if (r.routes[e].get) api_routes.get ('/' + e + params, r.routes[e].get); if (r.routes[e].post) api_routes.post ('/' + e + params, r.routes[e].post); if (r.routes[e].put) api_routes.put ('/' + e + params, r.routes[e].put); if (r.routes[e].delete) api_routes.delete ('/' + e + params, r.routes[e].delete); } } */ app.get ('/api/ids', function (req, res) { Message.find({},{id: true}) .exec () .then(results => { //selects id from message: var parsed = []; for (var i in results) { parsed.push (results[i].id); } //var parsed = results.map (x => x._id); res.send(parsed); } ) .catch(err => { console.log (err); res .status(500) .json (err); }); }); app.get ("/api/msg/:id", function (req, res) { Message.findOne ({_id: req.params.id}) .exec (function (err, results){ if (err) { console.log (err); res .status(404) .json (err); } else { console.log(JSON.stringify(results)); res.json(results); } }); }); /*app.get ("/api/msg/search/:phrase", function (req, res) { Message.find ({$text: {$search: req.params.phrase}) .then (function (err, results){ if (err) { console.log (err); res .status(404) .json (err); } else { console.log(JSON.stringify(results)); res.json(results); } }); }); */ /*function makeid() { var text = ""; var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (var i = 0; i < 5; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; }*/ app.post("/api/createMsg", function(req, res){ //x = mongoose.Types.ObjectId(); //y = x.toString(); //var z = makeid(); console.log("SUbject: "+JSON.stringify(req.body)); var message = new Message( {subject: req.body.sub, message: req.body.mess, user: req.body.use, tag: req.body.ta } ); message.save(function(err,result){ if(err){ return res .status(401) .send(err.message); }else{ res.json({message: "Message created!!"}); } }); }); /* addRoutes (dbs); addRoutes (admin); addRoutes (files); */ /* * Servers */ http.createServer (app) .listen (common.config.httpPort, function () { console.log ("Express http server listening on port " + common.config.httpPort); }); /* * SSL certificates * * Keys + Certificate in current dir (not servable!) * to create (self-signed) SSL certs: * * openssl genrsa -out privatekey.pem 1024 * openssl req -new -key privatekey.pem -out certrequest.csr * openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem * rm certrequest.csr */ if (common.config.httpsPort) { var options; try { try { // In case it's a real certificate: add CA chain cersts (TODO: use array if required) var ca = fs.readFileSync ('keys/ca_cert.pem'); } catch (e) { ca = undefined; console.log ("Note: Can't read CA bundle: "+e); } if (ca != undefined) { options = { key: fs.readFileSync ('keys/omkey.pem'), cert: fs.readFileSync ('keys/certificate.pem'), ca: ca }; https.createServer (options, app) .listen (common.config.httpsPort, function () { console.log ("Express https server listening on port " + common.config.httpsPort); }); } } catch (e) { console.log ("Note: Can't read SSL keys/certs: "+e+"\nDisabling https server"); } } else { console.log("Note: https server disabled by config"); } /* * Uncaught Exceptions */ process.on ("uncaughtException", function (err) { console.error ("*** Uncaught Exception:"); console.error (err.stack); });