UserSessionsManager.coffee 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. Settings = require('settings-sharelatex')
  2. redis = require('redis-sharelatex')
  3. logger = require("logger-sharelatex")
  4. Async = require('async')
  5. _ = require('underscore')
  6. rclient = redis.createClient(Settings.redis.web)
  7. module.exports = UserSessionsManager =
  8. _sessionSetKey: (user) ->
  9. return "UserSessions:#{user._id}"
  10. # mimic the key used by the express sessions
  11. _sessionKey: (sessionId) ->
  12. return "sess:#{sessionId}"
  13. trackSession: (user, sessionId, callback=(err)-> ) ->
  14. if !user?
  15. logger.log {sessionId}, "no user to track, returning"
  16. return callback(null)
  17. if !sessionId?
  18. logger.log {user_id: user._id}, "no sessionId to track, returning"
  19. return callback(null)
  20. logger.log {user_id: user._id, sessionId}, "onLogin handler"
  21. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  22. value = UserSessionsManager._sessionKey sessionId
  23. rclient.multi()
  24. .sadd(sessionSetKey, value)
  25. .expire(sessionSetKey, "#{Settings.cookieSessionLength}")
  26. .exec (err, response) ->
  27. if err?
  28. logger.err {err, user_id: user._id, sessionSetKey}, "error while adding session key to UserSessions set"
  29. return callback(err)
  30. UserSessionsManager._checkSessions(user, () ->)
  31. callback()
  32. untrackSession: (user, sessionId, callback=(err)-> ) ->
  33. if !user?
  34. logger.log {sessionId}, "no user to untrack, returning"
  35. return callback(null)
  36. if !sessionId?
  37. logger.log {user_id: user._id}, "no sessionId to untrack, returning"
  38. return callback(null)
  39. logger.log {user_id: user._id, sessionId}, "onLogout handler"
  40. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  41. value = UserSessionsManager._sessionKey sessionId
  42. rclient.multi()
  43. .srem(sessionSetKey, value)
  44. .expire(sessionSetKey, "#{Settings.cookieSessionLength}")
  45. .exec (err, response) ->
  46. if err?
  47. logger.err {err, user_id: user._id, sessionSetKey}, "error while removing session key from UserSessions set"
  48. return callback(err)
  49. UserSessionsManager._checkSessions(user, () ->)
  50. callback()
  51. revokeAllUserSessions: (user, retain, callback=(err)->) ->
  52. if !retain
  53. retain = []
  54. retain = retain.map((i) -> UserSessionsManager._sessionKey(i))
  55. if !user
  56. logger.log {}, "no user to revoke sessions for, returning"
  57. return callback(null)
  58. logger.log {user_id: user._id}, "revoking all existing sessions for user"
  59. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  60. rclient.smembers sessionSetKey, (err, sessionKeys) ->
  61. if err?
  62. logger.err {err, user_id: user._id, sessionSetKey}, "error getting contents of UserSessions set"
  63. return callback(err)
  64. keysToDelete = _.filter(sessionKeys, (k) -> k not in retain)
  65. if keysToDelete.length == 0
  66. logger.log {user_id: user._id}, "no sessions in UserSessions set to delete, returning"
  67. return callback(null)
  68. logger.log {user_id: user._id, count: keysToDelete.length}, "deleting sessions for user"
  69. rclient.multi()
  70. .del(keysToDelete)
  71. .srem(sessionSetKey, keysToDelete)
  72. .exec (err, result) ->
  73. if err?
  74. logger.err {err, user_id: user._id, sessionSetKey}, "error revoking all sessions for user"
  75. return callback(err)
  76. callback(null)
  77. touch: (user, callback=(err)->) ->
  78. if !user
  79. logger.log {}, "no user to touch sessions for, returning"
  80. return callback(null)
  81. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  82. rclient.expire sessionSetKey, "#{Settings.cookieSessionLength}", (err, response) ->
  83. if err?
  84. logger.err {err, user_id: user._id}, "error while updating ttl on UserSessions set"
  85. return callback(err)
  86. callback(null)
  87. _checkSessions: (user, callback=(err)->) ->
  88. if !user
  89. logger.log {}, "no user, returning"
  90. return callback(null)
  91. logger.log {user_id: user._id}, "checking sessions for user"
  92. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  93. rclient.smembers sessionSetKey, (err, sessionKeys) ->
  94. if err?
  95. logger.err {err, user_id: user._id, sessionSetKey}, "error getting contents of UserSessions set"
  96. return callback(err)
  97. logger.log {user_id: user._id, count: sessionKeys.length}, "checking sessions for user"
  98. Async.series(
  99. sessionKeys.map(
  100. (key) ->
  101. (next) ->
  102. rclient.get key, (err, val) ->
  103. if err?
  104. return next(err)
  105. if !val?
  106. logger.log {user_id: user._id, key}, ">> removing key from UserSessions set"
  107. rclient.srem sessionSetKey, key, (err, result) ->
  108. if err?
  109. return next(err)
  110. return next(null)
  111. else
  112. next()
  113. )
  114. , (err, results) ->
  115. logger.log {user_id: user._id}, "done checking sessions for user"
  116. return callback(err)
  117. )