|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // Original file created by Prof.Dr. Matthias Hopf
-
- /**
- * Express based http & https server
- *
- * Requires express >= 4
- */
- var common = require('./server/common'),
- authorize = require('./server/authorization'),
- dbs = require('./server/dbs');
- /*
- 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
- mong = common.mongoose, // mongoose
- // serveFavicon = require('serve-favicon'), // provide favicon
- bodyParser = require('body-parser'), // post request bodyparser
- MongoStore = require('connect-mongo')(session); // use mongodb as session storage
-
- var app = express();
-
- /*
- * Init
- */
- common .init();
- authorize .init(common);
- dbs .init (common);
- //files .init (common);
- mong.Promise = global.Promise;
-
- /*
- * 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');
-
-
- /*
- * Route Control
- */
- // 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: mong.connection,
- ttl: 30 * 24 * 3600
- }), // mongoose + connect-mongo
- //store: new MemoryStore ({checkPeriod: 24*3600*1000}), // memorystore
- }));
-
- // TODO Favicon for Desktop
- //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 access to 'public' folder
- app.use(express.static(__dirname + '/public'));
-
- // Other stuff is NOT authorized unless logged in
- //app.use (authorize.genCheckAuthorized ('user'));
-
- // 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);
-
- // Validate all other API calls
- //api_routes.use(authorize.genCheckAuthorized('user'));
- api_routes.post('/logout', authorize.logout);
-
- // Add API routes
- function addRoutes(r) {
- for (var e in r.routes) {
- var route = '/' + e + (r.routes[e].params ? "/" + r.routes[e].params : "");
- var log = "Adding routes for " + route + ":";
- /*
- var auth = r.routes[e].auth || r.auth;
- if (auth) {
- log += " [auth]";
- api_routes.use (route, function (req, res, next) {
- if (! auth(req))
- return next (common.genError (403, "Unauthorized"));
- next ();
- });
- }
- */
- /*
- var role = r.routes[e].role || r.role;
- if (role) {
- log += " [role:"+role+"]";
- api_routes.use (route, authorize.genCheckAuthorized (role));
- }
- */
- const methods = ["get", "post", "put", "delete"];
- for (var m in methods) {
- if (r.routes[e][methods[m]]) {
- log += " " + methods[m];
- api_routes[methods[m]](route, r.routes[e][methods[m]]);
- }
- }
- console.log(log);
- }
- }
-
- addRoutes(dbs);
-
- /*
- * 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);
- });
|