router.coffee 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. AdminController = require('./Features/ServerAdmin/AdminController')
  2. ErrorController = require('./Features/Errors/ErrorController')
  3. ProjectController = require("./Features/Project/ProjectController")
  4. ProjectApiController = require("./Features/Project/ProjectApiController")
  5. SpellingController = require('./Features/Spelling/SpellingController')
  6. SecurityManager = require('./managers/SecurityManager')
  7. AuthorizationManager = require('./Features/Security/AuthorizationManager')
  8. EditorController = require("./Features/Editor/EditorController")
  9. EditorHttpController = require("./Features/Editor/EditorHttpController")
  10. EditorUpdatesController = require("./Features/Editor/EditorUpdatesController")
  11. Settings = require('settings-sharelatex')
  12. TpdsController = require('./Features/ThirdPartyDataStore/TpdsController')
  13. SubscriptionRouter = require './Features/Subscription/SubscriptionRouter'
  14. UploadsRouter = require './Features/Uploads/UploadsRouter'
  15. metrics = require('./infrastructure/Metrics')
  16. ReferalController = require('./Features/Referal/ReferalController')
  17. ReferalMiddleware = require('./Features/Referal/ReferalMiddleware')
  18. TemplatesRouter = require('./Features/Templates/TemplatesRouter')
  19. TemplatesController = require('./Features/Templates/TemplatesController')
  20. TemplatesMiddlewear = require('./Features/Templates/TemplatesMiddlewear')
  21. AuthenticationController = require('./Features/Authentication/AuthenticationController')
  22. TagsController = require("./Features/Tags/TagsController")
  23. CollaboratorsController = require('./Features/Collaborators/CollaboratorsController')
  24. UserInfoController = require('./Features/User/UserInfoController')
  25. UserController = require("./Features/User/UserController")
  26. UserPagesController = require('./Features/User/UserPagesController')
  27. DocumentController = require('./Features/Documents/DocumentController')
  28. CompileManager = require("./Features/Compile/CompileManager")
  29. CompileController = require("./Features/Compile/CompileController")
  30. HealthCheckController = require("./Features/HealthCheck/HealthCheckController")
  31. ProjectDownloadsController = require "./Features/Downloads/ProjectDownloadsController"
  32. FileStoreController = require("./Features/FileStore/FileStoreController")
  33. TrackChangesController = require("./Features/TrackChanges/TrackChangesController")
  34. PasswordResetRouter = require("./Features/PasswordReset/PasswordResetRouter")
  35. StaticPagesRouter = require("./Features/StaticPages/StaticPagesRouter")
  36. ChatController = require("./Features/Chat/ChatController")
  37. BlogController = require("./Features/Blog/BlogController")
  38. WikiController = require("./Features/Wiki/WikiController")
  39. ConnectedUsersController = require("./Features/ConnectedUsers/ConnectedUsersController")
  40. DropboxRouter = require "./Features/Dropbox/DropboxRouter"
  41. dropboxHandler = require "./Features/Dropbox/DropboxHandler"
  42. logger = require("logger-sharelatex")
  43. _ = require("underscore")
  44. httpAuth = require('express').basicAuth (user, pass)->
  45. isValid = Settings.httpAuthUsers[user] == pass
  46. if !isValid
  47. logger.err user:user, pass:pass, "invalid login details"
  48. return isValid
  49. module.exports = class Router
  50. constructor: (app, io, socketSessions)->
  51. app.use(app.router)
  52. app.get '/login', UserPagesController.loginPage
  53. app.post '/login', AuthenticationController.login
  54. app.get '/logout', UserController.logout
  55. app.get '/restricted', SecurityManager.restricted
  56. app.get '/register', UserPagesController.registerPage
  57. app.post '/register', UserController.register
  58. SubscriptionRouter.apply(app)
  59. UploadsRouter.apply(app)
  60. PasswordResetRouter.apply(app)
  61. StaticPagesRouter.apply(app)
  62. TemplatesRouter.apply(app)
  63. DropboxRouter.apply(app)
  64. app.get '/blog', BlogController.getIndexPage
  65. app.get '/blog/*', BlogController.getPage
  66. if Settings.enableSubscriptions
  67. app.get '/user/bonus', AuthenticationController.requireLogin(), ReferalMiddleware.getUserReferalId, ReferalController.bonus
  68. app.get '/user/settings', AuthenticationController.requireLogin(), UserPagesController.settingsPage
  69. app.post '/user/settings', AuthenticationController.requireLogin(), UserController.updateUserSettings
  70. app.post '/user/password/update', AuthenticationController.requireLogin(), UserController.changePassword
  71. app.del '/user/newsletter/unsubscribe', AuthenticationController.requireLogin(), UserController.unsubscribe
  72. app.del '/user', AuthenticationController.requireLogin(), UserController.deleteUser
  73. app.get '/user/auth_token', AuthenticationController.requireLogin(), AuthenticationController.getAuthToken
  74. app.get '/user/personal_info', AuthenticationController.requireLogin(allow_auth_token: true), UserInfoController.getLoggedInUsersPersonalInfo
  75. app.get '/user/:user_id/personal_info', httpAuth, UserInfoController.getPersonalInfo
  76. app.get '/project', AuthenticationController.requireLogin(), ProjectController.projectListPage
  77. app.post '/project/new', AuthenticationController.requireLogin(), ProjectController.newProject
  78. app.get '/project/new/template', TemplatesMiddlewear.saveTemplateDataInSession, AuthenticationController.requireLogin(), TemplatesController.createProjectFromZipTemplate
  79. app.get '/Project/:Project_id', SecurityManager.requestCanAccessProject, ProjectController.loadEditor
  80. app.get '/Project/:Project_id/file/:File_id', SecurityManager.requestCanAccessProject, FileStoreController.getFile
  81. app.post '/project/:Project_id/settings', SecurityManager.requestCanModifyProject, ProjectController.updateProjectSettings
  82. app.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc
  83. app.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder
  84. app.post '/project/:Project_id/:entity_type/:entity_id/rename', SecurityManager.requestCanModifyProject, EditorHttpController.renameEntity
  85. app.post '/project/:Project_id/:entity_type/:entity_id/move', SecurityManager.requestCanModifyProject, EditorHttpController.moveEntity
  86. app.delete '/project/:Project_id/:entity_type/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteEntity
  87. app.post '/project/:Project_id/compile', SecurityManager.requestCanAccessProject, CompileController.compile
  88. app.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf
  89. app.get /^\/project\/([^\/]*)\/output\/(.*)$/,
  90. ((req, res, next) ->
  91. params =
  92. "Project_id": req.params[0]
  93. "file": req.params[1]
  94. req.params = params
  95. next()
  96. ), SecurityManager.requestCanAccessProject, CompileController.getFileFromClsi
  97. app.del "/project/:Project_id/output", SecurityManager.requestCanAccessProject, CompileController.deleteAuxFiles
  98. app.get "/project/:Project_id/sync/code", SecurityManager.requestCanAccessProject, CompileController.proxySync
  99. app.get "/project/:Project_id/sync/pdf", SecurityManager.requestCanAccessProject, CompileController.proxySync
  100. app.del '/Project/:Project_id', SecurityManager.requestIsOwner, ProjectController.deleteProject
  101. app.post '/Project/:Project_id/restore', SecurityManager.requestIsOwner, ProjectController.restoreProject
  102. app.post '/Project/:Project_id/clone', SecurityManager.requestCanAccessProject, ProjectController.cloneProject
  103. app.post '/project/:Project_id/rename', SecurityManager.requestIsOwner, ProjectController.renameProject
  104. app.get "/project/:Project_id/updates", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
  105. app.get "/project/:Project_id/doc/:doc_id/diff", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
  106. app.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
  107. app.post "/project/:Project_id/doc/:doc_id/restore", SecurityManager.requestCanAccessProject, EditorHttpController.restoreDoc
  108. app.post '/project/:project_id/leave', AuthenticationController.requireLogin(), CollaboratorsController.removeSelfFromProject
  109. app.get '/project/:Project_id/collaborators', SecurityManager.requestCanAccessProject(allow_auth_token: true), CollaboratorsController.getCollaborators
  110. app.get '/project/:Project_id/connected_users', SecurityManager.requestCanAccessProject, ConnectedUsersController.getConnectedUsers
  111. app.get '/Project/:Project_id/download/zip', SecurityManager.requestCanAccessProject, ProjectDownloadsController.downloadProject
  112. app.get '/project/download/zip', SecurityManager.requestCanAccessMultipleProjects, ProjectDownloadsController.downloadMultipleProjects
  113. app.get '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags
  114. app.post '/project/:project_id/tag', AuthenticationController.requireLogin(), TagsController.processTagsUpdate
  115. app.get '/project/:project_id/details', httpAuth, ProjectApiController.getProjectDetails
  116. app.get '/internal/project/:Project_id/zip', httpAuth, ProjectDownloadsController.downloadProject
  117. app.get '/internal/project/:project_id/compile/pdf', httpAuth, CompileController.compileAndDownloadPdf
  118. app.get '/project/:Project_id/doc/:doc_id', httpAuth, DocumentController.getDocument
  119. app.post '/project/:Project_id/doc/:doc_id', httpAuth, DocumentController.setDocument
  120. app.ignoreCsrf('post', '/project/:Project_id/doc/:doc_id')
  121. app.post '/user/:user_id/update/*', httpAuth, TpdsController.mergeUpdate
  122. app.del '/user/:user_id/update/*', httpAuth, TpdsController.deleteUpdate
  123. app.ignoreCsrf('post', '/user/:user_id/update/*')
  124. app.ignoreCsrf('delete', '/user/:user_id/update/*')
  125. app.post "/spelling/check", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi
  126. app.post "/spelling/learn", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi
  127. app.get "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.getMessages
  128. app.post "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.sendMessage
  129. app.get /learn(\/.*)?/, WikiController.getPage
  130. #Admin Stuff
  131. app.get '/admin', SecurityManager.requestIsAdmin, AdminController.index
  132. app.post '/admin/closeEditor', SecurityManager.requestIsAdmin, AdminController.closeEditor
  133. app.post '/admin/dissconectAllUsers', SecurityManager.requestIsAdmin, AdminController.dissconectAllUsers
  134. app.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription
  135. app.post '/admin/flushProjectToTpds', SecurityManager.requestIsAdmin, AdminController.flushProjectToTpds
  136. app.post '/admin/pollDropboxForUser', SecurityManager.requestIsAdmin, AdminController.pollDropboxForUser
  137. app.post '/admin/messages', SecurityManager.requestIsAdmin, AdminController.createMessage
  138. app.post '/admin/messages/clear', SecurityManager.requestIsAdmin, AdminController.clearMessages
  139. app.get '/perfTest', (req,res)->
  140. res.send("hello")
  141. req.session.destroy()
  142. app.get '/status', (req,res)->
  143. res.send("websharelatex is up")
  144. req.session.destroy()
  145. app.get '/health_check', HealthCheckController.check
  146. app.get "/status/compiler/:Project_id", SecurityManager.requestCanAccessProject, (req, res) ->
  147. sendRes = _.once (statusCode, message)->
  148. res.writeHead statusCode
  149. res.end message
  150. CompileManager.compile req.params.Project_id, "test-compile", {}, () ->
  151. sendRes 200, "Compiler returned in less than 10 seconds"
  152. setTimeout (() ->
  153. sendRes 500, "Compiler timed out"
  154. ), 10000
  155. req.session.destroy()
  156. app.get '/test', (req, res) ->
  157. res.render "tests",
  158. privilegeLevel: "owner"
  159. project:
  160. name: "test"
  161. date: Date.now()
  162. layout: false
  163. userCanSeeDropbox: true
  164. languages: []
  165. app.get "/ip", (req, res, next) ->
  166. res.send({
  167. ip: req.ip
  168. ips: req.ips
  169. headers: req.headers
  170. })
  171. app.get '/oops-express', (req, res, next) -> next(new Error("Test error"))
  172. app.get '/oops-internal', (req, res, next) -> throw new Error("Test error")
  173. app.get '/oops-mongo', (req, res, next) ->
  174. require("./models/Project").Project.findOne {}, () ->
  175. throw new Error("Test error")
  176. app.post '/error/client', (req, res, next) ->
  177. logger.error err: req.body.error, meta: req.body.meta, "client side error"
  178. res.send(204)
  179. app.get '*', ErrorController.notFound
  180. socketSessions.on 'connection', (err, client, session)->
  181. metrics.inc('socket-io.connection')
  182. # This is not ideal - we should come up with a better way of handling
  183. # anonymous users, but various logging lines rely on user._id
  184. if !session or !session.user?
  185. user = {_id: "anonymous-user"}
  186. else
  187. user = session.user
  188. client.on 'joinProject', (data, callback) ->
  189. EditorController.joinProject(client, user, data.project_id, callback)
  190. client.on 'disconnect', () ->
  191. metrics.inc ('socket-io.disconnect')
  192. EditorController.leaveProject client, user
  193. client.on 'reportError', (error, callback) ->
  194. EditorController.reportError client, error, callback
  195. client.on 'sendUpdate', (doc_id, windowName, change)->
  196. AuthorizationManager.ensureClientCanEditProject client, (error, project_id) =>
  197. EditorUpdatesController.applyAceUpdate(client, project_id, doc_id, windowName, change)
  198. client.on 'applyOtUpdate', (doc_id, update) ->
  199. AuthorizationManager.ensureClientCanEditProject client, (error, project_id) =>
  200. EditorUpdatesController.applyOtUpdate(client, project_id, doc_id, update)
  201. client.on 'clientTracking.updatePosition', (cursorData) ->
  202. AuthorizationManager.ensureClientCanViewProject client, (error, project_id) =>
  203. EditorController.updateClientPosition(client, cursorData)
  204. client.on 'addUserToProject', (email, newPrivalageLevel, callback)->
  205. AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
  206. EditorController.addUserToProject project_id, email, newPrivalageLevel, callback
  207. client.on 'removeUserFromProject', (user_id, callback)->
  208. AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
  209. EditorController.removeUserFromProject(project_id, user_id, callback)
  210. client.on 'leaveDoc', (doc_id, callback)->
  211. AuthorizationManager.ensureClientCanViewProject client, (error, project_id) =>
  212. EditorController.leaveDoc(client, project_id, doc_id, callback)
  213. client.on 'joinDoc', (args...)->
  214. AuthorizationManager.ensureClientCanViewProject client, (error, project_id) =>
  215. EditorController.joinDoc(client, project_id, args...)
  216. # Deprecated and can be removed after deploying.
  217. client.on 'pdfProject', (opts, callback)->
  218. AuthorizationManager.ensureClientCanViewProject client, (error, project_id) =>
  219. CompileManager.compile project_id, user._id, opts, (error, status, outputFiles) ->
  220. return callback error, status == "success", outputFiles
  221. client.on 'getRootDocumentsList', (callback)->
  222. AuthorizationManager.ensureClientCanEditProject client, (error, project_id) =>
  223. EditorController.getListOfDocPaths project_id, callback
  224. client.on 'forceResyncOfDropbox', (callback)->
  225. AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
  226. EditorController.forceResyncOfDropbox project_id, callback
  227. client.on 'getUserDropboxLinkStatus', (owner_id, callback)->
  228. AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
  229. dropboxHandler.getUserRegistrationStatus owner_id, callback
  230. client.on 'publishProjectAsTemplate', (user_id, callback)->
  231. AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
  232. TemplatesController.publishProject user_id, project_id, callback
  233. client.on 'unPublishProjectAsTemplate', (user_id, callback)->
  234. AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
  235. TemplatesController.unPublishProject user_id, project_id, callback
  236. client.on 'updateProjectDescription', (description, callback)->
  237. AuthorizationManager.ensureClientCanEditProject client, (error, project_id) =>
  238. EditorController.updateProjectDescription project_id, description, callback
  239. client.on "getPublishedDetails", (user_id, callback)->
  240. AuthorizationManager.ensureClientCanViewProject client, (error, project_id) =>
  241. TemplatesController.getTemplateDetails user_id, project_id, callback