server.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { AConfigChecker } from './src/AConfigChecker';
  2. import * as express from 'express';
  3. import { AddressInfo } from "net";
  4. import * as path from 'path';
  5. import * as bodyParser from 'body-parser';
  6. import route_index from './routes/index';
  7. import route_login from './routes/login';
  8. import Security from './src/Security';
  9. import { Session, SessionManager } from './src/Session';
  10. import UserConnectorFactory from './src/UserConnector/UserConnectorFactory';
  11. const debug = require('debug')('my express app');
  12. const app = express();
  13. declare global {
  14. namespace Express {
  15. interface Request {
  16. mSession: Session
  17. mCookies: Map<string, string>
  18. }
  19. }
  20. }
  21. // Check config
  22. (_ => {
  23. let cc: AConfigChecker[] = [
  24. UserConnectorFactory
  25. ];
  26. for (let i of cc) {
  27. let err = i.CheckConfig();
  28. if (err) {
  29. err = i.constructor.name + ": " + err;
  30. console.error("Configuration error: " + err);
  31. throw "Configuration error";
  32. }
  33. }
  34. })();
  35. // view engine setup
  36. app.set('views', [path.join(__dirname, 'views'), path.join(__dirname, 'views/template')]);
  37. app.set('view engine', 'pug');
  38. app.use(express.static(path.join(__dirname, 'public')));
  39. app.use(bodyParser.json());
  40. app.use(bodyParser.urlencoded({ extended: true }));
  41. // Security and session setup
  42. app.use((req, _, next) => {
  43. req.mCookies = new Map();
  44. (req.headers?.cookie || "").split(";").forEach(i => {
  45. let keyValue = i.split("=", 2);
  46. req.mCookies.set(keyValue[0].trim(), keyValue[1].trim());
  47. });
  48. req.mSession = SessionManager.GetSession(req);
  49. if (req.mSession.IsValid())
  50. req.mSession.Ping();
  51. if (req.query["API_KEY"])
  52. if (!Security.TryLoginApiKey(req.query["API_KEY"].toString())) {
  53. let err: any = new Error("Access denied");
  54. err['status'] = 403;
  55. next(err);
  56. return;
  57. }
  58. next();
  59. });
  60. // Annonymous pages
  61. app.use('/', route_index);
  62. app.use('/login', route_login);
  63. // Login check
  64. app.use((req, res, next) => {
  65. if (!req.mSession.IsValid()) {
  66. const URL = '/login?redirect=' + encodeURIComponent(req.url);
  67. res.status(302);
  68. res.setHeader("Location", URL);
  69. res.send("<!DOCTYPE html><html><body><a href='" + URL + "'>" + URL + "</a><script>document.location.href='" + URL + "';</script></html>");
  70. } else {
  71. next();
  72. }
  73. });
  74. // Any following routes need login
  75. app.use('/logged', route_index);
  76. // catch 404 and forward to error handler
  77. app.use((_, __, next) => {
  78. const err: any = new Error('Not Found');
  79. err['status'] = 404;
  80. next(err);
  81. });
  82. // error handlers
  83. // development error handler
  84. // will print stacktrace
  85. if (app.get('env') === 'development') {
  86. app.use((err: any, req: Express.Request, res: any, next: any) => { // eslint-disable-line @typescript-eslint/no-unused-vars
  87. res.status(err['status'] || 500);
  88. res.render('error', {
  89. message: err.message,
  90. error: err
  91. });
  92. });
  93. }
  94. // production error handler
  95. // no stacktraces leaked to user
  96. app.use((err: any, _: any, res: any, __: any) => { // eslint-disable-line @typescript-eslint/no-unused-vars
  97. res.status(err.status || 500);
  98. res.render('error', {
  99. message: err.message,
  100. error: {}
  101. });
  102. });
  103. app.set('port', process.env.port || 1337);
  104. const server = app.listen(app.get('port'), function () {
  105. debug(`Express server listening on port ${(server.address() as AddressInfo).port}`);
  106. });