WebsocketController.coffee 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. logger = require "logger-sharelatex"
  2. WebApiManager = require "./WebApiManager"
  3. AuthorizationManager = require "./AuthorizationManager"
  4. DocumentUpdaterManager = require "./DocumentUpdaterManager"
  5. module.exports = WebsocketController =
  6. # If the protocol version changes when the client reconnects,
  7. # it will force a full refresh of the page. Useful for non-backwards
  8. # compatible protocol changes. Use only in extreme need.
  9. PROTOCOL_VERSION: 2
  10. joinProject: (client, user, project_id, callback = (error, project, privilegeLevel, protocolVersion) ->) ->
  11. user_id = user?._id
  12. logger.log {user_id, project_id, client_id: client.id}, "user joining project"
  13. WebApiManager.joinProject project_id, user_id, (error, project, privilegeLevel) ->
  14. return callback(error) if error?
  15. if !privilegeLevel or privilegeLevel == ""
  16. err = new Error("not authorized")
  17. logger.error {err, project_id, user_id, client_id: client.id}, "user is not authorized to join project"
  18. return callback(err)
  19. client.join project_id
  20. client.set("privilege_level", privilegeLevel)
  21. client.set("user_id", user_id)
  22. client.set("project_id", project_id)
  23. client.set("owner_id", project?.owner?._id)
  24. client.set("first_name", user?.first_name)
  25. client.set("last_name", user?.last_name)
  26. client.set("email", user?.email)
  27. client.set("connected_time", new Date())
  28. client.set("signup_date", user?.signUpDate)
  29. client.set("login_count", user?.loginCount)
  30. callback null, project, privilegeLevel, WebsocketController.PROTOCOL_VERSION
  31. joinDoc: (client, doc_id, fromVersion = -1, callback = (error, doclines, version, ops) ->) ->
  32. WebsocketController._getClientData client, (error, {client_id, user_id, project_id}) ->
  33. logger.log {user_id, project_id, doc_id, fromVersion, client_id}, "client joining doc"
  34. AuthorizationManager.assertClientCanViewProject client, (error) ->
  35. return callback(error) if error?
  36. client.get "project_id", (error, project_id) ->
  37. return callback(error) if error?
  38. return callback(new Error("no project_id found on client")) if !project_id?
  39. DocumentUpdaterManager.getDocument project_id, doc_id, fromVersion, (error, lines, version, ops) ->
  40. return callback(error) if error?
  41. # Encode any binary bits of data so it can go via WebSockets
  42. # See http://ecmanaut.blogspot.co.uk/2006/07/encoding-decoding-utf8-in-javascript.html
  43. escapedLines = []
  44. for line in lines
  45. try
  46. line = unescape(encodeURIComponent(line))
  47. catch err
  48. logger.err {err, project_id, doc_id, fromVersion, line, client_id: client.id}, "error encoding line uri component"
  49. return callback(err)
  50. escapedLines.push line
  51. client.join(doc_id)
  52. callback null, escapedLines, version, ops
  53. leaveDoc: (client, doc_id, callback = (error) ->) ->
  54. WebsocketController._getClientData client, (error, {client_id, user_id, project_id}) ->
  55. logger.log {user_id, project_id, doc_id, client_id}, "client leaving doc"
  56. client.leave doc_id
  57. callback()
  58. # Only used in logging.
  59. _getClientData: (client, callback = (error, data) ->) ->
  60. client.get "user_id", (error, user_id) ->
  61. client.get "project_id", (error, project_id) ->
  62. callback null, {client_id: client.id, project_id, user_id}