split site into 2 routers, webRouter and apiRouter

web router has things like sessions etc added onto it. Api router is minimal, doesn't include things like csrf
This commit is contained in:
Henry Oswald 2015-06-30 14:38:32 +01:00
parent 665bdcf538
commit 1cc0cbe8fc
12 changed files with 206 additions and 195 deletions

View file

@ -0,0 +1,5 @@
AnalyticsController = require('./AnalyticsController')
module.exports =
apply: (webRouter, apiRouter) ->
webRouter.post '/event/:event', AnalyticsController.recordEvent

View file

@ -3,9 +3,9 @@ SecurityManager = require('../../managers/SecurityManager')
AuthenticationController = require('../Authentication/AuthenticationController') AuthenticationController = require('../Authentication/AuthenticationController')
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
app.post '/project/:project_id/leave', AuthenticationController.requireLogin(), CollaboratorsController.removeSelfFromProject webRouter.post '/project/:project_id/leave', AuthenticationController.requireLogin(), CollaboratorsController.removeSelfFromProject
app.get '/project/:Project_id/collaborators', SecurityManager.requestCanAccessProject(allow_auth_token: true), CollaboratorsController.getCollaborators apiRouter.get '/project/:Project_id/collaborators', SecurityManager.requestCanAccessProject(allow_auth_token: true), CollaboratorsController.getCollaborators
app.post '/project/:Project_id/users', SecurityManager.requestIsOwner, CollaboratorsController.addUserToProject webRouter.post '/project/:Project_id/users', SecurityManager.requestIsOwner, CollaboratorsController.addUserToProject
app.delete '/project/:Project_id/users/:user_id', SecurityManager.requestIsOwner, CollaboratorsController.removeUserFromProject webRouter.delete '/project/:Project_id/users/:user_id', SecurityManager.requestIsOwner, CollaboratorsController.removeUserFromProject

View file

@ -3,21 +3,20 @@ SecurityManager = require('../../managers/SecurityManager')
AuthenticationController = require "../Authentication/AuthenticationController" AuthenticationController = require "../Authentication/AuthenticationController"
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
app.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc webRouter.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc
app.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder webRouter.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder
app.post '/project/:Project_id/:entity_type/:entity_id/rename', SecurityManager.requestCanModifyProject, EditorHttpController.renameEntity webRouter.post '/project/:Project_id/:entity_type/:entity_id/rename', SecurityManager.requestCanModifyProject, EditorHttpController.renameEntity
app.post '/project/:Project_id/:entity_type/:entity_id/move', SecurityManager.requestCanModifyProject, EditorHttpController.moveEntity webRouter.post '/project/:Project_id/:entity_type/:entity_id/move', SecurityManager.requestCanModifyProject, EditorHttpController.moveEntity
app.delete '/project/:Project_id/file/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteFile webRouter.delete '/project/:Project_id/file/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteFile
app.delete '/project/:Project_id/doc/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteDoc webRouter.delete '/project/:Project_id/doc/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteDoc
app.delete '/project/:Project_id/folder/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteFolder webRouter.delete '/project/:Project_id/folder/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteFolder
app.post '/project/:Project_id/doc/:doc_id/restore', SecurityManager.requestCanModifyProject, EditorHttpController.restoreDoc webRouter.post '/project/:Project_id/doc/:doc_id/restore', SecurityManager.requestCanModifyProject, EditorHttpController.restoreDoc
# Called by the real-time API to load up the current project state. # Called by the real-time API to load up the current project state.
# This is a post request because it's more than just a getting of data. We take actions # This is a post request because it's more than just a getting of data. We take actions
# whenever a user joins a project, like updating the deleted status. # whenever a user joins a project, like updating the deleted status.
app.post '/project/:Project_id/join', AuthenticationController.httpAuth, EditorHttpController.joinProject apiRouter.post '/project/:Project_id/join', AuthenticationController.httpAuth, EditorHttpController.joinProject
app.ignoreCsrf('post', '/project/:Project_id/join')

View file

@ -2,13 +2,13 @@ PasswordResetController = require("./PasswordResetController")
AuthenticationController = require('../Authentication/AuthenticationController') AuthenticationController = require('../Authentication/AuthenticationController')
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
app.get '/user/password/reset', PasswordResetController.renderRequestResetForm webRouter.get '/user/password/reset', PasswordResetController.renderRequestResetForm
app.post '/user/password/reset', PasswordResetController.requestReset webRouter.post '/user/password/reset', PasswordResetController.requestReset
AuthenticationController.addEndpointToLoginWhitelist '/user/password/reset' AuthenticationController.addEndpointToLoginWhitelist '/user/password/reset'
app.get '/user/password/set', PasswordResetController.renderSetPasswordForm webRouter.get '/user/password/set', PasswordResetController.renderSetPasswordForm
app.post '/user/password/set', PasswordResetController.setNewUserPassword webRouter.post '/user/password/set', PasswordResetController.setNewUserPassword
AuthenticationController.addEndpointToLoginWhitelist '/user/password/set' AuthenticationController.addEndpointToLoginWhitelist '/user/password/set'

View file

@ -10,8 +10,8 @@ wsProxy = httpProxy.createProxyServer({
}) })
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
app.all /\/socket\.io\/.*/, (req, res, next) -> webRouter.all /\/socket\.io\/.*/, (req, res, next) ->
proxy.web req, res, next proxy.web req, res, next
setTimeout () -> setTimeout () ->

View file

@ -3,18 +3,18 @@ UniversityController = require("./UniversityController")
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
app.get '/', HomeController.index webRouter.get '/', HomeController.index
app.get '/home', HomeController.home webRouter.get '/home', HomeController.home
app.get '/tos', HomeController.externalPage("tos", "Terms of Service") webRouter.get '/tos', HomeController.externalPage("tos", "Terms of Service")
app.get '/about', HomeController.externalPage("about", "About Us") webRouter.get '/about', HomeController.externalPage("about", "About Us")
app.get '/security', HomeController.externalPage("security", "Security") webRouter.get '/security', HomeController.externalPage("security", "Security")
app.get '/privacy_policy', HomeController.externalPage("privacy", "Privacy Policy") webRouter.get '/privacy_policy', HomeController.externalPage("privacy", "Privacy Policy")
app.get '/planned_maintenance', HomeController.externalPage("planned_maintenance", "Planned Maintenance") webRouter.get '/planned_maintenance', HomeController.externalPage("planned_maintenance", "Planned Maintenance")
app.get '/style', HomeController.externalPage("style_guide", "Style Guide") webRouter.get '/style', HomeController.externalPage("style_guide", "Style Guide")
app.get '/dropbox', HomeController.externalPage("dropbox", "Dropbox and ShareLaTeX") webRouter.get '/dropbox', HomeController.externalPage("dropbox", "Dropbox and ShareLaTeX")
app.get '/university', UniversityController.getIndexPage webRouter.get '/university', UniversityController.getIndexPage
app.get '/university/*', UniversityController.getPage webRouter.get '/university/*', UniversityController.getPage

View file

@ -4,44 +4,43 @@ SubscriptionGroupController = require './SubscriptionGroupController'
Settings = require "settings-sharelatex" Settings = require "settings-sharelatex"
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
return unless Settings.enableSubscriptions return unless Settings.enableSubscriptions
app.get '/user/subscription/plans', SubscriptionController.plansPage webRouter.get '/user/subscription/plans', SubscriptionController.plansPage
app.get '/user/subscription', AuthenticationController.requireLogin(), SubscriptionController.userSubscriptionPage webRouter.get '/user/subscription', AuthenticationController.requireLogin(), SubscriptionController.userSubscriptionPage
app.get '/user/subscription/custom_account', AuthenticationController.requireLogin(), SubscriptionController.userCustomSubscriptionPage webRouter.get '/user/subscription/custom_account', AuthenticationController.requireLogin(), SubscriptionController.userCustomSubscriptionPage
app.get '/user/subscription/new', AuthenticationController.requireLogin(), SubscriptionController.paymentPage webRouter.get '/user/subscription/new', AuthenticationController.requireLogin(), SubscriptionController.paymentPage
app.get '/user/subscription/billing-details/edit', AuthenticationController.requireLogin(), SubscriptionController.editBillingDetailsPage webRouter.get '/user/subscription/billing-details/edit', AuthenticationController.requireLogin(), SubscriptionController.editBillingDetailsPage
app.get '/user/subscription/thank-you', AuthenticationController.requireLogin(), SubscriptionController.successful_subscription webRouter.get '/user/subscription/thank-you', AuthenticationController.requireLogin(), SubscriptionController.successful_subscription
app.get '/subscription/group', AuthenticationController.requireLogin(), SubscriptionGroupController.renderSubscriptionGroupAdminPage webRouter.get '/subscription/group', AuthenticationController.requireLogin(), SubscriptionGroupController.renderSubscriptionGroupAdminPage
app.post '/subscription/group/user', AuthenticationController.requireLogin(), SubscriptionGroupController.addUserToGroup webRouter.post '/subscription/group/user', AuthenticationController.requireLogin(), SubscriptionGroupController.addUserToGroup
app.get '/subscription/group/export', AuthenticationController.requireLogin(), SubscriptionGroupController.exportGroupCsv webRouter.get '/subscription/group/export', AuthenticationController.requireLogin(), SubscriptionGroupController.exportGroupCsv
app.delete '/subscription/group/user/:user_id', AuthenticationController.requireLogin(), SubscriptionGroupController.removeUserFromGroup webRouter.delete '/subscription/group/user/:user_id', AuthenticationController.requireLogin(), SubscriptionGroupController.removeUserFromGroup
app.get '/user/subscription/:subscription_id/group/invited', AuthenticationController.requireLogin(), SubscriptionGroupController.renderGroupInvitePage webRouter.get '/user/subscription/:subscription_id/group/invited', AuthenticationController.requireLogin(), SubscriptionGroupController.renderGroupInvitePage
app.post '/user/subscription/:subscription_id/group/begin-join', AuthenticationController.requireLogin(), SubscriptionGroupController.beginJoinGroup webRouter.post '/user/subscription/:subscription_id/group/begin-join', AuthenticationController.requireLogin(), SubscriptionGroupController.beginJoinGroup
app.get '/user/subscription/:subscription_id/group/complete-join', AuthenticationController.requireLogin(), SubscriptionGroupController.completeJoin webRouter.get '/user/subscription/:subscription_id/group/complete-join', AuthenticationController.requireLogin(), SubscriptionGroupController.completeJoin
app.get '/user/subscription/:subscription_id/group/successful-join', AuthenticationController.requireLogin(), SubscriptionGroupController.renderSuccessfulJoinPage webRouter.get '/user/subscription/:subscription_id/group/successful-join', AuthenticationController.requireLogin(), SubscriptionGroupController.renderSuccessfulJoinPage
#recurly callback #recurly callback
app.post '/user/subscription/callback', SubscriptionController.recurlyNotificationParser, SubscriptionController.recurlyCallback apiRouter.post '/user/subscription/callback', SubscriptionController.recurlyNotificationParser, SubscriptionController.recurlyCallback
app.ignoreCsrf("post", '/user/subscription/callback')
#user changes their account state #user changes their account state
app.post '/user/subscription/create', AuthenticationController.requireLogin(), SubscriptionController.createSubscription webRouter.post '/user/subscription/create', AuthenticationController.requireLogin(), SubscriptionController.createSubscription
app.post '/user/subscription/update', AuthenticationController.requireLogin(), SubscriptionController.updateSubscription webRouter.post '/user/subscription/update', AuthenticationController.requireLogin(), SubscriptionController.updateSubscription
app.post '/user/subscription/cancel', AuthenticationController.requireLogin(), SubscriptionController.cancelSubscription webRouter.post '/user/subscription/cancel', AuthenticationController.requireLogin(), SubscriptionController.cancelSubscription
app.post '/user/subscription/reactivate', AuthenticationController.requireLogin(), SubscriptionController.reactivateSubscription webRouter.post '/user/subscription/reactivate', AuthenticationController.requireLogin(), SubscriptionController.reactivateSubscription
app.get "/user/subscription/upgrade-annual", AuthenticationController.requireLogin(), SubscriptionController.renderUpgradeToAnnualPlanPage webRouter.get "/user/subscription/upgrade-annual", AuthenticationController.requireLogin(), SubscriptionController.renderUpgradeToAnnualPlanPage
app.post "/user/subscription/upgrade-annual", AuthenticationController.requireLogin(), SubscriptionController.processUpgradeToAnnualPlan webRouter.post "/user/subscription/upgrade-annual", AuthenticationController.requireLogin(), SubscriptionController.processUpgradeToAnnualPlan

View file

@ -3,11 +3,11 @@ AuthenticationController = require('../Authentication/AuthenticationController')
ProjectUploadController = require "./ProjectUploadController" ProjectUploadController = require "./ProjectUploadController"
module.exports = module.exports =
apply: (app) -> apply: (webRouter, apiRouter) ->
app.post '/project/new/upload', webRouter.post '/project/new/upload',
AuthenticationController.requireLogin(), AuthenticationController.requireLogin(),
ProjectUploadController.uploadProject ProjectUploadController.uploadProject
app.post '/Project/:Project_id/upload', webRouter.post '/Project/:Project_id/upload',
SecurityManager.requestCanModifyProject, SecurityManager.requestCanModifyProject,
ProjectUploadController.uploadFile ProjectUploadController.uploadFile

View file

@ -39,7 +39,7 @@ for path in [
logger.log filePath:filePath, "file does not exist for fingerprints" logger.log filePath:filePath, "file does not exist for fingerprints"
module.exports = (app)-> module.exports = (app, webRouter, apiRouter)->
app.use (req, res, next)-> app.use (req, res, next)->
res.locals.session = req.session res.locals.session = req.session
next() next()
@ -94,8 +94,8 @@ module.exports = (app)->
return "" return ""
next() next()
app.use (req, res, next) -> webRouter.use (req, res, next) ->
res.locals.csrfToken = req.csrfToken() res.locals.csrfToken = req?.csrfToken()
next() next()
app.use (req, res, next) -> app.use (req, res, next) ->

View file

@ -13,9 +13,9 @@ module.exports = Modules =
loadedModule.name = moduleName loadedModule.name = moduleName
@modules.push loadedModule @modules.push loadedModule
applyRouter: (app) -> applyRouter: (webRouter, apiRouter) ->
for module in @modules for module in @modules
module.router?.apply(app) module.router?.apply(webRouter, apiRouter)
viewIncludes: {} viewIncludes: {}
loadViewIncludes: (app) -> loadViewIncludes: (app) ->

View file

@ -44,19 +44,31 @@ else
app = express() app = express()
ignoreCsrfRoutes = [] webRouter = express.Router()
app.ignoreCsrf = (method, route) -> apiRouter = express.Router()
ignoreCsrfRoutes.push new express.Route(method, route)
if Settings.behindProxy if Settings.behindProxy
app.enable('trust proxy') app.enable('trust proxy')
app.use express.static(__dirname + '/../../../public', {maxAge: staticCacheAge })
webRouter.use express.static(__dirname + '/../../../public', {maxAge: staticCacheAge })
app.set 'views', __dirname + '/../../views' app.set 'views', __dirname + '/../../views'
app.set 'view engine', 'jade' app.set 'view engine', 'jade'
Modules.loadViewIncludes app Modules.loadViewIncludes app
app.use cookieParser(Settings.security.sessionSecret)
app.use session
app.use bodyParser.urlencoded({ extended: true })
app.use bodyParser.json()
app.use multer(dest: Settings.path.uploadFolder)
app.use methodOverride()
app.use metrics.http.monitor(logger)
app.use RedirectManager
app.use OldAssetProxy
webRouter.use cookieParser(Settings.security.sessionSecret)
webRouter.use session
resave: false resave: false
secret:Settings.security.sessionSecret secret:Settings.security.sessionSecret
proxy: Settings.behindProxy proxy: Settings.behindProxy
@ -66,36 +78,23 @@ app.use session
secure: Settings.secureCookie secure: Settings.secureCookie
store: sessionStore store: sessionStore
key: Settings.cookieName key: Settings.cookieName
webRouter.use csrfProtection
app.use bodyParser.urlencoded({ extended: true }) webRouter.use translations.expressMiddlewear
app.use bodyParser.json() webRouter.use translations.setLangBasedOnDomainMiddlewear
app.use multer(dest: Settings.path.uploadFolder)
app.use translations.expressMiddlewear
app.use translations.setLangBasedOnDomainMiddlewear
# Measure expiry from last request, not last login # Measure expiry from last request, not last login
app.use (req, res, next) -> webRouter.use (req, res, next) ->
req.session.touch() req.session.touch()
next() next()
app.use (req, res, next) -> webRouter.use ReferalConnect.use
for route in ignoreCsrfRoutes expressLocals(app, webRouter, apiRouter)
if route.method == req.method?.toLowerCase() and route.match(req.path)
return next()
csrfProtection(req, res, next)
app.use ReferalConnect.use
app.use methodOverride()
expressLocals(app)
if app.get('env') == 'production' if app.get('env') == 'production'
logger.info "Production Enviroment" logger.info "Production Enviroment"
app.enable('view cache') app.enable('view cache')
app.use metrics.http.monitor(logger)
app.use RedirectManager
app.use OldAssetProxy
app.use (req, res, next)-> app.use (req, res, next)->
metrics.inc "http-request" metrics.inc "http-request"
@ -109,12 +108,11 @@ app.use (req, res, next) ->
else else
next() next()
app.get "/status", (req, res)-> apiRouter.get "/status", (req, res)->
res.send("web sharelatex is alive") res.send("web sharelatex is alive")
req.session.destroy()
profiler = require "v8-profiler" profiler = require "v8-profiler"
app.get "/profile", (req, res) -> apiRouter.get "/profile", (req, res) ->
time = parseInt(req.query.time || "1000") time = parseInt(req.query.time || "1000")
profiler.startProfiling("test") profiler.startProfiling("test")
setTimeout () -> setTimeout () ->
@ -125,7 +123,12 @@ app.get "/profile", (req, res) ->
logger.info ("creating HTTP server").yellow logger.info ("creating HTTP server").yellow
server = require('http').createServer(app) server = require('http').createServer(app)
router = new Router(app) # process api routes first, if nothing matched fall though and use
# web middlewear + routes
app.use(apiRouter)
app.use(webRouter)
router = new Router(webRouter, apiRouter)
module.exports = module.exports =
app: app app: app

View file

@ -40,65 +40,67 @@ logger = require("logger-sharelatex")
_ = require("underscore") _ = require("underscore")
module.exports = class Router module.exports = class Router
constructor: (app)-> constructor: (webRouter, apiRouter)->
if !Settings.allowPublicAccess if !Settings.allowPublicAccess
app.all '*', AuthenticationController.requireGlobalLogin webRouter.all '*', AuthenticationController.requireGlobalLogin
app.get '/login', UserPagesController.loginPage webRouter.get '/login', UserPagesController.loginPage
AuthenticationController.addEndpointToLoginWhitelist '/login' AuthenticationController.addEndpointToLoginWhitelist '/login'
app.post '/login', AuthenticationController.login webRouter.post '/login', AuthenticationController.login
app.get '/logout', UserController.logout webRouter.get '/logout', UserController.logout
app.get '/restricted', SecurityManager.restricted webRouter.get '/restricted', SecurityManager.restricted
# Left as a placeholder for implementing a public register page # Left as a placeholder for implementing a public register page
app.get '/register', UserPagesController.registerPage webRouter.get '/register', UserPagesController.registerPage
AuthenticationController.addEndpointToLoginWhitelist '/register' AuthenticationController.addEndpointToLoginWhitelist '/register'
EditorRouter.apply(app)
CollaboratorsRouter.apply(app)
SubscriptionRouter.apply(app)
UploadsRouter.apply(app)
PasswordResetRouter.apply(app)
StaticPagesRouter.apply(app)
RealTimeProxyRouter.apply(app)
Modules.applyRouter(app) EditorRouter.apply(webRouter, apiRouter)
CollaboratorsRouter.apply(webRouter, apiRouter)
SubscriptionRouter.apply(webRouter, apiRouter)
UploadsRouter.apply(webRouter, apiRouter)
PasswordResetRouter.apply(webRouter, apiRouter)
StaticPagesRouter.apply(webRouter, apiRouter)
RealTimeProxyRouter.apply(webRouter, apiRouter)
AnalyticsRouter.apply(webRouter, apiRouter)
Modules.applyRouter(webRouter, apiRouter)
app.get '/blog', BlogController.getIndexPage
app.get '/blog/*', BlogController.getPage
if Settings.enableSubscriptions if Settings.enableSubscriptions
app.get '/user/bonus', AuthenticationController.requireLogin(), ReferalMiddleware.getUserReferalId, ReferalController.bonus webRouter.get '/user/bonus', AuthenticationController.requireLogin(), ReferalMiddleware.getUserReferalId, ReferalController.bonus
app.get '/user/settings', AuthenticationController.requireLogin(), UserPagesController.settingsPage webRouter.get '/blog', BlogController.getIndexPage
app.post '/user/settings', AuthenticationController.requireLogin(), UserController.updateUserSettings webRouter.get '/blog/*', BlogController.getPage
app.post '/user/password/update', AuthenticationController.requireLogin(), UserController.changePassword
app.delete '/user/newsletter/unsubscribe', AuthenticationController.requireLogin(), UserController.unsubscribe webRouter.get '/user/settings', AuthenticationController.requireLogin(), UserPagesController.settingsPage
app.delete '/user', AuthenticationController.requireLogin(), UserController.deleteUser webRouter.post '/user/settings', AuthenticationController.requireLogin(), UserController.updateUserSettings
webRouter.post '/user/password/update', AuthenticationController.requireLogin(), UserController.changePassword
app.get '/user/auth_token', AuthenticationController.requireLogin(), AuthenticationController.getAuthToken webRouter.delete '/user/newsletter/unsubscribe', AuthenticationController.requireLogin(), UserController.unsubscribe
app.get '/user/personal_info', AuthenticationController.requireLogin(allow_auth_token: true), UserInfoController.getLoggedInUsersPersonalInfo webRouter.delete '/user', AuthenticationController.requireLogin(), UserController.deleteUser
app.get '/user/:user_id/personal_info', AuthenticationController.httpAuth, UserInfoController.getPersonalInfo
app.get '/project', AuthenticationController.requireLogin(), ProjectController.projectListPage webRouter.get '/user/auth_token', AuthenticationController.requireLogin(), AuthenticationController.getAuthToken
app.post '/project/new', AuthenticationController.requireLogin(), ProjectController.newProject webRouter.get '/user/personal_info', AuthenticationController.requireLogin(allow_auth_token: true), UserInfoController.getLoggedInUsersPersonalInfo
apiRouter.get '/user/:user_id/personal_info', AuthenticationController.httpAuth, UserInfoController.getPersonalInfo
app.get '/Project/:Project_id', RateLimiterMiddlewear.rateLimit({ webRouter.get '/project', AuthenticationController.requireLogin(), ProjectController.projectListPage
webRouter.post '/project/new', AuthenticationController.requireLogin(), ProjectController.newProject
webRouter.get '/Project/:Project_id', RateLimiterMiddlewear.rateLimit({
endpointName: "open-project" endpointName: "open-project"
params: ["Project_id"] params: ["Project_id"]
maxRequests: 10 maxRequests: 10
timeInterval: 60 timeInterval: 60
}), SecurityManager.requestCanAccessProject, ProjectController.loadEditor }), SecurityManager.requestCanAccessProject, ProjectController.loadEditor
app.get '/Project/:Project_id/file/:File_id', SecurityManager.requestCanAccessProject, FileStoreController.getFile webRouter.get '/Project/:Project_id/file/:File_id', SecurityManager.requestCanAccessProject, FileStoreController.getFile
webRouter.post '/project/:Project_id/settings', SecurityManager.requestCanModifyProject, ProjectController.updateProjectSettings
app.post '/project/:Project_id/settings', SecurityManager.requestCanModifyProject, ProjectController.updateProjectSettings webRouter.post '/project/:Project_id/compile', SecurityManager.requestCanAccessProject, CompileController.compile
webRouter.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf
app.post '/project/:Project_id/compile', SecurityManager.requestCanAccessProject, CompileController.compile webRouter.get /^\/project\/([^\/]*)\/output\/(.*)$/,
app.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf
app.get /^\/project\/([^\/]*)\/output\/(.*)$/,
((req, res, next) -> ((req, res, next) ->
params = params =
"Project_id": req.params[0] "Project_id": req.params[0]
@ -106,78 +108,82 @@ module.exports = class Router
req.params = params req.params = params
next() next()
), SecurityManager.requestCanAccessProject, CompileController.getFileFromClsi ), SecurityManager.requestCanAccessProject, CompileController.getFileFromClsi
app.delete "/project/:Project_id/output", SecurityManager.requestCanAccessProject, CompileController.deleteAuxFiles webRouter.delete "/project/:Project_id/output", SecurityManager.requestCanAccessProject, CompileController.deleteAuxFiles
app.get "/project/:Project_id/sync/code", SecurityManager.requestCanAccessProject, CompileController.proxySync webRouter.get "/project/:Project_id/sync/code", SecurityManager.requestCanAccessProject, CompileController.proxySync
app.get "/project/:Project_id/sync/pdf", SecurityManager.requestCanAccessProject, CompileController.proxySync webRouter.get "/project/:Project_id/sync/pdf", SecurityManager.requestCanAccessProject, CompileController.proxySync
app.delete '/Project/:Project_id', SecurityManager.requestIsOwner, ProjectController.deleteProject webRouter.delete '/Project/:Project_id', SecurityManager.requestIsOwner, ProjectController.deleteProject
app.post '/Project/:Project_id/restore', SecurityManager.requestIsOwner, ProjectController.restoreProject webRouter.post '/Project/:Project_id/restore', SecurityManager.requestIsOwner, ProjectController.restoreProject
app.post '/Project/:Project_id/clone', SecurityManager.requestCanAccessProject, ProjectController.cloneProject webRouter.post '/Project/:Project_id/clone', SecurityManager.requestCanAccessProject, ProjectController.cloneProject
app.post '/project/:Project_id/rename', SecurityManager.requestIsOwner, ProjectController.renameProject webRouter.post '/project/:Project_id/rename', SecurityManager.requestIsOwner, ProjectController.renameProject
app.get "/project/:Project_id/updates", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi webRouter.get "/project/:Project_id/updates", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.get "/project/:Project_id/doc/:doc_id/diff", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi webRouter.get "/project/:Project_id/doc/:doc_id/diff", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi webRouter.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.get '/Project/:Project_id/download/zip', SecurityManager.requestCanAccessProject, ProjectDownloadsController.downloadProject webRouter.get '/Project/:Project_id/download/zip', SecurityManager.requestCanAccessProject, ProjectDownloadsController.downloadProject
app.get '/project/download/zip', SecurityManager.requestCanAccessMultipleProjects, ProjectDownloadsController.downloadMultipleProjects webRouter.get '/project/download/zip', SecurityManager.requestCanAccessMultipleProjects, ProjectDownloadsController.downloadMultipleProjects
app.get '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags webRouter.get '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags
app.post '/project/:project_id/tag', AuthenticationController.requireLogin(), TagsController.processTagsUpdate webRouter.post '/project/:project_id/tag', AuthenticationController.requireLogin(), TagsController.processTagsUpdate
app.get '/project/:project_id/details', AuthenticationController.httpAuth, ProjectApiController.getProjectDetails # Deprecated in favour of /internal/project/:project_id but still used by versioning
apiRouter.get '/project/:project_id/details', AuthenticationController.httpAuth, ProjectApiController.getProjectDetails
app.get '/internal/project/:Project_id/zip', AuthenticationController.httpAuth, ProjectDownloadsController.downloadProject # New 'stable' /internal API end points
app.get '/internal/project/:project_id/compile/pdf', AuthenticationController.httpAuth, CompileController.compileAndDownloadPdf apiRouter.get '/internal/project/:project_id', AuthenticationController.httpAuth, ProjectApiController.getProjectDetails
apiRouter.get '/internal/project/:Project_id/zip', AuthenticationController.httpAuth, ProjectDownloadsController.downloadProject
webRouter.get /^\/internal\/project\/([^\/]*)\/output\/(.*)$/,
((req, res, next) ->
params =
"Project_id": req.params[0]
"file": req.params[1]
req.params = params
next()
), AuthenticationController.httpAuth, CompileController.getFileFromClsi
app.get '/project/:Project_id/doc/:doc_id', AuthenticationController.httpAuth, DocumentController.getDocument apiRouter.get '/project/:Project_id/doc/:doc_id', AuthenticationController.httpAuth, DocumentController.getDocument
app.post '/project/:Project_id/doc/:doc_id', AuthenticationController.httpAuth, DocumentController.setDocument apiRouter.post '/project/:Project_id/doc/:doc_id', AuthenticationController.httpAuth, DocumentController.setDocument
app.ignoreCsrf('post', '/project/:Project_id/doc/:doc_id')
app.post '/user/:user_id/update/*', AuthenticationController.httpAuth, TpdsController.mergeUpdate apiRouter.post '/user/:user_id/update/*', AuthenticationController.httpAuth, TpdsController.mergeUpdate
app.delete '/user/:user_id/update/*', AuthenticationController.httpAuth, TpdsController.deleteUpdate apiRouter.delete '/user/:user_id/update/*', AuthenticationController.httpAuth, TpdsController.deleteUpdate
app.ignoreCsrf('post', '/user/:user_id/update/*')
app.ignoreCsrf('delete', '/user/:user_id/update/*')
app.post '/project/:project_id/contents/*', AuthenticationController.httpAuth, TpdsController.updateProjectContents apiRouter.post '/project/:project_id/contents/*', AuthenticationController.httpAuth, TpdsController.updateProjectContents
app.delete '/project/:project_id/contents/*', AuthenticationController.httpAuth, TpdsController.deleteProjectContents apiRouter.delete '/project/:project_id/contents/*', AuthenticationController.httpAuth, TpdsController.deleteProjectContents
app.ignoreCsrf('post', '/project/:project_id/contents/*')
app.ignoreCsrf('delete', '/project/:project_id/contents/*')
app.post "/spelling/check", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi webRouter.post "/spelling/check", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi
app.post "/spelling/learn", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi webRouter.post "/spelling/learn", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi
app.get "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.getMessages webRouter.get "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.getMessages
app.post "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.sendMessage webRouter.post "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.sendMessage
app.get /learn(\/.*)?/, WikiController.getPage webRouter.get /learn(\/.*)?/, WikiController.getPage
#Admin Stuff #Admin Stuff
app.get '/admin', SecurityManager.requestIsAdmin, AdminController.index webRouter.get '/admin', SecurityManager.requestIsAdmin, AdminController.index
app.get '/admin/register', SecurityManager.requestIsAdmin, AdminController.registerNewUser webRouter.get '/admin/register', SecurityManager.requestIsAdmin, AdminController.registerNewUser
app.post '/admin/register', SecurityManager.requestIsAdmin, UserController.register webRouter.post '/admin/register', SecurityManager.requestIsAdmin, UserController.register
app.post '/admin/closeEditor', SecurityManager.requestIsAdmin, AdminController.closeEditor webRouter.post '/admin/closeEditor', SecurityManager.requestIsAdmin, AdminController.closeEditor
app.post '/admin/dissconectAllUsers', SecurityManager.requestIsAdmin, AdminController.dissconectAllUsers webRouter.post '/admin/dissconectAllUsers', SecurityManager.requestIsAdmin, AdminController.dissconectAllUsers
app.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription webRouter.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription
app.post '/admin/flushProjectToTpds', SecurityManager.requestIsAdmin, AdminController.flushProjectToTpds webRouter.post '/admin/flushProjectToTpds', SecurityManager.requestIsAdmin, AdminController.flushProjectToTpds
app.post '/admin/pollDropboxForUser', SecurityManager.requestIsAdmin, AdminController.pollDropboxForUser webRouter.post '/admin/pollDropboxForUser', SecurityManager.requestIsAdmin, AdminController.pollDropboxForUser
app.post '/admin/messages', SecurityManager.requestIsAdmin, AdminController.createMessage webRouter.post '/admin/messages', SecurityManager.requestIsAdmin, AdminController.createMessage
app.post '/admin/messages/clear', SecurityManager.requestIsAdmin, AdminController.clearMessages webRouter.post '/admin/messages/clear', SecurityManager.requestIsAdmin, AdminController.clearMessages
app.get '/perfTest', (req,res)-> apiRouter.get '/perfTest', (req,res)->
res.send("hello") res.send("hello")
req.session.destroy()
app.get '/status', (req,res)-> apiRouter.get '/status', (req,res)->
res.send("websharelatex is up") res.send("websharelatex is up")
req.session.destroy()
app.get '/health_check', HealthCheckController.check
app.get '/health_check/redis', HealthCheckController.checkRedis
app.get "/status/compiler/:Project_id", SecurityManager.requestCanAccessProject, (req, res) -> webRouter.get '/health_check', HealthCheckController.check
webRouter.get '/health_check/redis', HealthCheckController.checkRedis
apiRouter.get "/status/compiler/:Project_id", SecurityManager.requestCanAccessProject, (req, res) ->
sendRes = _.once (statusCode, message)-> sendRes = _.once (statusCode, message)->
res.writeHead statusCode res.writeHead statusCode
res.end message res.end message
@ -186,27 +192,26 @@ module.exports = class Router
setTimeout (() -> setTimeout (() ->
sendRes 500, "Compiler timed out" sendRes 500, "Compiler timed out"
), 10000 ), 10000
req.session.destroy()
app.get "/ip", (req, res, next) -> apiRouter.get "/ip", (req, res, next) ->
res.send({ res.send({
ip: req.ip ip: req.ip
ips: req.ips ips: req.ips
headers: req.headers headers: req.headers
}) })
app.get '/oops-express', (req, res, next) -> next(new Error("Test error")) apiRouter.get '/oops-express', (req, res, next) -> next(new Error("Test error"))
app.get '/oops-internal', (req, res, next) -> throw new Error("Test error") apiRouter.get '/oops-internal', (req, res, next) -> throw new Error("Test error")
app.get '/oops-mongo', (req, res, next) -> apiRouter.get '/oops-mongo', (req, res, next) ->
require("./models/Project").Project.findOne {}, () -> require("./models/Project").Project.findOne {}, () ->
throw new Error("Test error") throw new Error("Test error")
app.get '/opps-small', (req, res, next)-> apiRouter.get '/opps-small', (req, res, next)->
logger.err "test error occured" logger.err "test error occured"
res.send() res.send()
app.post '/error/client', (req, res, next) -> webRouter.post '/error/client', (req, res, next) ->
logger.error err: req.body.error, meta: req.body.meta, "client side error" logger.error err: req.body.error, meta: req.body.meta, "client side error"
res.send(204) res.send(204)
app.get '*', ErrorController.notFound webRouter.get '*', ErrorController.notFound