Server.coffee 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. Path = require "path"
  2. express = require('express')
  3. Settings = require('settings-sharelatex')
  4. logger = require 'logger-sharelatex'
  5. metrics = require('metrics-sharelatex')
  6. crawlerLogger = require('./CrawlerLogger')
  7. expressLocals = require('./ExpressLocals')
  8. Router = require('../router')
  9. helmet = require "helmet"
  10. metrics.inc("startup")
  11. UserSessionsRedis = require('../Features/User/UserSessionsRedis')
  12. sessionsRedisClient = UserSessionsRedis.client()
  13. session = require("express-session")
  14. RedisStore = require('connect-redis')(session)
  15. bodyParser = require('body-parser')
  16. multer = require('multer')
  17. methodOverride = require('method-override')
  18. csrf = require('csurf')
  19. csrfProtection = csrf()
  20. cookieParser = require('cookie-parser')
  21. bearerToken = require('express-bearer-token')
  22. # Init the session store
  23. sessionStore = new RedisStore(client:sessionsRedisClient)
  24. passport = require('passport')
  25. LocalStrategy = require('passport-local').Strategy
  26. Mongoose = require("./Mongoose")
  27. oneDayInMilliseconds = 86400000
  28. ReferalConnect = require('../Features/Referal/ReferalConnect')
  29. RedirectManager = require("./RedirectManager")
  30. ProxyManager = require("./ProxyManager")
  31. translations = require("translations-sharelatex").setup(Settings.i18n)
  32. Modules = require "./Modules"
  33. ErrorController = require "../Features/Errors/ErrorController"
  34. UserSessionsManager = require "../Features/User/UserSessionsManager"
  35. AuthenticationController = require "../Features/Authentication/AuthenticationController"
  36. metrics.event_loop?.monitor(logger)
  37. Settings.editorIsOpen ||= true
  38. if Settings.cacheStaticAssets
  39. staticCacheAge = (oneDayInMilliseconds * 365)
  40. else
  41. staticCacheAge = 0
  42. app = express()
  43. webRouter = express.Router()
  44. privateApiRouter = express.Router()
  45. publicApiRouter = express.Router()
  46. if Settings.behindProxy
  47. app.enable('trust proxy')
  48. webRouter.use express.static(__dirname + '/../../../public', {maxAge: staticCacheAge })
  49. app.set 'views', __dirname + '/../../views'
  50. app.set 'view engine', 'pug'
  51. Modules.loadViewIncludes app
  52. app.use bodyParser.urlencoded({ extended: true, limit: "2mb"})
  53. # Make sure we can process the max doc length plus some overhead for JSON encoding
  54. app.use bodyParser.json({limit: Settings.max_doc_length + 64 * 1024}) # 64kb overhead
  55. app.use multer(dest: Settings.path.uploadFolder)
  56. app.use methodOverride()
  57. app.use bearerToken()
  58. app.use metrics.http.monitor(logger)
  59. RedirectManager.apply(webRouter)
  60. ProxyManager.apply(publicApiRouter)
  61. webRouter.use cookieParser(Settings.security.sessionSecret)
  62. webRouter.use session
  63. resave: false
  64. saveUninitialized:false
  65. secret:Settings.security.sessionSecret
  66. proxy: Settings.behindProxy
  67. cookie:
  68. domain: Settings.cookieDomain
  69. maxAge: Settings.cookieSessionLength
  70. secure: Settings.secureCookie
  71. store: sessionStore
  72. key: Settings.cookieName
  73. rolling: true
  74. # passport
  75. webRouter.use passport.initialize()
  76. webRouter.use passport.session()
  77. passport.use(new LocalStrategy(
  78. {
  79. passReqToCallback: true,
  80. usernameField: 'email',
  81. passwordField: 'password'
  82. },
  83. AuthenticationController.doPassportLogin
  84. ))
  85. passport.serializeUser(AuthenticationController.serializeUser)
  86. passport.deserializeUser(AuthenticationController.deserializeUser)
  87. Modules.hooks.fire 'passportSetup', passport, (err) ->
  88. if err?
  89. logger.err {err}, "error setting up passport in modules"
  90. Modules.applyNonCsrfRouter(webRouter, privateApiRouter, publicApiRouter)
  91. webRouter.use csrfProtection
  92. webRouter.use translations.expressMiddlewear
  93. webRouter.use translations.setLangBasedOnDomainMiddlewear
  94. # Measure expiry from last request, not last login
  95. webRouter.use (req, res, next) ->
  96. req.session.touch()
  97. if AuthenticationController.isUserLoggedIn(req)
  98. UserSessionsManager.touch(AuthenticationController.getSessionUser(req), (err)->)
  99. next()
  100. webRouter.use ReferalConnect.use
  101. expressLocals(app, webRouter, privateApiRouter, publicApiRouter)
  102. if app.get('env') == 'production'
  103. logger.info "Production Enviroment"
  104. app.enable('view cache')
  105. app.use (req, res, next)->
  106. metrics.inc "http-request"
  107. crawlerLogger.log(req)
  108. next()
  109. webRouter.use (req, res, next) ->
  110. if Settings.editorIsOpen
  111. next()
  112. else if req.url.indexOf("/admin") == 0
  113. next()
  114. else
  115. res.status(503)
  116. res.render("general/closed", {title:"maintenance"})
  117. # add security headers using Helmet
  118. webRouter.use (req, res, next) ->
  119. isLoggedIn = AuthenticationController.isUserLoggedIn(req)
  120. isProjectPage = !!req.path.match('^/project/[a-f0-9]{24}$')
  121. helmet({ # note that more headers are added by default
  122. dnsPrefetchControl: false
  123. referrerPolicy: { policy: 'origin-when-cross-origin' }
  124. noCache: isLoggedIn || isProjectPage
  125. noSniff: false
  126. hsts: false
  127. frameguard: false
  128. })(req, res, next)
  129. profiler = require "v8-profiler"
  130. privateApiRouter.get "/profile", (req, res) ->
  131. time = parseInt(req.query.time || "1000")
  132. profiler.startProfiling("test")
  133. setTimeout () ->
  134. profile = profiler.stopProfiling("test")
  135. res.json(profile)
  136. , time
  137. app.get "/heapdump", (req, res)->
  138. require('heapdump').writeSnapshot '/tmp/' + Date.now() + '.web.heapsnapshot', (err, filename)->
  139. res.send filename
  140. logger.info ("creating HTTP server").yellow
  141. server = require('http').createServer(app)
  142. # provide settings for separate web and api processes
  143. # if enableApiRouter and enableWebRouter are not defined they default
  144. # to true.
  145. notDefined = (x) -> !x?
  146. enableApiRouter = Settings.web?.enableApiRouter
  147. if enableApiRouter or notDefined(enableApiRouter)
  148. logger.info("providing api router");
  149. app.use(privateApiRouter)
  150. app.use(ErrorController.handleApiError)
  151. enableWebRouter = Settings.web?.enableWebRouter
  152. if enableWebRouter or notDefined(enableWebRouter)
  153. logger.info("providing web router");
  154. app.use(publicApiRouter) # public API goes with web router for public access
  155. app.use(ErrorController.handleApiError)
  156. app.use(webRouter)
  157. app.use(ErrorController.handleError)
  158. router = new Router(webRouter, privateApiRouter, publicApiRouter)
  159. module.exports =
  160. app: app
  161. server: server