overleaf/services/web/app/coffee/infrastructure/Server.coffee

200 lines
5.8 KiB
CoffeeScript
Raw Normal View History

2014-05-07 10:29:04 -04:00
Path = require "path"
2014-02-12 05:23:40 -05:00
express = require('express')
Settings = require('settings-sharelatex')
logger = require 'logger-sharelatex'
metrics = require('metrics-sharelatex')
2014-02-12 05:23:40 -05:00
crawlerLogger = require('./CrawlerLogger')
expressLocals = require('./ExpressLocals')
Router = require('../router')
helmet = require "helmet"
2014-02-12 05:23:40 -05:00
metrics.inc("startup")
UserSessionsRedis = require('../Features/User/UserSessionsRedis')
sessionsRedisClient = UserSessionsRedis.client()
2014-09-26 12:04:33 -04:00
2015-06-30 07:04:41 -04:00
session = require("express-session")
RedisStore = require('connect-redis')(session)
bodyParser = require('body-parser')
multer = require('multer')
methodOverride = require('method-override')
csrf = require('csurf')
csrfProtection = csrf()
cookieParser = require('cookie-parser')
# Init the session store
sessionStore = new RedisStore(client:sessionsRedisClient)
2014-09-26 12:04:33 -04:00
2016-09-02 11:17:37 -04:00
passport = require('passport')
LocalStrategy = require('passport-local').Strategy
2015-06-30 07:04:41 -04:00
Mongoose = require("./Mongoose")
2014-02-12 05:23:40 -05:00
oneDayInMilliseconds = 86400000
ReferalConnect = require('../Features/Referal/ReferalConnect')
RedirectManager = require("./RedirectManager")
2018-06-18 12:37:58 -04:00
ProxyManager = require("./ProxyManager")
translations = require("translations-sharelatex").setup(Settings.i18n)
2014-09-08 10:40:46 -04:00
Modules = require "./Modules"
2014-02-12 05:23:40 -05:00
ErrorController = require "../Features/Errors/ErrorController"
2016-07-01 06:24:46 -04:00
UserSessionsManager = require "../Features/User/UserSessionsManager"
2016-09-02 11:17:37 -04:00
AuthenticationController = require "../Features/Authentication/AuthenticationController"
2014-02-12 05:23:40 -05:00
2015-06-23 08:50:42 -04:00
metrics.event_loop?.monitor(logger)
2014-02-12 05:23:40 -05:00
Settings.editorIsOpen ||= true
if Settings.cacheStaticAssets
staticCacheAge = (oneDayInMilliseconds * 365)
else
staticCacheAge = 0
app = express()
webRouter = express.Router()
2017-07-05 09:32:55 -04:00
privateApiRouter = express.Router()
publicApiRouter = express.Router()
2014-07-30 09:22:36 -04:00
2015-06-30 07:04:41 -04:00
if Settings.behindProxy
app.enable('trust proxy')
webRouter.use express.static(__dirname + '/../../../public', {maxAge: staticCacheAge })
2015-06-30 07:04:41 -04:00
app.set 'views', __dirname + '/../../views'
2017-01-20 07:03:02 -05:00
app.set 'view engine', 'pug'
2015-06-30 07:04:41 -04:00
Modules.loadViewIncludes app
2015-07-08 09:34:59 -04:00
app.use bodyParser.urlencoded({ extended: true, limit: "2mb"})
# Make sure we can process the max doc length plus some overhead for JSON encoding
app.use bodyParser.json({limit: Settings.max_doc_length + 16 * 1024}) # 16kb overhead
app.use multer(dest: Settings.path.uploadFolder)
app.use methodOverride()
app.use metrics.http.monitor(logger)
app.use RedirectManager
2018-07-04 12:59:19 -04:00
ProxyManager.apply(publicApiRouter)
webRouter.use cookieParser(Settings.security.sessionSecret)
webRouter.use session
2015-06-30 07:04:41 -04:00
resave: false
saveUninitialized:false
2015-06-30 07:04:41 -04:00
secret:Settings.security.sessionSecret
proxy: Settings.behindProxy
cookie:
domain: Settings.cookieDomain
maxAge: Settings.cookieSessionLength
secure: Settings.secureCookie
store: sessionStore
key: Settings.cookieName
2016-11-30 04:41:58 -05:00
rolling: true
2015-06-30 07:04:41 -04:00
2016-09-02 11:17:37 -04:00
# passport
webRouter.use passport.initialize()
webRouter.use passport.session()
passport.use(new LocalStrategy(
{
passReqToCallback: true,
usernameField: 'email',
passwordField: 'password'
},
AuthenticationController.doPassportLogin
))
passport.serializeUser(AuthenticationController.serializeUser)
passport.deserializeUser(AuthenticationController.deserializeUser)
Modules.hooks.fire 'passportSetup', passport, (err) ->
if err?
logger.err {err}, "error setting up passport in modules"
2017-07-05 09:32:55 -04:00
Modules.applyNonCsrfRouter(webRouter, privateApiRouter, publicApiRouter)
webRouter.use csrfProtection
webRouter.use translations.expressMiddlewear
webRouter.use translations.setLangBasedOnDomainMiddlewear
2015-06-30 07:04:41 -04:00
# Measure expiry from last request, not last login
webRouter.use (req, res, next) ->
2015-06-30 07:04:41 -04:00
req.session.touch()
2016-09-22 08:48:09 -04:00
if AuthenticationController.isUserLoggedIn(req)
UserSessionsManager.touch(AuthenticationController.getSessionUser(req), (err)->)
2015-06-30 07:04:41 -04:00
next()
2014-02-12 05:23:40 -05:00
webRouter.use ReferalConnect.use
2017-07-05 09:32:55 -04:00
expressLocals(app, webRouter, privateApiRouter, publicApiRouter)
2014-02-12 05:23:40 -05:00
2015-06-30 07:04:41 -04:00
if app.get('env') == 'production'
2014-02-12 05:23:40 -05:00
logger.info "Production Enviroment"
app.enable('view cache')
app.use (req, res, next)->
metrics.inc "http-request"
crawlerLogger.log(req)
next()
webRouter.use (req, res, next) ->
if Settings.editorIsOpen
next()
else if req.url.indexOf("/admin") == 0
next()
else
2014-02-12 05:23:40 -05:00
res.status(503)
2014-08-01 08:47:14 -04:00
res.render("general/closed", {title:"maintenance"})
2014-02-12 05:23:40 -05:00
# add security headers using Helmet
webRouter.use (req, res, next) ->
isLoggedIn = AuthenticationController.isUserLoggedIn(req)
isProjectPage = !!req.path.match('^/project/[a-f0-9]{24}$')
helmet({ # note that more headers are added by default
dnsPrefetchControl: false
referrerPolicy: { policy: 'origin-when-cross-origin' }
noCache: isLoggedIn || isProjectPage
2017-09-13 05:53:11 -04:00
noSniff: false
hsts: false
frameguard: false
})(req, res, next)
2015-02-03 06:05:23 -05:00
profiler = require "v8-profiler"
2017-07-05 09:32:55 -04:00
privateApiRouter.get "/profile", (req, res) ->
2015-02-03 06:05:23 -05:00
time = parseInt(req.query.time || "1000")
profiler.startProfiling("test")
setTimeout () ->
profile = profiler.stopProfiling("test")
res.json(profile)
, time
2014-02-12 05:23:40 -05:00
2015-11-30 11:16:16 -05:00
app.get "/heapdump", (req, res)->
2016-04-19 11:48:51 -04:00
require('heapdump').writeSnapshot '/tmp/' + Date.now() + '.web.heapsnapshot', (err, filename)->
2015-11-30 11:16:16 -05:00
res.send filename
2014-02-12 05:23:40 -05:00
logger.info ("creating HTTP server").yellow
server = require('http').createServer(app)
# provide settings for separate web and api processes
# if enableApiRouter and enableWebRouter are not defined they default
# to true.
notDefined = (x) -> !x?
enableApiRouter = Settings.web?.enableApiRouter
if enableApiRouter or notDefined(enableApiRouter)
logger.info("providing api router");
2017-07-05 09:32:55 -04:00
app.use(privateApiRouter)
app.use(ErrorController.handleApiError)
enableWebRouter = Settings.web?.enableWebRouter
if enableWebRouter or notDefined(enableWebRouter)
logger.info("providing web router");
2017-07-05 09:32:55 -04:00
app.use(publicApiRouter) # public API goes with web router for public access
2017-07-05 10:06:23 -04:00
app.use(ErrorController.handleApiError)
app.use(webRouter)
app.use(ErrorController.handleError)
2017-07-05 09:32:55 -04:00
router = new Router(webRouter, privateApiRouter, publicApiRouter)
2014-02-12 05:23:40 -05:00
module.exports =
app: app
server: server