UserSessionsManager.coffee 5.8 KB

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