EditorController.coffee 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. logger = require('logger-sharelatex')
  2. Metrics = require('metrics-sharelatex')
  3. sanitize = require('sanitizer')
  4. ProjectEntityHandler = require('../Project/ProjectEntityHandler')
  5. ProjectOptionsHandler = require('../Project/ProjectOptionsHandler')
  6. ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
  7. ProjectDeleter = require("../Project/ProjectDeleter")
  8. DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
  9. EditorRealTimeController = require("./EditorRealTimeController")
  10. async = require('async')
  11. LockManager = require("../../infrastructure/LockManager")
  12. PublicAccessLevels = require("../Authorization/PublicAccessLevels")
  13. _ = require('underscore')
  14. module.exports = EditorController =
  15. setDoc: (project_id, doc_id, user_id, docLines, source, callback = (err)->)->
  16. DocumentUpdaterHandler.setDocument project_id, doc_id, user_id, docLines, source, (err)=>
  17. logger.log project_id:project_id, doc_id:doc_id, "notifying users that the document has been updated"
  18. DocumentUpdaterHandler.flushDocToMongo project_id, doc_id, callback
  19. addDoc: (project_id, folder_id, docName, docLines, source, user_id, callback = (error, doc)->)->
  20. LockManager.runWithLock project_id,
  21. (cb) -> EditorController.addDocWithoutLock project_id, folder_id, docName, docLines, source, user_id, cb
  22. (err, doc) ->
  23. if err?
  24. logger.err err:err, project_id:project_id, source:source, "could add doc"
  25. return callback err
  26. callback null, doc
  27. addDocWithoutLock: (project_id, folder_id, docName, docLines, source, user_id, callback = (error, doc)->)->
  28. docName = docName.trim()
  29. logger.log {project_id, folder_id, docName, source}, "sending new doc to project"
  30. Metrics.inc "editor.add-doc"
  31. ProjectEntityHandler.addDoc project_id, folder_id, docName, docLines, user_id, (err, doc, folder_id)=>
  32. if err?
  33. logger.err err:err, project_id:project_id, docName:docName, "error adding doc without lock"
  34. return callback(err)
  35. EditorRealTimeController.emitToRoom(project_id, 'reciveNewDoc', folder_id, doc, source)
  36. callback(err, doc)
  37. addFile: (project_id, folder_id, fileName, path, source, user_id, callback = (error, file)->)->
  38. LockManager.runWithLock project_id,
  39. (cb) -> EditorController.addFileWithoutLock project_id, folder_id, fileName, path, source, user_id, cb
  40. (err, file) ->
  41. if err?
  42. logger.err err:err, project_id:project_id, source:source, "could add file"
  43. return callback(err)
  44. callback null, file
  45. addFileWithoutLock: (project_id, folder_id, fileName, path, source, user_id, callback = (error, file)->)->
  46. fileName = fileName.trim()
  47. logger.log {project_id, folder_id, fileName, path}, "sending new file to project"
  48. Metrics.inc "editor.add-file"
  49. ProjectEntityHandler.addFile project_id, folder_id, fileName, path, user_id, (err, fileRef, folder_id)=>
  50. if err?
  51. logger.err err:err, project_id:project_id, folder_id:folder_id, fileName:fileName, "error adding file without lock"
  52. return callback(err)
  53. EditorRealTimeController.emitToRoom(project_id, 'reciveNewFile', folder_id, fileRef, source)
  54. callback(err, fileRef)
  55. replaceFileWithoutLock: (project_id, file_id, fsPath, source, user_id, callback = (error) ->)->
  56. ProjectEntityHandler.replaceFile project_id, file_id, fsPath, user_id, callback
  57. addFolder : (project_id, folder_id, folderName, source, callback = (error, folder)->)->
  58. LockManager.runWithLock project_id,
  59. (cb) -> EditorController.addFolderWithoutLock project_id, folder_id, folderName, source, cb
  60. (err, folder)->
  61. if err?
  62. logger.err err:err, project_id:project_id, source:source, "could not add folder"
  63. return callback(err)
  64. callback null, folder
  65. addFolderWithoutLock: (project_id, folder_id, folderName, source, callback = (error, folder)->)->
  66. folderName = folderName.trim()
  67. logger.log {project_id, folder_id, folderName, source}, "sending new folder to project"
  68. Metrics.inc "editor.add-folder"
  69. ProjectEntityHandler.addFolder project_id, folder_id, folderName, (err, folder, folder_id)=>
  70. if err?
  71. logger.err err:err, project_id:project_id, folder_id:folder_id, folderName:folderName, "error adding folder without lock"
  72. return callback(err)
  73. @p.notifyProjectUsersOfNewFolder project_id, folder_id, folder, (error) ->
  74. callback error, folder
  75. mkdirp : (project_id, path, callback = (error, newFolders, lastFolder)->)->
  76. LockManager.runWithLock project_id,
  77. (cb) -> EditorController.mkdirpWithoutLock project_id, path, cb
  78. (err, newFolders, lastFolder) ->
  79. if err?
  80. logger.err err:err, project_id:project_id, "could not mkdirp"
  81. return callback(err)
  82. callback err, newFolders, lastFolder
  83. mkdirpWithoutLock: (project_id, path, callback = (error, newFolders, lastFolder)->)->
  84. logger.log project_id:project_id, path:path, "making directories if they don't exist"
  85. ProjectEntityHandler.mkdirp project_id, path, (err, newFolders, lastFolder)=>
  86. if err?
  87. logger.err err:err, project_id:project_id, path:path, "error mkdirp without lock"
  88. return callback(err)
  89. self = @
  90. jobs = _.map newFolders, (folder, index)->
  91. return (cb)->
  92. self.p.notifyProjectUsersOfNewFolder project_id, folder.parentFolder_id, folder, cb
  93. async.series jobs, (err)->
  94. callback err, newFolders, lastFolder
  95. deleteEntity : (project_id, entity_id, entityType, source, userId, callback = (error)->)->
  96. LockManager.runWithLock project_id,
  97. (cb) -> EditorController.deleteEntityWithoutLock project_id, entity_id, entityType, source, userId, cb
  98. (err)->
  99. if err?
  100. logger.err err:err, project_id:project_id, "could not delete entity"
  101. callback(err)
  102. deleteEntityWithoutLock: (project_id, entity_id, entityType, source, userId, callback)->
  103. logger.log {project_id, entity_id, entityType, source}, "start delete process of entity"
  104. Metrics.inc "editor.delete-entity"
  105. ProjectEntityHandler.deleteEntity project_id, entity_id, entityType, userId, (err)->
  106. if err?
  107. logger.err err:err, project_id:project_id, entity_id:entity_id, entityType:entityType, "error deleting entity"
  108. return callback(err)
  109. logger.log project_id:project_id, entity_id:entity_id, entityType:entityType, "telling users entity has been deleted"
  110. EditorRealTimeController.emitToRoom(project_id, 'removeEntity', entity_id, source)
  111. if callback?
  112. callback()
  113. notifyUsersProjectHasBeenDeletedOrRenamed: (project_id, callback)->
  114. EditorRealTimeController.emitToRoom(project_id, 'projectRenamedOrDeletedByExternalSource')
  115. callback()
  116. updateProjectDescription: (project_id, description, callback = ->)->
  117. logger.log project_id:project_id, description:description, "updating project description"
  118. ProjectDetailsHandler.setProjectDescription project_id, description, (err)->
  119. if err?
  120. logger.err err:err, project_id:project_id, description:description, "something went wrong setting the project description"
  121. return callback(err)
  122. EditorRealTimeController.emitToRoom(project_id, 'projectDescriptionUpdated', description)
  123. callback()
  124. deleteProject: (project_id, callback)->
  125. Metrics.inc "editor.delete-project"
  126. logger.log project_id:project_id, "recived message to delete project"
  127. ProjectDeleter.deleteProject project_id, callback
  128. renameEntity: (project_id, entity_id, entityType, newName, userId, callback = (error) ->)->
  129. newName = sanitize.escape(newName)
  130. Metrics.inc "editor.rename-entity"
  131. logger.log entity_id:entity_id, entity_id:entity_id, entity_id:entity_id, "reciving new name for entity for project"
  132. LockManager.runWithLock project_id,
  133. (cb) -> ProjectEntityHandler.renameEntity project_id, entity_id, entityType, newName, userId, cb
  134. (err) ->
  135. if err?
  136. logger.err err:err, project_id:project_id, entity_id:entity_id, entityType:entityType, newName:newName, "error renaming entity"
  137. return callback(err)
  138. if newName.length > 0
  139. EditorRealTimeController.emitToRoom project_id, 'reciveEntityRename', entity_id, newName
  140. callback()
  141. moveEntity: (project_id, entity_id, folder_id, entityType, userId, callback = (error) ->)->
  142. Metrics.inc "editor.move-entity"
  143. LockManager.runWithLock project_id,
  144. (cb) -> ProjectEntityHandler.moveEntity project_id, entity_id, folder_id, entityType, userId, cb
  145. (err) ->
  146. if err?
  147. logger.err err:err, project_id:project_id, entity_id:entity_id, folder_id:folder_id, "error moving entity"
  148. return callback(err)
  149. EditorRealTimeController.emitToRoom project_id, 'reciveEntityMove', entity_id, folder_id
  150. callback()
  151. renameProject: (project_id, newName, callback = (err) ->) ->
  152. ProjectDetailsHandler.renameProject project_id, newName, (err) ->
  153. if err?
  154. logger.err err:err, project_id:project_id, newName:newName, "error renaming project"
  155. return callback(err)
  156. EditorRealTimeController.emitToRoom project_id, 'projectNameUpdated', newName
  157. callback()
  158. setCompiler : (project_id, compiler, callback = (err) ->) ->
  159. ProjectOptionsHandler.setCompiler project_id, compiler, (err) ->
  160. return callback(err) if err?
  161. logger.log compiler:compiler, project_id:project_id, "setting compiler"
  162. EditorRealTimeController.emitToRoom project_id, 'compilerUpdated', compiler
  163. callback()
  164. setSpellCheckLanguage : (project_id, languageCode, callback = (err) ->) ->
  165. ProjectOptionsHandler.setSpellCheckLanguage project_id, languageCode, (err) ->
  166. return callback(err) if err?
  167. logger.log languageCode:languageCode, project_id:project_id, "setting languageCode for spell check"
  168. EditorRealTimeController.emitToRoom project_id, 'spellCheckLanguageUpdated', languageCode
  169. callback()
  170. setPublicAccessLevel : (project_id, newAccessLevel, callback = (err) ->) ->
  171. ProjectDetailsHandler.setPublicAccessLevel project_id, newAccessLevel, (err) ->
  172. return callback(err) if err?
  173. EditorRealTimeController.emitToRoom(
  174. project_id,
  175. 'project:publicAccessLevel:changed',
  176. {newAccessLevel}
  177. )
  178. if newAccessLevel == PublicAccessLevels.TOKEN_BASED
  179. ProjectDetailsHandler.ensureTokensArePresent project_id, (err, tokens) ->
  180. return callback(err) if err?
  181. EditorRealTimeController.emitToRoom(
  182. project_id,
  183. 'project:tokens:changed',
  184. {tokens}
  185. )
  186. callback()
  187. else
  188. callback()
  189. setRootDoc: (project_id, newRootDocID, callback = (err) ->) ->
  190. ProjectEntityHandler.setRootDoc project_id, newRootDocID, (err) ->
  191. return callback(err) if err?
  192. EditorRealTimeController.emitToRoom project_id, 'rootDocUpdated', newRootDocID
  193. callback()
  194. p:
  195. notifyProjectUsersOfNewFolder: (project_id, folder_id, folder, callback = (error)->)->
  196. logger.log project_id:project_id, folder:folder, parentFolder_id:folder_id, "sending newly created folder out to users"
  197. EditorRealTimeController.emitToRoom(project_id, "reciveNewFolder", folder_id, folder)
  198. callback()