UserSessionsManager.coffee 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. if !user
  41. logger.log {sessionId}, "no user, for some reason"
  42. return callback()
  43. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  44. value = UserSessionsManager._sessionKey sessionId
  45. rclient.multi()
  46. .srem(sessionSetKey, value)
  47. .expire(sessionSetKey, "#{Settings.cookieSessionLength}")
  48. .exec (err, response) ->
  49. if err
  50. logger.err {err, user_id: user._id, sessionSetKey}, "error while removing session key from UserSessions set"
  51. return callback(err)
  52. UserSessionsManager._checkSessions(user, () ->)
  53. callback()
  54. revokeAllUserSessions: (user, retain, callback=(err)->) ->
  55. if !retain
  56. retain = []
  57. if !user
  58. logger.log {}, "no user to revoke sessions for, returning"
  59. return callback(null)
  60. logger.log {user_id: user._id}, "revoking all existing sessions for user"
  61. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  62. rclient.smembers sessionSetKey, (err, sessionKeys) ->
  63. if err
  64. logger.err {err, user_id: user._id, sessionSetKey}, "error getting contents of UserSessions set"
  65. return callback(err)
  66. keysToDelete = _.filter(sessionKeys, (k) => k not in retain)
  67. logger.log {user_id: user._id, count: keysToDelete.length}, "deleting sessions for user"
  68. rclient.multi()
  69. .del(keysToDelete)
  70. .srem(sessionSetKey, keysToDelete)
  71. .exec (err, result) ->
  72. if err
  73. logger.err {err, user_id: user._id, sessionSetKey}, "error revoking all sessions for user"
  74. return callback(err)
  75. callback(null)
  76. touch: (user, callback=(err)->) ->
  77. if !user
  78. logger.log {}, "no user to touch sessions for, returning"
  79. return callback(null)
  80. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  81. rclient.expire sessionSetKey, "#{Settings.cookieSessionLength}", (err, response) ->
  82. if err
  83. logger.err {err, user_id: user._id}, "error while updating ttl on UserSessions set"
  84. return callback(err)
  85. callback(null)
  86. _checkSessions: (user, callback=(err)->) ->
  87. if !user
  88. logger.log {}, "no user, returning"
  89. return callback(null)
  90. logger.log {user_id: user._id}, "checking sessions for user"
  91. sessionSetKey = UserSessionsManager._sessionSetKey(user)
  92. rclient.smembers sessionSetKey, (err, sessionKeys) ->
  93. if err
  94. logger.err {err, user_id: user._id, sessionSetKey}, "error getting contents of UserSessions set"
  95. return callback(err)
  96. logger.log {user_id: user._id, count: sessionKeys.length}, "checking sessions for user"
  97. Async.series(
  98. sessionKeys.map(
  99. (key) ->
  100. (next) ->
  101. rclient.get key, (err, val) ->
  102. if err
  103. return next(err)
  104. if val == null
  105. logger.log {user_id: user._id, key}, ">> removing key from UserSessions set"
  106. rclient.srem sessionSetKey, key, (err, result) ->
  107. if err
  108. return next(err)
  109. return next(null)
  110. else
  111. next()
  112. )
  113. , (err, results) ->
  114. logger.log {user_id: user._id}, "done checking sessions for user"
  115. return callback(err)
  116. )