EditorController.coffee 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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, callback = (error, doc)->)->
  20. LockManager.getLock project_id, (err)->
  21. if err?
  22. logger.err err:err, project_id:project_id, source:source, "could not get lock to addDoc"
  23. return callback(err)
  24. EditorController.addDocWithoutLock project_id, folder_id, docName, docLines, source, (error, doc)->
  25. LockManager.releaseLock project_id, ->
  26. callback(error, doc)
  27. addDocWithoutLock: (project_id, folder_id, docName, docLines, source, 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, (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, callback = (error, file)->)->
  38. LockManager.getLock project_id, (err)->
  39. if err?
  40. logger.err err:err, project_id:project_id, source:source, "could not get lock to addFile"
  41. return callback(err)
  42. EditorController.addFileWithoutLock project_id, folder_id, fileName, path, source, (error, file)->
  43. LockManager.releaseLock project_id, ->
  44. callback(error, file)
  45. addFileWithoutLock: (project_id, folder_id, fileName, path, source, 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, (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. replaceFile: (project_id, file_id, fsPath, source, callback = (error) ->)->
  56. ProjectEntityHandler.replaceFile project_id, file_id, fsPath, callback
  57. addFolder : (project_id, folder_id, folderName, source, callback = (error, folder)->)->
  58. LockManager.getLock project_id, (err)->
  59. if err?
  60. logger.err err:err, project_id:project_id, source:source, "could not get lock to addFolder"
  61. return callback(err)
  62. EditorController.addFolderWithoutLock project_id, folder_id, folderName, source, (error, folder)->
  63. LockManager.releaseLock project_id, ->
  64. callback(error, 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)->
  76. LockManager.getLock project_id, (err)->
  77. if err?
  78. logger.err err:err, project_id:project_id, "could not get lock to mkdirp"
  79. return callback(err)
  80. EditorController.mkdirpWithoutLock project_id, path, (err, newFolders, lastFolder)->
  81. LockManager.releaseLock project_id, ->
  82. callback(err, newFolders, lastFolder)
  83. mkdirpWithoutLock: (project_id, path, callback)->
  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, callback)->
  96. LockManager.getLock project_id, (err)->
  97. if err?
  98. logger.err err:err, project_id:project_id, "could not get lock to deleteEntity"
  99. return callback(err)
  100. EditorController.deleteEntityWithoutLock project_id, entity_id, entityType, source, (err)->
  101. LockManager.releaseLock project_id, ()->
  102. callback(err)
  103. deleteEntityWithoutLock: (project_id, entity_id, entityType, source, callback)->
  104. logger.log {project_id, entity_id, entityType, source}, "start delete process of entity"
  105. Metrics.inc "editor.delete-entity"
  106. ProjectEntityHandler.deleteEntity project_id, entity_id, entityType, (err)->
  107. if err?
  108. logger.err err:err, project_id:project_id, entity_id:entity_id, entityType:entityType, "error deleting entity"
  109. return callback(err)
  110. logger.log project_id:project_id, entity_id:entity_id, entityType:entityType, "telling users entity has been deleted"
  111. EditorRealTimeController.emitToRoom(project_id, 'removeEntity', entity_id, source)
  112. if callback?
  113. callback()
  114. getListOfDocPaths: (project_id, callback)->
  115. ProjectEntityHandler.getAllDocs project_id, (err, docs)->
  116. docList = _.map docs, (doc, path)->
  117. return {_id:doc._id, path:path.substring(1)}
  118. callback(null, docList)
  119. notifyUsersProjectHasBeenDeletedOrRenamed: (project_id, callback)->
  120. EditorRealTimeController.emitToRoom(project_id, 'projectRenamedOrDeletedByExternalSource')
  121. callback()
  122. updateProjectDescription: (project_id, description, callback = ->)->
  123. logger.log project_id:project_id, description:description, "updating project description"
  124. ProjectDetailsHandler.setProjectDescription project_id, description, (err)->
  125. if err?
  126. logger.err err:err, project_id:project_id, description:description, "something went wrong setting the project description"
  127. return callback(err)
  128. EditorRealTimeController.emitToRoom(project_id, 'projectDescriptionUpdated', description)
  129. callback()
  130. deleteProject: (project_id, callback)->
  131. Metrics.inc "editor.delete-project"
  132. logger.log project_id:project_id, "recived message to delete project"
  133. ProjectDeleter.deleteProject project_id, callback
  134. renameEntity: (project_id, entity_id, entityType, newName, userId, callback)->
  135. newName = sanitize.escape(newName)
  136. Metrics.inc "editor.rename-entity"
  137. logger.log entity_id:entity_id, entity_id:entity_id, entity_id:entity_id, "reciving new name for entity for project"
  138. ProjectEntityHandler.renameEntity project_id, entity_id, entityType, newName, userId, (err) ->
  139. if err?
  140. logger.err err:err, project_id:project_id, entity_id:entity_id, entityType:entityType, newName:newName, "error renaming entity"
  141. return callback(err)
  142. if newName.length > 0
  143. EditorRealTimeController.emitToRoom project_id, 'reciveEntityRename', entity_id, newName
  144. callback?()
  145. moveEntity: (project_id, entity_id, folder_id, entityType, userId, callback)->
  146. Metrics.inc "editor.move-entity"
  147. LockManager.getLock project_id, (err)->
  148. if err?
  149. logger.err err:err, project_id:project_id, "could not get lock for move entity"
  150. return callback(err)
  151. ProjectEntityHandler.moveEntity project_id, entity_id, folder_id, entityType, userId, =>
  152. if err?
  153. logger.err err:err, project_id:project_id, entity_id:entity_id, folder_id:folder_id, "error moving entity"
  154. return callback(err)
  155. LockManager.releaseLock project_id, ->
  156. EditorRealTimeController.emitToRoom project_id, 'reciveEntityMove', entity_id, folder_id
  157. callback?()
  158. renameProject: (project_id, newName, callback = (err) ->) ->
  159. ProjectDetailsHandler.renameProject project_id, newName, (err) ->
  160. if err?
  161. logger.err err:err, project_id:project_id, newName:newName, "error renaming project"
  162. return callback(err)
  163. EditorRealTimeController.emitToRoom project_id, 'projectNameUpdated', newName
  164. callback()
  165. setCompiler : (project_id, compiler, callback = (err) ->) ->
  166. ProjectOptionsHandler.setCompiler project_id, compiler, (err) ->
  167. return callback(err) if err?
  168. logger.log compiler:compiler, project_id:project_id, "setting compiler"
  169. EditorRealTimeController.emitToRoom project_id, 'compilerUpdated', compiler
  170. callback()
  171. setSpellCheckLanguage : (project_id, languageCode, callback = (err) ->) ->
  172. ProjectOptionsHandler.setSpellCheckLanguage project_id, languageCode, (err) ->
  173. return callback(err) if err?
  174. logger.log languageCode:languageCode, project_id:project_id, "setting languageCode for spell check"
  175. EditorRealTimeController.emitToRoom project_id, 'spellCheckLanguageUpdated', languageCode
  176. callback()
  177. setPublicAccessLevel : (project_id, newAccessLevel, callback = (err) ->) ->
  178. ProjectDetailsHandler.setPublicAccessLevel project_id, newAccessLevel, (err) ->
  179. return callback(err) if err?
  180. EditorRealTimeController.emitToRoom(
  181. project_id,
  182. 'project:publicAccessLevel:changed',
  183. {newAccessLevel}
  184. )
  185. if newAccessLevel == PublicAccessLevels.TOKEN_BASED
  186. ProjectDetailsHandler.ensureTokensArePresent project_id, (err, tokens) ->
  187. return callback(err) if err?
  188. EditorRealTimeController.emitToRoom(
  189. project_id,
  190. 'project:tokens:changed',
  191. {tokens}
  192. )
  193. callback()
  194. else
  195. callback()
  196. setRootDoc: (project_id, newRootDocID, callback = (err) ->) ->
  197. ProjectEntityHandler.setRootDoc project_id, newRootDocID, (err) ->
  198. return callback(err) if err?
  199. EditorRealTimeController.emitToRoom project_id, 'rootDocUpdated', newRootDocID
  200. callback()
  201. p:
  202. notifyProjectUsersOfNewFolder: (project_id, folder_id, folder, callback = (error)->)->
  203. logger.log project_id:project_id, folder:folder, parentFolder_id:folder_id, "sending newly created folder out to users"
  204. EditorRealTimeController.emitToRoom(project_id, "reciveNewFolder", folder_id, folder)
  205. callback()