SessionSockets.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import metrics from '@overleaf/metrics'
  2. import OError from '@overleaf/o-error'
  3. import { EventEmitter } from 'node:events'
  4. import Errors from './Errors.js'
  5. const { MissingSessionError } = Errors
  6. export default function (io, sessionStore, cookieParser, cookieName) {
  7. const missingSessionError = new MissingSessionError()
  8. const sessionSockets = new EventEmitter()
  9. function next(error, socket, session) {
  10. sessionSockets.emit('connection', error, socket, session)
  11. }
  12. io.on('connection', function (socket) {
  13. const req = socket.handshake
  14. cookieParser(req, {}, function () {
  15. const sessionId = req.signedCookies && req.signedCookies[cookieName]
  16. if (!sessionId) {
  17. metrics.inc('session.cookie', 1, {
  18. // the cookie-parser middleware sets the signed cookie to false if the
  19. // signature is invalid, so we can use this to detect bad signatures
  20. status: sessionId === false ? 'bad-signature' : 'none',
  21. })
  22. return next(missingSessionError, socket)
  23. }
  24. sessionStore.get(sessionId, function (error, session) {
  25. if (error) {
  26. metrics.inc('session.cookie', 1, { status: 'error' })
  27. OError.tag(error, 'error getting session from sessionStore', {
  28. sessionId,
  29. })
  30. return next(error, socket)
  31. }
  32. if (!session) {
  33. metrics.inc('session.cookie', 1, { status: 'missing' })
  34. return next(missingSessionError, socket)
  35. }
  36. metrics.inc('session.cookie', 1, { status: 'signed' })
  37. next(null, socket, session)
  38. })
  39. })
  40. })
  41. return sessionSockets
  42. }