ProjectController.coffee 8.3 KB

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