Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.js 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // Original file created by Prof.Dr. Matthias Hopf
  2. /**
  3. * Express based http & https server
  4. *
  5. * Requires express >= 4
  6. */
  7. var common = require('./server/common'),
  8. authorize = require('./server/authorization'),
  9. dbs = require('./server/dbs');
  10. /*
  11. dbs = require ('./server/dbs'),
  12. files = require ('./server/files');
  13. */
  14. const fs = common.fs, // file sync, read certificates
  15. http = common.http, // http handler
  16. https = require('https'), // https handler
  17. express = require('express'), // node server framework
  18. session = require('express-session'), // session management (security)
  19. morgan = require('morgan'), // logger
  20. mong = common.mongoose, // mongoose
  21. // serveFavicon = require('serve-favicon'), // provide favicon
  22. bodyParser = require('body-parser'), // post request bodyparser
  23. MongoStore = require('connect-mongo')(session); // use mongodb as session storage
  24. var app = express();
  25. /*
  26. * Init
  27. */
  28. common .init();
  29. authorize .init(common);
  30. dbs .init (common);
  31. //files .init (common);
  32. mong.Promise = global.Promise;
  33. /*
  34. * Security
  35. *
  36. * TODO: Install helmet
  37. * https://expressjs.com/de/advanced/best-practice-security.html
  38. *
  39. * (Disable Header information: Powerd by Express)
  40. * -> Information disclosure
  41. */
  42. app.disable('x-powered-by');
  43. /*
  44. * Route Control
  45. */
  46. // Session Management
  47. app.set('trust proxy', 1) // trust first proxy, neccessary for cookie secure: true flag
  48. app.use(session({
  49. secret: 'ahhgylhuvh', // caesar(3) 2 letter surname
  50. resave: false,
  51. saveUninitialized: false,
  52. cookie: {
  53. maxAge: 30 * 24 * 3600 * 1000, // TODO: ttl for session as well (Store)
  54. secure: true, // true for https only (since our app works only with https)
  55. },
  56. name: 'om.sid',
  57. store: new MongoStore({
  58. mongooseConnection: mong.connection,
  59. ttl: 30 * 24 * 3600
  60. }), // mongoose + connect-mongo
  61. //store: new MemoryStore ({checkPeriod: 24*3600*1000}), // memorystore
  62. }));
  63. // TODO Favicon for Desktop
  64. //app.use (serveFavicon (__dirname + '/public/favicon.ico'));
  65. // Minimal Logging
  66. //app.use (morgan ('dev'));
  67. // Advanced Logging
  68. morgan.token('user', function (req, res) {
  69. return (req.session && req.session.user) || '-';
  70. });
  71. morgan.token('userColored', function (req, res) {
  72. var color = 0;
  73. if (req.session && req.session.roles)
  74. color = req.session.roles.admin ? 31 // red
  75. : req.session.roles.user ? 34 // blue
  76. : 0; // no color
  77. return '\x1b[' + color + 'm' + ((req.session && req.session.user) || '-') + '\x1b[0m';
  78. });
  79. morgan.token('statusColored', function (req, res) {
  80. var color = res.statusCode >= 500 ? 31 // red
  81. : res.statusCode >= 400 ? 33 // yellow
  82. : res.statusCode >= 300 ? 36 // cyan
  83. : res.statusCode >= 200 ? 32 // green
  84. : 0; // no color
  85. return '\x1b[' + color + 'm' + (res.headersSent ? res.statusCode : '-') + '\x1b[0m';
  86. });
  87. app.use(morgan(':date[iso] :statusColored :method :url :userColored :response-time ms :res[content-length]'));
  88. // BodyParser
  89. // Returns middleware that only parses json bodies.
  90. // (https://www.npmjs.com/package/body-parser#bodyparserjsonoptions)
  91. app.use(bodyParser.json());
  92. // Returns middleware that only parses urlencoded bodies
  93. // with qs library (https://www.npmjs.com/package/qs#readme)
  94. app.use(bodyParser.urlencoded({
  95. extended: true
  96. }));
  97. // API
  98. var api_routes = express.Router(); // express app-object routing
  99. app.use('/api', api_routes);
  100. // Static Files - Allow access to 'public' folder
  101. app.use(express.static(__dirname + '/public'));
  102. // Other stuff is NOT authorized unless logged in
  103. //app.use (authorize.genCheckAuthorized ('user'));
  104. // No error so far? Then it's a 404!
  105. app.use(function (req, res, next) {
  106. next(common.genError(404, req.url));
  107. });
  108. //app.use (routes.errorHandler (true)); /* true: show stack traces */
  109. /*
  110. * API
  111. */
  112. // API allowed for all
  113. api_routes.post('/login', authorize.login);
  114. // Validate all other API calls
  115. //api_routes.use(authorize.genCheckAuthorized('user'));
  116. api_routes.post('/logout', authorize.logout);
  117. // Add API routes
  118. function addRoutes(r) {
  119. for (var e in r.routes) {
  120. var route = '/' + e + (r.routes[e].params ? "/" + r.routes[e].params : "");
  121. var log = "Adding routes for " + route + ":";
  122. /*
  123. var auth = r.routes[e].auth || r.auth;
  124. if (auth) {
  125. log += " [auth]";
  126. api_routes.use (route, function (req, res, next) {
  127. if (! auth(req))
  128. return next (common.genError (403, "Unauthorized"));
  129. next ();
  130. });
  131. }
  132. */
  133. /*
  134. var role = r.routes[e].role || r.role;
  135. if (role) {
  136. log += " [role:"+role+"]";
  137. api_routes.use (route, authorize.genCheckAuthorized (role));
  138. }
  139. */
  140. const methods = ["get", "post", "put", "delete"];
  141. for (var m in methods) {
  142. if (r.routes[e][methods[m]]) {
  143. log += " " + methods[m];
  144. api_routes[methods[m]](route, r.routes[e][methods[m]]);
  145. }
  146. }
  147. console.log(log);
  148. }
  149. }
  150. addRoutes(dbs);
  151. /*
  152. * Servers
  153. */
  154. http.createServer(app).listen(common.config.httpPort, function () {
  155. console.log("Express http server listening on port " + common.config.httpPort);
  156. });
  157. /*
  158. * SSL certificates
  159. *
  160. * Keys + Certificate in current dir (not servable!)
  161. * to create (self-signed) SSL certs:
  162. *
  163. * openssl genrsa -out privatekey.pem 1024
  164. * openssl req -new -key privatekey.pem -out certrequest.csr
  165. * openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
  166. * rm certrequest.csr
  167. */
  168. if (common.config.httpsPort) {
  169. var options;
  170. try {
  171. try {
  172. // In case it's a real certificate: add CA chain cersts (TODO: use array if required)
  173. var ca = fs.readFileSync('keys/ca_cert.pem');
  174. } catch (e) {
  175. ca = undefined;
  176. console.log("Note: Can't read CA bundle: " + e);
  177. }
  178. if (ca != undefined) {
  179. options = {
  180. key: fs.readFileSync('keys/omkey.pem'),
  181. cert: fs.readFileSync('keys/certificate.pem'),
  182. ca: ca
  183. };
  184. https.createServer(options, app).listen(common.config.httpsPort, function () {
  185. console.log("Express https server listening on port " + common.config.httpsPort);
  186. });
  187. }
  188. } catch (e) {
  189. console.log("Note: Can't read SSL keys/certs: " + e + "\nDisabling https server");
  190. }
  191. } else {
  192. console.log("Note: https server disabled by config");
  193. }
  194. /*
  195. * Uncaught Exceptions
  196. */
  197. process.on("uncaughtException", function (err) {
  198. console.error("*** Uncaught Exception:");
  199. console.error(err.stack);
  200. });