mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #152 from overleaf/jpa-vendor-cookie
[misc] vendor a patched session.socket.io middleware
This commit is contained in:
commit
cfe37dcbb5
6 changed files with 217 additions and 7 deletions
|
@ -17,7 +17,7 @@ if Settings.sentry?.dsn?
|
||||||
sessionRedisClient = redis.createClient(Settings.redis.websessions)
|
sessionRedisClient = redis.createClient(Settings.redis.websessions)
|
||||||
|
|
||||||
RedisStore = require('connect-redis')(session)
|
RedisStore = require('connect-redis')(session)
|
||||||
SessionSockets = require('session.socket.io')
|
SessionSockets = require('./app/js/SessionSockets')
|
||||||
CookieParser = require("cookie-parser")
|
CookieParser = require("cookie-parser")
|
||||||
|
|
||||||
DrainManager = require("./app/js/DrainManager")
|
DrainManager = require("./app/js/DrainManager")
|
||||||
|
|
23
services/real-time/app/coffee/SessionSockets.coffee
Normal file
23
services/real-time/app/coffee/SessionSockets.coffee
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{EventEmitter} = require('events')
|
||||||
|
|
||||||
|
module.exports = (io, sessionStore, cookieParser, cookieName) ->
|
||||||
|
missingSessionError = new Error('could not look up session by key')
|
||||||
|
|
||||||
|
sessionSockets = new EventEmitter()
|
||||||
|
next = (error, socket, session) ->
|
||||||
|
sessionSockets.emit 'connection', error, socket, session
|
||||||
|
|
||||||
|
io.on 'connection', (socket) ->
|
||||||
|
req = socket.handshake
|
||||||
|
cookieParser req, {}, () ->
|
||||||
|
sessionId = req.signedCookies and req.signedCookies[cookieName]
|
||||||
|
if not sessionId
|
||||||
|
return next(missingSessionError, socket)
|
||||||
|
sessionStore.get sessionId, (error, session) ->
|
||||||
|
if error
|
||||||
|
return next(error, socket)
|
||||||
|
if not session
|
||||||
|
return next(missingSessionError, socket)
|
||||||
|
next(null, socket, session)
|
||||||
|
|
||||||
|
return sessionSockets
|
5
services/real-time/package-lock.json
generated
5
services/real-time/package-lock.json
generated
|
@ -2165,11 +2165,6 @@
|
||||||
"send": "0.16.2"
|
"send": "0.16.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"session.socket.io": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/session.socket.io/-/session.socket.io-0.1.6.tgz",
|
|
||||||
"integrity": "sha1-vh7sJAYJWgP4dw6ozN5s8SYBxdA="
|
|
||||||
},
|
|
||||||
"setprototypeof": {
|
"setprototypeof": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
"metrics-sharelatex": "^2.6.2",
|
"metrics-sharelatex": "^2.6.2",
|
||||||
"redis-sharelatex": "^1.0.12",
|
"redis-sharelatex": "^1.0.12",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
"session.socket.io": "^0.1.6",
|
|
||||||
"settings-sharelatex": "^1.1.0",
|
"settings-sharelatex": "^1.1.0",
|
||||||
"socket.io": "0.9.19",
|
"socket.io": "0.9.19",
|
||||||
"socket.io-client": "^0.9.16"
|
"socket.io-client": "^0.9.16"
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
RealTimeClient = require("./helpers/RealTimeClient")
|
||||||
|
Settings = require("settings-sharelatex")
|
||||||
|
{expect} = require('chai')
|
||||||
|
|
||||||
|
describe 'SessionSockets', ->
|
||||||
|
before ->
|
||||||
|
@checkSocket = (fn) ->
|
||||||
|
client = RealTimeClient.connect()
|
||||||
|
client.on 'connectionAccepted', fn
|
||||||
|
client.on 'connectionRejected', fn
|
||||||
|
return null
|
||||||
|
|
||||||
|
describe 'without cookies', ->
|
||||||
|
before ->
|
||||||
|
RealTimeClient.cookie = null
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('invalid session')
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a different cookie', ->
|
||||||
|
before ->
|
||||||
|
RealTimeClient.cookie = "some.key=someValue"
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('invalid session')
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with an invalid cookie', ->
|
||||||
|
before (done) ->
|
||||||
|
RealTimeClient.setSession {}, (error) ->
|
||||||
|
return done(error) if error
|
||||||
|
RealTimeClient.cookie = "#{Settings.cookieName}=#{
|
||||||
|
RealTimeClient.cookie.slice(17, 49)
|
||||||
|
}"
|
||||||
|
done()
|
||||||
|
return null
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('invalid session')
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a valid cookie and no matching session', ->
|
||||||
|
before ->
|
||||||
|
RealTimeClient.cookie = "#{Settings.cookieName}=unknownId"
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('invalid session')
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a valid cookie and a matching session', ->
|
||||||
|
before (done) ->
|
||||||
|
RealTimeClient.setSession({}, done)
|
||||||
|
return null
|
||||||
|
|
||||||
|
it 'should not return an error', (done) ->
|
||||||
|
@checkSocket (error) ->
|
||||||
|
expect(error).to.not.exist
|
||||||
|
done()
|
126
services/real-time/test/unit/coffee/SessionSocketsTests.coffee
Normal file
126
services/real-time/test/unit/coffee/SessionSocketsTests.coffee
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{EventEmitter} = require('events')
|
||||||
|
{expect} = require('chai')
|
||||||
|
SandboxedModule = require('sandboxed-module')
|
||||||
|
modulePath = '../../../app/js/SessionSockets'
|
||||||
|
sinon = require('sinon')
|
||||||
|
|
||||||
|
describe 'SessionSockets', ->
|
||||||
|
before ->
|
||||||
|
@SessionSocketsModule = SandboxedModule.require modulePath
|
||||||
|
@io = new EventEmitter()
|
||||||
|
@id1 = Math.random().toString()
|
||||||
|
@id2 = Math.random().toString()
|
||||||
|
redisResponses =
|
||||||
|
error: [new Error('Redis: something went wrong'), null]
|
||||||
|
unknownId: [null, null]
|
||||||
|
redisResponses[@id1] = [null, {user: {_id: '123'}}]
|
||||||
|
redisResponses[@id2] = [null, {user: {_id: 'abc'}}]
|
||||||
|
|
||||||
|
@sessionStore =
|
||||||
|
get: sinon.stub().callsFake (id, fn) ->
|
||||||
|
fn.apply(null, redisResponses[id])
|
||||||
|
@cookieParser = (req, res, next) ->
|
||||||
|
req.signedCookies = req._signedCookies
|
||||||
|
next()
|
||||||
|
@SessionSockets = @SessionSocketsModule(@io, @sessionStore, @cookieParser, 'ol.sid')
|
||||||
|
@checkSocket = (socket, fn) =>
|
||||||
|
@SessionSockets.once('connection', fn)
|
||||||
|
@io.emit('connection', socket)
|
||||||
|
|
||||||
|
describe 'without cookies', ->
|
||||||
|
before ->
|
||||||
|
@socket = {handshake: {}}
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket @socket, (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('could not look up session by key')
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should not query redis', (done) ->
|
||||||
|
@checkSocket @socket, () =>
|
||||||
|
expect(@sessionStore.get.called).to.equal(false)
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a different cookie', ->
|
||||||
|
before ->
|
||||||
|
@socket = {handshake: {_signedCookies: {other: 1}}}
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket @socket, (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('could not look up session by key')
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should not query redis', (done) ->
|
||||||
|
@checkSocket @socket, () =>
|
||||||
|
expect(@sessionStore.get.called).to.equal(false)
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a valid cookie and a failing session lookup', ->
|
||||||
|
before ->
|
||||||
|
@socket = {handshake: {_signedCookies: {'ol.sid': 'error'}}}
|
||||||
|
|
||||||
|
it 'should query redis', (done) ->
|
||||||
|
@checkSocket @socket, () =>
|
||||||
|
expect(@sessionStore.get.called).to.equal(true)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should return a redis error', (done) ->
|
||||||
|
@checkSocket @socket, (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('Redis: something went wrong')
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a valid cookie and no matching session', ->
|
||||||
|
before ->
|
||||||
|
@socket = {handshake: {_signedCookies: {'ol.sid': 'unknownId'}}}
|
||||||
|
|
||||||
|
it 'should query redis', (done) ->
|
||||||
|
@checkSocket @socket, () =>
|
||||||
|
expect(@sessionStore.get.called).to.equal(true)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should return a lookup error', (done) ->
|
||||||
|
@checkSocket @socket, (error) ->
|
||||||
|
expect(error).to.exist
|
||||||
|
expect(error.message).to.equal('could not look up session by key')
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a valid cookie and a matching session', ->
|
||||||
|
before ->
|
||||||
|
@socket = {handshake: {_signedCookies: {'ol.sid': @id1}}}
|
||||||
|
|
||||||
|
it 'should query redis', (done) ->
|
||||||
|
@checkSocket @socket, () =>
|
||||||
|
expect(@sessionStore.get.called).to.equal(true)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should not return an error', (done) ->
|
||||||
|
@checkSocket @socket, (error) ->
|
||||||
|
expect(error).to.not.exist
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should return the session', (done) ->
|
||||||
|
@checkSocket @socket, (error, s, session) ->
|
||||||
|
expect(session).to.deep.equal({user: {_id: '123'}})
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'with a different valid cookie and matching session', ->
|
||||||
|
before ->
|
||||||
|
@socket = {handshake: {_signedCookies: {'ol.sid': @id2}}}
|
||||||
|
|
||||||
|
it 'should query redis', (done) ->
|
||||||
|
@checkSocket @socket, () =>
|
||||||
|
expect(@sessionStore.get.called).to.equal(true)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should not return an error', (done) ->
|
||||||
|
@checkSocket @socket, (error) ->
|
||||||
|
expect(error).to.not.exist
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should return the other session', (done) ->
|
||||||
|
@checkSocket @socket, (error, s, session) ->
|
||||||
|
expect(session).to.deep.equal({user: {_id: 'abc'}})
|
||||||
|
done()
|
Loading…
Reference in a new issue