ProjectController.coffee 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. User = require('../models/User').User
  2. Project = require('../models/Project').Project
  3. sanitize = require('validator').sanitize
  4. path = require "path"
  5. logger = require('logger-sharelatex')
  6. _ = require('underscore')
  7. fs = require('fs')
  8. ProjectHandler = require '../handlers/ProjectHandler'
  9. SecurityManager = require '../managers/SecurityManager'
  10. GuidManager = require '../managers/GuidManager'
  11. Settings = require('settings-sharelatex')
  12. projectCreationHandler = require '../Features/Project/ProjectCreationHandler'
  13. projectLocator = require '../Features/Project/ProjectLocator'
  14. projectDuplicator = require('../Features/Project/ProjectDuplicator')
  15. ProjectZipStreamManager = require '../Features/Downloads/ProjectZipStreamManager'
  16. metrics = require('../infrastructure/Metrics')
  17. TagsHandler = require('../Features/Tags/TagsHandler')
  18. SubscriptionLocator = require("../Features/Subscription/SubscriptionLocator")
  19. SubscriptionFormatters = require("../Features/Subscription/SubscriptionFormatters")
  20. FileStoreHandler = require("../Features/FileStore/FileStoreHandler")
  21. module.exports = class ProjectController
  22. constructor: (@collaberationManager)->
  23. ProjectHandler = new ProjectHandler()
  24. list: (req, res, next)->
  25. timer = new metrics.Timer("project-list")
  26. user_id = req.session.user._id
  27. startTime = new Date()
  28. User.findById user_id, (error, user) ->
  29. logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - User.findById"
  30. startTime = new Date()
  31. # TODO: Remove this one month after the ability to start free trials was removed
  32. SubscriptionLocator.getUsersSubscription user._id, (err, subscription)->
  33. logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - Subscription.getUsersSubscription"
  34. startTime = new Date()
  35. return next(error) if error?
  36. # TODO: Remove this one month after the ability to start free trials was removed
  37. if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt?
  38. freeTrial =
  39. expired: !!subscription.freeTrial.downgraded
  40. expiresAt: SubscriptionFormatters.formatDate(subscription.freeTrial.expiresAt)
  41. TagsHandler.getAllTags user_id, (err, tags, tagsGroupedByProject)->
  42. logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - TagsHandler.getAllTags"
  43. startTime = new Date()
  44. Project.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel', (projects, collabertions, readOnlyProjects)->
  45. logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - Project.findAllUsersProjects"
  46. startTime = new Date()
  47. for project in projects
  48. project.accessLevel = "owner"
  49. for project in collabertions
  50. project.accessLevel = "readWrite"
  51. for project in readOnlyProjects
  52. project.accessLevel = "readOnly"
  53. projects = projects.concat(collabertions).concat(readOnlyProjects)
  54. projects = projects.map (project)->
  55. project.tags = tagsGroupedByProject[project._id] || []
  56. return project
  57. tags = _.sortBy tags, (tag)->
  58. -tag.project_ids.length
  59. logger.log projects:projects, collabertions:collabertions, readOnlyProjects:readOnlyProjects, user_id:user_id, "rendering project list"
  60. sortedProjects = _.sortBy projects, (project)->
  61. return - project.lastUpdated
  62. res.render 'project/list',
  63. title:'Your Projects'
  64. priority_title: true
  65. projects: sortedProjects
  66. freeTrial: freeTrial
  67. tags:tags
  68. projectTabActive: true
  69. logger.log user_id: user_id, duration: (new Date() - startTime), "project list timer - Finished"
  70. timer.done()
  71. apiNewProject: (req, res)->
  72. user = req.session.user
  73. projectName = sanitize(req.body.projectName).xss()
  74. template = sanitize(req.body.template).xss()
  75. logger.log user: user, type: template, name: projectName, "creating project"
  76. if template == 'example'
  77. projectCreationHandler.createExampleProject user._id, projectName, (err, project)->
  78. if err?
  79. logger.error err: err, project: project, user: user, name: projectName, type: "example", "error creating project"
  80. res.send 500
  81. else
  82. logger.log project: project, user: user, name: projectName, type: "example", "created project"
  83. res.send {project_id:project._id}
  84. else
  85. projectCreationHandler.createBasicProject user._id, projectName, (err, project)->
  86. if err?
  87. logger.error err: err, project: project, user: user, name: projectName, type: "basic", "error creating project"
  88. res.send 500
  89. else
  90. logger.log project: project, user: user, name: projectName, type: "basic", "created project"
  91. res.send {project_id:project._id}
  92. loadEditor: (req, res)->
  93. timer = new metrics.Timer("load-editor")
  94. if !Settings.editorIsOpen
  95. res.render("general/closed", {title:"updating site"})
  96. else
  97. if req.session.user?
  98. user_id = req.session.user._id
  99. else
  100. user_id = 'openUser'
  101. project_id = req.params.Project_id
  102. Project.findPopulatedById project_id, (err, project)->
  103. User.findById user_id, (err, user)->
  104. if user_id == 'openUser'
  105. anonymous = true
  106. user =
  107. id : user_id
  108. ace:
  109. mode:'none'
  110. theme:'textmate'
  111. fontSize: '12'
  112. autoComplete: true
  113. spellCheckLanguage: ""
  114. pdfViewer: ""
  115. subscription:
  116. freeTrial:
  117. allowed: true
  118. featureSwitches:
  119. dropbox: false
  120. longPolling: false
  121. else
  122. anonymous = false
  123. SubscriptionLocator.getUsersSubscription user._id, (err, subscription)->
  124. SecurityManager.userCanAccessProject user, project, (canAccess, privlageLevel)->
  125. allowedFreeTrial = true
  126. if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt?
  127. allowedFreeTrial = !!subscription.freeTrial.allowed
  128. if canAccess
  129. timer.done()
  130. res.render 'project/editor',
  131. title: project.name
  132. priority_title: true
  133. bodyClasses: ["editor"]
  134. project : project
  135. owner : project.owner_ref
  136. userObject : JSON.stringify({
  137. id : user.id
  138. email : user.email
  139. first_name : user.first_name
  140. last_name : user.last_name
  141. referal_id : user.referal_id
  142. subscription :
  143. freeTrial: {allowed: allowedFreeTrial}
  144. })
  145. userSettingsObject: JSON.stringify({
  146. mode : user.ace.mode
  147. theme : user.ace.theme
  148. project_id : project._id
  149. fontSize : user.ace.fontSize
  150. autoComplete: user.ace.autoComplete
  151. spellCheckLanguage: user.ace.spellCheckLanguage
  152. pdfViewer : user.ace.pdfViewer
  153. docPositions: {}
  154. longPolling: user.featureSwitches.longPolling
  155. })
  156. sharelatexObject : JSON.stringify({
  157. siteUrl: Settings.siteUrl,
  158. jsPath: res.locals.jsPath
  159. })
  160. privlageLevel: privlageLevel
  161. userCanSeeDropbox: user.featureSwitches.dropbox and project.owner_ref._id+"" == user._id+""
  162. loadPdfjs: (user.ace.pdfViewer == "pdfjs")
  163. chatUrl: Settings.apis.chat.url
  164. anonymous: anonymous
  165. languages: Settings.languages,
  166. startBufferingRequest: (req, res, next) ->
  167. req.bufferedChunks = []
  168. req.endEmitted = false
  169. bufferChunk = (chunk) -> req.bufferedChunks.push(chunk)
  170. req.on "data", bufferChunk
  171. endCallback = () -> req.endEmitted = true
  172. req.on "end", endCallback
  173. req.emitBufferedData = () ->
  174. logger.log chunks: @bufferedChunks.length, emittedEnd: @endEmitted, "emitting buffer chunks"
  175. @removeListener "data", bufferChunk
  176. while @bufferedChunks.length > 0
  177. @emit "data", @bufferedChunks.shift()
  178. @removeListener "end", endCallback
  179. @emit "end" if @endEmitted
  180. next()
  181. downloadImageFile : (req, res)->
  182. project_id = req.params.Project_id
  183. file_id = req.params.File_id
  184. queryString = req.query
  185. logger.log project_id: project_id, file_id: file_id, queryString:queryString, "file download"
  186. res.setHeader("Content-Disposition", "attachment")
  187. FileStoreHandler.getFileStream project_id, file_id, queryString, (err, stream)->
  188. stream.pipe res
  189. cloneProject: (req, res)->
  190. metrics.inc "cloned-project"
  191. project_id = req.params.Project_id
  192. projectName = req.body.projectName
  193. logger.log project_id:project_id, projectName:projectName, "cloning project"
  194. if !req.session.user?
  195. return res.send redir:"/register"
  196. projectDuplicator.duplicate req.session.user, project_id, projectName, (err, project)->
  197. if err?
  198. logger.error err:err, project_id: project_id, user_id: req.session.user._id, "error cloning project"
  199. return next(err)
  200. res.send(project_id:project._id)
  201. deleteProject: (req, res)->
  202. project_id = req.params.Project_id
  203. logger.log project_id:project_id, "deleting project"
  204. ProjectHandler.deleteProject project_id, (err)->
  205. if err?
  206. res.send 500
  207. else
  208. res.send 200